From c33b8c14fe25ea5117ef054270528ddf107b47e0 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Wed, 3 Jul 2019 12:36:07 +0100 Subject: [PATCH 01/13] Rename db to database to conform with other drivers --- src/driver.js | 12 +++---- src/internal/bolt-protocol-util.js | 8 ++--- src/internal/bolt-protocol-v1.js | 19 +++++----- src/internal/bolt-protocol-v3.js | 12 +++---- src/internal/bolt-protocol-v4.js | 8 ++--- src/internal/connection-holder.js | 18 ++++++---- src/internal/connection-providers.js | 8 ++--- src/internal/connectivity-verifier.js | 8 ++--- src/internal/http/http-session.js | 10 ++++-- src/internal/request-message.js | 20 +++++------ src/session.js | 11 +++--- src/transaction.js | 4 +-- test/bolt-v4.test.js | 36 +++++++++---------- test/internal/bolt-protocol-v1.test.js | 12 +++---- test/internal/bolt-protocol-v3.test.js | 12 +++---- test/internal/bolt-protocol-v4.test.js | 12 +++---- test/internal/connection-holder.test.js | 22 +++++++----- .../node/direct.driver.boltkit.test.js | 2 +- types/driver.d.ts | 4 +-- 19 files changed, 128 insertions(+), 110 deletions(-) diff --git a/src/driver.js b/src/driver.js index e1be7ab6d..066f41fb4 100644 --- a/src/driver.js +++ b/src/driver.js @@ -111,13 +111,13 @@ class Driver { /** * Verifies connectivity of this driver by trying to open a connection with the provided driver options. - * @param {string} [db=''] the target database to verify connectivity for. + * @param {string} [database=''] the target database to verify connectivity for. * @returns {Promise} promise resolved with server info or rejected with error. */ - verifyConnectivity ({ db = '' } = {}) { + verifyConnectivity ({ database = '' } = {}) { const connectionProvider = this._getOrCreateConnectionProvider() const connectivityVerifier = new ConnectivityVerifier(connectionProvider) - return connectivityVerifier.verify({ db }) + return connectivityVerifier.verify({ database }) } /** @@ -194,13 +194,13 @@ class Driver { * @param {string} [defaultAccessMode=WRITE] the access mode of this session, allowed values are {@link READ} and {@link WRITE}. * @param {string|string[]} [bookmarks=null] the initial reference or references to some previous * transactions. Value is optional and absence indicates that that the bookmarks do not exist or are unknown. - * @param {string} [db=''] the database this session will connect to. + * @param {string} [database=''] the database this session will connect to. * @return {Session} new session. */ session ({ defaultAccessMode = WRITE, bookmarks: bookmarkOrBookmarks, - db = '' + database = '' } = {}) { const sessionMode = Driver._validateSessionMode(defaultAccessMode) const connectionProvider = this._getOrCreateConnectionProvider() @@ -209,7 +209,7 @@ class Driver { : Bookmark.empty() return new Session({ mode: sessionMode, - db, + database, connectionProvider, bookmark, config: this._config diff --git a/src/internal/bolt-protocol-util.js b/src/internal/bolt-protocol-util.js index 154f34826..07d51cec7 100644 --- a/src/internal/bolt-protocol-util.js +++ b/src/internal/bolt-protocol-util.js @@ -39,12 +39,12 @@ function assertTxConfigIsEmpty (txConfig, connection, observer) { /** * Asserts that the passed-in database name is empty. - * @param {string} db + * @param {string} database * @param {Connection} connection * @param {StreamObserver} observer */ -function assertDbIsEmpty (db, connection, observer) { - if (db) { +function assertDatabaseIsEmpty (database, connection, observer) { + if (database) { const error = newError( 'Driver is connected to the database that does not support multiple databases. ' + 'Please upgrade to neo4j 4.0.0 or later in order to use this functionality' @@ -57,4 +57,4 @@ function assertDbIsEmpty (db, connection, observer) { } } -export { assertDbIsEmpty, assertTxConfigIsEmpty } +export { assertDatabaseIsEmpty, assertTxConfigIsEmpty } diff --git a/src/internal/bolt-protocol-v1.js b/src/internal/bolt-protocol-v1.js index 3a2cfb328..db23b231b 100644 --- a/src/internal/bolt-protocol-v1.js +++ b/src/internal/bolt-protocol-v1.js @@ -21,7 +21,10 @@ import * as v1 from './packstream-v1' import Bookmark from './bookmark' import TxConfig from './tx-config' import { ACCESS_MODE_WRITE } from './constants' -import { assertDbIsEmpty, assertTxConfigIsEmpty } from './bolt-protocol-util' +import { + assertDatabaseIsEmpty, + assertTxConfigIsEmpty +} from './bolt-protocol-util' export default class BoltProtocol { /** @@ -81,12 +84,12 @@ export default class BoltProtocol { * @param {StreamObserver} observer the response observer. * @param {Bookmark} bookmark the bookmark. * @param {TxConfig} txConfig the configuration. - * @param {string} db the target database name. + * @param {string} database the target database name. * @param {string} mode the access mode. */ - beginTransaction (observer, { bookmark, txConfig, db, mode }) { + beginTransaction (observer, { bookmark, txConfig, database, mode }) { assertTxConfigIsEmpty(txConfig, this._connection, observer) - assertDbIsEmpty(db, this._connection, observer) + assertDatabaseIsEmpty(database, this._connection, observer) const runMessage = RequestMessage.run( 'BEGIN', @@ -133,14 +136,14 @@ export default class BoltProtocol { * @param {StreamObserver} observer the response observer. * @param {Bookmark} bookmark the bookmark. * @param {TxConfig} txConfig the auto-commit transaction configuration. - * @param {string} db the target database name. + * @param {string} database the target database name. * @param {string} mode the access mode. */ - run (statement, parameters, observer, { bookmark, txConfig, db, mode }) { + run (statement, parameters, observer, { bookmark, txConfig, database, mode }) { // bookmark and mode are ignored in this version of the protocol assertTxConfigIsEmpty(txConfig, this._connection, observer) - // passing in a db name on this protocol version throws an error - assertDbIsEmpty(db, this._connection, observer) + // passing in a database name on this protocol version throws an error + assertDatabaseIsEmpty(database, this._connection, observer) const runMessage = RequestMessage.run(statement, parameters) const pullAllMessage = RequestMessage.pullAll() diff --git a/src/internal/bolt-protocol-v3.js b/src/internal/bolt-protocol-v3.js index bad399f09..5d0394f01 100644 --- a/src/internal/bolt-protocol-v3.js +++ b/src/internal/bolt-protocol-v3.js @@ -18,7 +18,7 @@ */ import BoltProtocolV2 from './bolt-protocol-v2' import RequestMessage from './request-message' -import { assertDbIsEmpty } from './bolt-protocol-util' +import { assertDatabaseIsEmpty } from './bolt-protocol-util' export default class BoltProtocol extends BoltProtocolV2 { transformMetadata (metadata) { @@ -48,8 +48,8 @@ export default class BoltProtocol extends BoltProtocolV2 { this._connection.write(message, observer, true) } - beginTransaction (observer, { bookmark, txConfig, db, mode }) { - assertDbIsEmpty(db, this._connection, observer) + beginTransaction (observer, { bookmark, txConfig, database, mode }) { + assertDatabaseIsEmpty(database, this._connection, observer) prepareToHandleSingleResponse(observer) const message = RequestMessage.begin({ bookmark, txConfig, mode }) this._connection.write(message, observer, true) @@ -67,9 +67,9 @@ export default class BoltProtocol extends BoltProtocolV2 { this._connection.write(message, observer, true) } - run (statement, parameters, observer, { bookmark, txConfig, db, mode }) { - // passing in a db name on this protocol version throws an error - assertDbIsEmpty(db, this._connection, observer) + run (statement, parameters, observer, { bookmark, txConfig, database, mode }) { + // passing in a database name on this protocol version throws an error + assertDatabaseIsEmpty(database, this._connection, observer) const runMessage = RequestMessage.runWithMetadata(statement, parameters, { bookmark, diff --git a/src/internal/bolt-protocol-v4.js b/src/internal/bolt-protocol-v4.js index f5534a8e7..ca75ada8a 100644 --- a/src/internal/bolt-protocol-v4.js +++ b/src/internal/bolt-protocol-v4.js @@ -20,16 +20,16 @@ import BoltProtocolV3 from './bolt-protocol-v3' import RequestMessage from './request-message' export default class BoltProtocol extends BoltProtocolV3 { - beginTransaction (observer, { bookmark, txConfig, db, mode }) { - const message = RequestMessage.begin({ bookmark, txConfig, db, mode }) + beginTransaction (observer, { bookmark, txConfig, database, mode }) { + const message = RequestMessage.begin({ bookmark, txConfig, database, mode }) this._connection.write(message, observer, true) } - run (statement, parameters, observer, { bookmark, txConfig, db, mode }) { + run (statement, parameters, observer, { bookmark, txConfig, database, mode }) { const runMessage = RequestMessage.runWithMetadata(statement, parameters, { bookmark, txConfig, - db, + database, mode }) const pullMessage = RequestMessage.pull() diff --git a/src/internal/connection-holder.js b/src/internal/connection-holder.js index c81ae63cd..bd6cbba6b 100644 --- a/src/internal/connection-holder.js +++ b/src/internal/connection-holder.js @@ -28,12 +28,16 @@ export default class ConnectionHolder { /** * @constructor * @param {string} mode - the access mode for new connection holder. - * @param {string} db - the target database name. + * @param {string} database - the target database name. * @param {ConnectionProvider} connectionProvider - the connection provider to acquire connections from. */ - constructor ({ mode = ACCESS_MODE_WRITE, db = '', connectionProvider } = {}) { + constructor ({ + mode = ACCESS_MODE_WRITE, + database = '', + connectionProvider + } = {}) { this._mode = mode - this._db = db ? assertString(db, 'db') : '' + this._database = database ? assertString(database, 'database') : '' this._connectionProvider = connectionProvider this._referenceCount = 0 this._connectionPromise = Promise.resolve(null) @@ -49,10 +53,10 @@ export default class ConnectionHolder { /** * Returns the target database name - * @returns {string} db name + * @returns {string} the database name */ - db () { - return this._db + database () { + return this._database } /** @@ -63,7 +67,7 @@ export default class ConnectionHolder { if (this._referenceCount === 0) { this._connectionPromise = this._connectionProvider.acquireConnection( this._mode, - this._db + this._database ) } this._referenceCount++ diff --git a/src/internal/connection-providers.js b/src/internal/connection-providers.js index 04bbe6261..5f3cbb1ec 100644 --- a/src/internal/connection-providers.js +++ b/src/internal/connection-providers.js @@ -28,7 +28,7 @@ import { HostNameResolver } from './node' const UNAUTHORIZED_ERROR_CODE = 'Neo.ClientError.Security.Unauthorized' class ConnectionProvider { - acquireConnection (accessMode, db) { + acquireConnection (accessMode, database) { throw new Error('Abstract function') } @@ -51,7 +51,7 @@ export class DirectConnectionProvider extends ConnectionProvider { this._driverOnErrorCallback = driverOnErrorCallback } - acquireConnection (accessMode, db) { + acquireConnection (accessMode, database) { const connectionPromise = this._connectionPool.acquire(this._address) return this._withAdditionalOnErrorCallback( connectionPromise, @@ -83,7 +83,7 @@ export class LoadBalancer extends ConnectionProvider { this._useSeedRouter = true } - acquireConnection (accessMode, db) { + acquireConnection (accessMode, database) { const connectionPromise = this._freshRoutingTable(accessMode).then( routingTable => { if (accessMode === READ) { @@ -357,7 +357,7 @@ export class SingleConnectionProvider extends ConnectionProvider { this._connection = connection } - acquireConnection (mode, db) { + acquireConnection (mode, database) { const connection = this._connection this._connection = null return Promise.resolve(connection) diff --git a/src/internal/connectivity-verifier.js b/src/internal/connectivity-verifier.js index 0a013c69f..b47d6f24b 100644 --- a/src/internal/connectivity-verifier.js +++ b/src/internal/connectivity-verifier.js @@ -37,8 +37,8 @@ export default class ConnectivityVerifier { * Try to obtain a working connection from the connection provider. * @returns {Promise} promise resolved with server info or rejected with error. */ - verify ({ db = '' } = {}) { - return acquireAndReleaseDummyConnection(this._connectionProvider, db) + verify ({ database = '' } = {}) { + return acquireAndReleaseDummyConnection(this._connectionProvider, database) } } @@ -47,10 +47,10 @@ export default class ConnectivityVerifier { * @param {ConnectionProvider} connectionProvider the provider to obtain connections from. * @return {Promise} promise resolved with server info or rejected with error. */ -function acquireAndReleaseDummyConnection (connectionProvider, db) { +function acquireAndReleaseDummyConnection (connectionProvider, database) { const connectionHolder = new ConnectionHolder({ mode: READ, - db, + database, connectionProvider }) connectionHolder.initializeConnection() diff --git a/src/internal/http/http-session.js b/src/internal/http/http-session.js index 5379e636f..e1e279485 100644 --- a/src/internal/http/http-session.js +++ b/src/internal/http/http-session.js @@ -26,8 +26,14 @@ import { EMPTY_CONNECTION_HOLDER } from '../connection-holder' import Result from '../../result' export default class HttpSession extends Session { - constructor ({ url, authToken, config, db = '', sessionTracker } = {}) { - super({ mode: WRITE, connectionProvider: null, bookmark: null, db, config }) + constructor ({ url, authToken, config, database = '', sessionTracker } = {}) { + super({ + mode: WRITE, + connectionProvider: null, + bookmark: null, + database, + config + }) this._ongoingTransactionIds = [] this._serverInfoSupplier = createServerInfoSupplier(url) this._requestRunner = new HttpRequestRunner(url, authToken) diff --git a/src/internal/request-message.js b/src/internal/request-message.js index 62c2675d7..4faa9783f 100644 --- a/src/internal/request-message.js +++ b/src/internal/request-message.js @@ -115,12 +115,12 @@ export default class RequestMessage { * Create a new BEGIN message. * @param {Bookmark} bookmark the bookmark. * @param {TxConfig} txConfig the configuration. - * @param {string} db the database name. + * @param {string} database the database name. * @param {string} mode the access mode. * @return {RequestMessage} new BEGIN message. */ - static begin ({ bookmark, txConfig, db, mode } = {}) { - const metadata = buildTxMetadata(bookmark, txConfig, db, mode) + static begin ({ bookmark, txConfig, database, mode } = {}) { + const metadata = buildTxMetadata(bookmark, txConfig, database, mode) return new RequestMessage( BEGIN, [metadata], @@ -150,16 +150,16 @@ export default class RequestMessage { * @param {object} parameters the statement parameters. * @param {Bookmark} bookmark the bookmark. * @param {TxConfig} txConfig the configuration. - * @param {string} db the database name. + * @param {string} database the database name. * @param {string} mode the access mode. * @return {RequestMessage} new RUN message with additional metadata. */ static runWithMetadata ( statement, parameters, - { bookmark, txConfig, db, mode } = {} + { bookmark, txConfig, database, mode } = {} ) { - const metadata = buildTxMetadata(bookmark, txConfig, db, mode) + const metadata = buildTxMetadata(bookmark, txConfig, database, mode) return new RequestMessage( RUN, [statement, parameters, metadata], @@ -213,11 +213,11 @@ export default class RequestMessage { * Create an object that represent transaction metadata. * @param {Bookmark} bookmark the bookmark. * @param {TxConfig} txConfig the configuration. - * @param {string} db the database name. + * @param {string} database the database name. * @param {string} mode the access mode. * @return {object} a metadata object. */ -function buildTxMetadata (bookmark, txConfig, db, mode) { +function buildTxMetadata (bookmark, txConfig, database, mode) { const metadata = {} if (!bookmark.isEmpty()) { metadata['bookmarks'] = bookmark.values() @@ -228,8 +228,8 @@ function buildTxMetadata (bookmark, txConfig, db, mode) { if (txConfig.metadata) { metadata['tx_metadata'] = txConfig.metadata } - if (db) { - metadata['db'] = assertString(db, 'db') + if (database) { + metadata['db'] = assertString(database, 'database') } if (mode === ACCESS_MODE_READ) { metadata['mode'] = READ_MODE diff --git a/src/session.js b/src/session.js index 8d6939190..75cd68fa9 100644 --- a/src/session.js +++ b/src/session.js @@ -60,19 +60,20 @@ class Session { * @param {string} mode the default access mode for this session. * @param {ConnectionProvider} connectionProvider - the connection provider to acquire connections from. * @param {Bookmark} bookmark - the initial bookmark for this session. + * @param {string} database the database name * @param {Object} [config={}] - this driver configuration. */ - constructor ({ mode, connectionProvider, bookmark, db, config }) { + constructor ({ mode, connectionProvider, bookmark, database, config }) { this._mode = mode - this._db = db + this._database = database this._readConnectionHolder = new ConnectionHolder({ mode: ACCESS_MODE_READ, - db, + database, connectionProvider }) this._writeConnectionHolder = new ConnectionHolder({ mode: ACCESS_MODE_WRITE, - db, + database, connectionProvider }) this._open = true @@ -104,7 +105,7 @@ class Session { bookmark: this._lastBookmark, txConfig: autoCommitTxConfig, mode: this._mode, - db: this._db + database: this._database }) ) } diff --git a/src/transaction.js b/src/transaction.js index f6a84806c..68f6724db 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -52,7 +52,7 @@ class Transaction { bookmark: bookmark, txConfig: txConfig, mode: this._connectionHolder.mode(), - db: this._connectionHolder.db() + database: this._connectionHolder.database() }) ) .catch(error => streamObserver.onError(error)) @@ -186,7 +186,7 @@ let _states = { bookmark: bookmark, txConfig: txConfig, mode: connectionHolder.mode(), - db: connectionHolder.db() + database: connectionHolder.database() }) ) .catch(error => observer.onError(error)) diff --git a/test/bolt-v4.test.js b/test/bolt-v4.test.js index 24523e19b..5a160bfb6 100644 --- a/test/bolt-v4.test.js +++ b/test/bolt-v4.test.js @@ -53,7 +53,7 @@ describe('Bolt V4 API', () => { return } - const session = driver.session({ db: 'adb' }) + const session = driver.session({ database: 'adb' }) session .run('RETURN 1') @@ -71,7 +71,7 @@ describe('Bolt V4 API', () => { return } - const session = driver.session({ db: 'adb' }) + const session = driver.session({ database: 'adb' }) const tx = session.beginTransaction() tx.run('RETURN 1') @@ -89,7 +89,7 @@ describe('Bolt V4 API', () => { return } - const session = driver.session({ db: 'adb' }) + const session = driver.session({ database: 'adb' }) session .readTransaction(tx => tx.run('RETURN 1')) @@ -107,7 +107,7 @@ describe('Bolt V4 API', () => { return } - const session = driver.session({ db: 'adb' }) + const session = driver.session({ database: 'adb' }) session .writeTransaction(tx => tx.run('RETURN 1')) @@ -119,7 +119,7 @@ describe('Bolt V4 API', () => { }) }) - it('should return db.name as null in result summary', async () => { + it('should return database.name as null in result summary', async () => { if (databaseSupportsBoltV4()) { return } @@ -142,7 +142,7 @@ describe('Bolt V4 API', () => { return } - const neoSession = driver.session({ db: 'testdb' }) + const neoSession = driver.session({ database: 'testdb' }) try { await neoSession.run('RETURN 1') @@ -171,16 +171,16 @@ describe('Bolt V4 API', () => { return } - const neoSession = driver.session({ db: 'neo4j' }) + const neoSession = driver.session({ database: 'neo4j' }) try { const result = await session.run( - 'CREATE (n { db: $db }) RETURN n.db', - { db: 'neo4j' } + 'CREATE (n { name: $name }) RETURN n.name', + { name: 'neo4j' } ) expect(result.records.length).toBe(1) - expect(result.records[0].get('n.db')).toBe('neo4j') + expect(result.records[0].get('n.name')).toBe('neo4j') } finally { neoSession.close() } @@ -195,16 +195,16 @@ describe('Bolt V4 API', () => { 'neo4j://localhost', sharedNeo4j.authToken ) - const neoSession = driver.session({ db: 'neo4j' }) + const neoSession = driver.session({ database: 'neo4j' }) try { const result = await session.run( - 'CREATE (n { db: $db }) RETURN n.db', - { db: 'neo4j' } + 'CREATE (n { name: $name }) RETURN n.name', + { name: 'neo4j' } ) expect(result.records.length).toBe(1) - expect(result.records[0].get('n.db')).toBe('neo4j') + expect(result.records[0].get('n.name')).toBe('neo4j') } finally { neoSession.close() neoDriver.close() @@ -213,13 +213,13 @@ describe('Bolt V4 API', () => { }) }) - async function testDatabaseNameInSummary (dbname) { + async function testDatabaseNameInSummary (database) { if (!databaseSupportsBoltV4()) { return } - const neoSession = dbname - ? driver.session({ db: dbname }) + const neoSession = database + ? driver.session({ database }) : driver.session() try { @@ -228,7 +228,7 @@ describe('Bolt V4 API', () => { }) expect(result.summary.database).toBeTruthy() - expect(result.summary.database.name).toBe(dbname || 'neo4j') + expect(result.summary.database.name).toBe(database || 'neo4j') } finally { neoSession.close() } diff --git a/test/internal/bolt-protocol-v1.test.js b/test/internal/bolt-protocol-v1.test.js index bb74344eb..d17b5ce14 100644 --- a/test/internal/bolt-protocol-v1.test.js +++ b/test/internal/bolt-protocol-v1.test.js @@ -235,25 +235,25 @@ describe('BoltProtocolV1', () => { } describe('beginTransaction', () => { - function verifyBeginTransaction (db) { + function verifyBeginTransaction (database) { verifyError((protocol, observer) => - protocol.beginTransaction(observer, { db }) + protocol.beginTransaction(observer, { database }) ) } - it('should throw error when db is set', () => { + it('should throw error when database is set', () => { verifyBeginTransaction('test') }) }) describe('run', () => { - function verifyRun (db) { + function verifyRun (database) { verifyError((protocol, observer) => - protocol.run('statement', {}, observer, { db }) + protocol.run('statement', {}, observer, { database }) ) } - it('should throw error when db is set', () => { + it('should throw error when database is set', () => { verifyRun('test') }) }) diff --git a/test/internal/bolt-protocol-v3.test.js b/test/internal/bolt-protocol-v3.test.js index aa308aa49..dc4d2b6ad 100644 --- a/test/internal/bolt-protocol-v3.test.js +++ b/test/internal/bolt-protocol-v3.test.js @@ -168,25 +168,25 @@ describe('BoltProtocolV3', () => { } describe('beginTransaction', () => { - function verifyBeginTransaction (db) { + function verifyBeginTransaction (database) { verifyError((protocol, observer) => - protocol.beginTransaction(observer, { db }) + protocol.beginTransaction(observer, { database }) ) } - it('should throw error when db is set', () => { + it('should throw error when database is set', () => { verifyBeginTransaction('test') }) }) describe('run', () => { - function verifyRun (db) { + function verifyRun (database) { verifyError((protocol, observer) => - protocol.run('statement', {}, observer, { db }) + protocol.run('statement', {}, observer, { database }) ) } - it('should throw error when db is set', () => { + it('should throw error when database is set', () => { verifyRun('test') }) }) diff --git a/test/internal/bolt-protocol-v4.test.js b/test/internal/bolt-protocol-v4.test.js index 8ccc47ccd..c0d0980ff 100644 --- a/test/internal/bolt-protocol-v4.test.js +++ b/test/internal/bolt-protocol-v4.test.js @@ -30,7 +30,7 @@ describe('BoltProtocolV4', () => { }) it('should run a statement', () => { - const db = 'testdb' + const database = 'testdb' const bookmark = new Bookmark([ 'neo4j:bookmark:v1:tx1', 'neo4j:bookmark:v1:tx2' @@ -49,7 +49,7 @@ describe('BoltProtocolV4', () => { protocol.run(statement, parameters, observer, { bookmark, txConfig, - db, + database, mode: WRITE }) @@ -59,7 +59,7 @@ describe('BoltProtocolV4', () => { RequestMessage.runWithMetadata(statement, parameters, { bookmark, txConfig, - db, + database, mode: WRITE }) ) @@ -69,7 +69,7 @@ describe('BoltProtocolV4', () => { }) it('should begin a transaction', () => { - const db = 'testdb' + const database = 'testdb' const bookmark = new Bookmark([ 'neo4j:bookmark:v1:tx1', 'neo4j:bookmark:v1:tx2' @@ -86,13 +86,13 @@ describe('BoltProtocolV4', () => { protocol.beginTransaction(observer, { bookmark, txConfig, - db, + database, mode: WRITE }) recorder.verifyMessageCount(1) expect(recorder.messages[0]).toBeMessage( - RequestMessage.begin({ bookmark, txConfig, db, mode: WRITE }) + RequestMessage.begin({ bookmark, txConfig, database, mode: WRITE }) ) expect(recorder.observers).toEqual([observer]) expect(recorder.flushes).toEqual([true]) diff --git a/test/internal/connection-holder.test.js b/test/internal/connection-holder.test.js index 9f616274b..5309cba8d 100644 --- a/test/internal/connection-holder.test.js +++ b/test/internal/connection-holder.test.js @@ -258,9 +258,9 @@ describe('ConnectionHolder', () => { verifyMode(new ConnectionHolder({ mode: READ }), READ) }) - it('should default to empty db', () => { + it('should default to empty database', () => { function verifyDefault (connectionProvider) { - expect(connectionProvider.db()).toBe('') + expect(connectionProvider.database()).toBe('') } const connectionProvider = newSingleConnectionProvider(new FakeConnection()) @@ -269,24 +269,28 @@ describe('ConnectionHolder', () => { verifyDefault(new ConnectionHolder({ mode: READ, connectionProvider })) verifyDefault(new ConnectionHolder({ mode: WRITE, connectionProvider })) verifyDefault( - new ConnectionHolder({ mode: WRITE, db: '', connectionProvider }) + new ConnectionHolder({ mode: WRITE, database: '', connectionProvider }) ) verifyDefault( - new ConnectionHolder({ mode: WRITE, db: null, connectionProvider }) + new ConnectionHolder({ mode: WRITE, database: null, connectionProvider }) ) verifyDefault( - new ConnectionHolder({ mode: WRITE, db: undefined, connectionProvider }) + new ConnectionHolder({ + mode: WRITE, + database: undefined, + connectionProvider + }) ) }) - it('should return passed db', () => { + it('should return passed database', () => { const connectionProvider = newSingleConnectionProvider(new FakeConnection()) const connectionHolder = new ConnectionHolder({ - db: 'testdb', + database: 'testdb', connectionProvider }) - expect(connectionHolder.db()).toBe('testdb') + expect(connectionHolder.database()).toBe('testdb') }) }) @@ -297,7 +301,7 @@ class RecordingConnectionProvider extends SingleConnectionProvider { this.acquireConnectionInvoked = 0 } - acquireConnection (mode, db) { + acquireConnection (mode, database) { return this.connectionPromises[this.acquireConnectionInvoked++] } } diff --git a/test/internal/node/direct.driver.boltkit.test.js b/test/internal/node/direct.driver.boltkit.test.js index 81dd7b9b3..af587495f 100644 --- a/test/internal/node/direct.driver.boltkit.test.js +++ b/test/internal/node/direct.driver.boltkit.test.js @@ -20,7 +20,7 @@ import neo4j from '../../../src' import { READ, WRITE } from '../../../src/driver' import boltStub from '../bolt-stub' -import { newError, SERVICE_UNAVAILABLE } from '../../../src/v1/error' +import { newError, SERVICE_UNAVAILABLE } from '../../../src/error' describe('direct driver with stub server', () => { let originalTimeout diff --git a/types/driver.d.ts b/types/driver.d.ts index 19def0de4..34060ef77 100644 --- a/types/driver.d.ts +++ b/types/driver.d.ts @@ -65,11 +65,11 @@ declare interface Driver { session({ defaultAccessMode, bookmarks, - db + database }?: { defaultAccessMode?: SessionMode bookmarks?: string | string[] - db?: string + database?: string }): Session close(): void From 138764b810854845e031a7edde4df3aff12af566 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Fri, 5 Jul 2019 09:43:56 +0100 Subject: [PATCH 02/13] Add support for multiple routing tables and new routing procedure --- src/driver.js | 2 +- src/internal/connection-provider-direct.js | 37 ++ ...ders.js => connection-provider-routing.js} | 172 ++++--- src/internal/connection-provider-single.js | 33 ++ src/internal/connection-provider.js | 34 ++ src/internal/connection.js | 10 + src/internal/rediscovery.js | 13 +- src/internal/routing-table.js | 4 +- src/internal/routing-util.js | 27 +- src/routing-driver.js | 4 +- test/internal/connection-holder.test.js | 2 +- .../connection-provider-direct.test.js | 60 +++ ...js => connection-provider-routing.test.js} | 437 ++++++++++-------- test/internal/connectivity-verifier.test.js | 2 +- test/internal/fake-connection.js | 6 + .../node/direct.driver.boltkit.test.js | 2 +- .../node/routing.driver.boltkit.test.js | 154 +++--- test/internal/rediscovery.test.js | 2 +- test/internal/routing-table.test.js | 18 +- test/internal/routing-util.test.js | 57 ++- .../boltstub/acquire_endpoints.script | 2 +- .../acquire_endpoints_and_exit.script | 2 +- ...ire_endpoints_old_routing_procedure.script | 2 +- .../boltstub/acquire_endpoints_v3.script | 3 +- .../acquire_endpoints_with_one_of_each.script | 2 +- .../address_unavailable_template.script.mst | 5 +- .../boltstub/dead_routing_server.script | 4 +- .../discover_ipv6_servers_and_read.script | 2 +- .../boltstub/discover_new_servers.script | 2 +- .../boltstub/discover_no_writers.script | 2 +- .../boltstub/discover_one_router.script | 2 +- .../boltstub/discover_servers.script | 2 +- .../boltstub/discover_servers_and_read.script | 2 +- .../empty_get_servers_response.script | 2 +- test/resources/boltstub/failed_auth.script | 2 +- .../boltstub/get_routing_table.script | 2 +- .../get_routing_table_with_context.script | 2 +- .../boltstub/multiple_bookmarks.script | 8 +- .../multiple_records_get_servers.script | 1 - .../boltstub/no_readers_get_servers.script | 2 +- .../boltstub/no_routers_get_servers.script | 2 +- .../no_servers_entry_get_servers.script | 2 +- .../boltstub/no_ttl_entry_get_servers.script | 2 +- test/resources/boltstub/no_writers.script | 2 +- test/resources/boltstub/non_discovery.script | 2 +- .../boltstub/not_able_to_write.script | 10 +- .../not_able_to_write_in_transaction.script | 16 +- .../boltstub/one_of_each_template.script.mst | 2 +- .../boltstub/query_with_error.script | 2 +- .../boltstub/read_server_and_exit.script | 5 +- ...rver.script => read_server_v2_read.script} | 5 +- ...script => read_server_v2_read_dead.script} | 3 +- .../boltstub/read_server_v2_read_tx.script | 19 + .../read_server_v2_read_tx_dead.script | 11 + .../boltstub/read_server_with_version.script | 2 +- .../boltstub/read_tx_with_bookmarks.script | 1 - test/resources/boltstub/rediscover.script | 2 +- .../rediscover_and_read_with_init.script | 2 +- .../rediscover_using_initial_router.script | 17 +- test/resources/boltstub/reset_error.script | 1 + test/resources/boltstub/return_x.script | 2 +- .../routing_table_with_zero_ttl.script | 2 +- test/resources/boltstub/short_ttl.script | 2 +- .../boltstub/single_write_server.script | 2 +- .../two_write_responses_server.script | 6 +- ...rsable_multiple_records_get_servers.script | 10 + .../unparsable_servers_get_servers.script | 2 +- .../unparsable_ttl_get_servers.script | 2 +- ...rite_read_tx_with_bookmark_override.script | 12 +- .../write_read_tx_with_bookmarks.script | 12 +- test/resources/boltstub/write_server.script | 11 - ...er.script => write_server_v2_write.script} | 8 +- .../boltstub/write_server_v2_write_tx.script | 16 + .../write_server_v2_write_tx_dead.script | 11 + .../boltstub/write_server_v3_write.script | 5 +- .../boltstub/write_server_v3_write_tx.script | 5 +- .../boltstub/write_server_with_version.script | 4 +- .../boltstub/write_tx_with_bookmarks.script | 8 +- test/session.test.js | 2 +- 79 files changed, 855 insertions(+), 502 deletions(-) create mode 100644 src/internal/connection-provider-direct.js rename src/internal/{connection-providers.js => connection-provider-routing.js} (70%) create mode 100644 src/internal/connection-provider-single.js create mode 100644 src/internal/connection-provider.js create mode 100644 test/internal/connection-provider-direct.test.js rename test/internal/{connection-providers.test.js => connection-provider-routing.test.js} (73%) rename test/resources/boltstub/{read_server.script => read_server_v2_read.script} (66%) rename test/resources/boltstub/{dead_read_server.script => read_server_v2_read_dead.script} (68%) create mode 100644 test/resources/boltstub/read_server_v2_read_tx.script create mode 100644 test/resources/boltstub/read_server_v2_read_tx_dead.script create mode 100644 test/resources/boltstub/unparsable_multiple_records_get_servers.script delete mode 100644 test/resources/boltstub/write_server.script rename test/resources/boltstub/{dead_write_server.script => write_server_v2_write.script} (50%) create mode 100644 test/resources/boltstub/write_server_v2_write_tx.script create mode 100644 test/resources/boltstub/write_server_v2_write_tx_dead.script diff --git a/src/driver.js b/src/driver.js index 066f41fb4..11fe99de6 100644 --- a/src/driver.js +++ b/src/driver.js @@ -21,7 +21,7 @@ import Session from './session' import Pool from './internal/pool' import Connection from './internal/connection' import { newError, SERVICE_UNAVAILABLE } from './error' -import { DirectConnectionProvider } from './internal/connection-providers' +import DirectConnectionProvider from './internal/connection-provider-direct' import Bookmark from './internal/bookmark' import ConnectivityVerifier from './internal/connectivity-verifier' import PoolConfig, { diff --git a/src/internal/connection-provider-direct.js b/src/internal/connection-provider-direct.js new file mode 100644 index 000000000..9a465dfed --- /dev/null +++ b/src/internal/connection-provider-direct.js @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ConnectionProvider from './connection-provider' + +export default class DirectConnectionProvider extends ConnectionProvider { + constructor (address, connectionPool, driverOnErrorCallback) { + super() + this._address = address + this._connectionPool = connectionPool + this._driverOnErrorCallback = driverOnErrorCallback + } + + acquireConnection (accessMode, database) { + const connectionPromise = this._connectionPool.acquire(this._address) + return this._withAdditionalOnErrorCallback( + connectionPromise, + this._driverOnErrorCallback + ) + } +} diff --git a/src/internal/connection-providers.js b/src/internal/connection-provider-routing.js similarity index 70% rename from src/internal/connection-providers.js rename to src/internal/connection-provider-routing.js index 5f3cbb1ec..dfa56c4a9 100644 --- a/src/internal/connection-providers.js +++ b/src/internal/connection-provider-routing.js @@ -24,43 +24,17 @@ import RoutingTable from './routing-table' import Rediscovery from './rediscovery' import RoutingUtil from './routing-util' import { HostNameResolver } from './node' +import ConnectionProvider from './connection-provider' +import SingleConnectionProvider from './connection-provider-single' +import { VERSION_4_0_0 } from './server-version' const UNAUTHORIZED_ERROR_CODE = 'Neo.ClientError.Security.Unauthorized' +const DATABASE_NOT_FOUND_ERROR_CODE = + 'Neo.ClientError.Database.DatabaseNotFound' +const SYSTEM_DB_NAME = 'system' +const DEFAULT_DB_NAME = '' -class ConnectionProvider { - acquireConnection (accessMode, database) { - throw new Error('Abstract function') - } - - _withAdditionalOnErrorCallback (connectionPromise, driverOnErrorCallback) { - // install error handler from the driver on the connection promise; this callback is installed separately - // so that it does not handle errors, instead it is just an additional error reporting facility. - connectionPromise.catch(error => { - driverOnErrorCallback(error) - }) - // return the original connection promise - return connectionPromise - } -} - -export class DirectConnectionProvider extends ConnectionProvider { - constructor (address, connectionPool, driverOnErrorCallback) { - super() - this._address = address - this._connectionPool = connectionPool - this._driverOnErrorCallback = driverOnErrorCallback - } - - acquireConnection (accessMode, database) { - const connectionPromise = this._connectionPool.acquire(this._address) - return this._withAdditionalOnErrorCallback( - connectionPromise, - this._driverOnErrorCallback - ) - } -} - -export class LoadBalancer extends ConnectionProvider { +export default class RoutingConnectionProvider extends ConnectionProvider { constructor ( address, routingContext, @@ -72,7 +46,7 @@ export class LoadBalancer extends ConnectionProvider { ) { super() this._seedRouter = address - this._routingTable = new RoutingTable() + this._routingTables = {} this._rediscovery = new Rediscovery(new RoutingUtil(routingContext)) this._connectionPool = connectionPool this._driverOnErrorCallback = driverOnErrorCallback @@ -84,23 +58,24 @@ export class LoadBalancer extends ConnectionProvider { } acquireConnection (accessMode, database) { - const connectionPromise = this._freshRoutingTable(accessMode).then( - routingTable => { - if (accessMode === READ) { - const address = this._loadBalancingStrategy.selectReader( - routingTable.readers - ) - return this._acquireConnectionToServer(address, 'read') - } else if (accessMode === WRITE) { - const address = this._loadBalancingStrategy.selectWriter( - routingTable.writers - ) - return this._acquireConnectionToServer(address, 'write') - } else { - throw newError('Illegal mode ' + accessMode) - } + const connectionPromise = this._freshRoutingTable( + accessMode, + database || DEFAULT_DB_NAME + ).then(routingTable => { + if (accessMode === READ) { + const address = this._loadBalancingStrategy.selectReader( + routingTable.readers + ) + return this._acquireConnectionToServer(address, 'read', routingTable) + } else if (accessMode === WRITE) { + const address = this._loadBalancingStrategy.selectWriter( + routingTable.writers + ) + return this._acquireConnectionToServer(address, 'write', routingTable) + } else { + throw newError('Illegal mode ' + accessMode) } - ) + }) return this._withAdditionalOnErrorCallback( connectionPromise, this._driverOnErrorCallback @@ -108,21 +83,23 @@ export class LoadBalancer extends ConnectionProvider { } forget (address) { - this._routingTable.forget(address) + Object.values(this._routingTables).forEach(routingTable => + routingTable.forget(address) + ) this._connectionPool.purge(address) } forgetWriter (address) { - this._routingTable.forgetWriter(address) + Object.values(this._routingTables).forEach(routingTable => + routingTable.forgetWriter(address) + ) } - _acquireConnectionToServer (address, serverName) { + _acquireConnectionToServer (address, serverName, routingTable) { if (!address) { return Promise.reject( newError( - `Failed to obtain connection towards ${serverName} server. Known routing table is: ${ - this._routingTable - }`, + `Failed to obtain connection towards ${serverName} server. Known routing table is: ${routingTable}`, SESSION_EXPIRED ) ) @@ -130,14 +107,15 @@ export class LoadBalancer extends ConnectionProvider { return this._connectionPool.acquire(address) } - _freshRoutingTable (accessMode) { - const currentRoutingTable = this._routingTable + _freshRoutingTable (accessMode, database) { + const currentRoutingTable = + this._routingTables[database] || new RoutingTable({ database }) if (!currentRoutingTable.isStaleFor(accessMode)) { return Promise.resolve(currentRoutingTable) } this._log.info( - `Routing table is stale for ${accessMode}: ${currentRoutingTable}` + `Routing table is stale for database: "${database}" and access mode: "${accessMode}": ${currentRoutingTable}` ) return this._refreshRoutingTable(currentRoutingTable) } @@ -163,7 +141,11 @@ export class LoadBalancer extends ConnectionProvider { ) { // we start with seed router, no routers were probed before const seenRouters = [] - return this._fetchRoutingTableUsingSeedRouter(seenRouters, this._seedRouter) + return this._fetchRoutingTableUsingSeedRouter( + seenRouters, + this._seedRouter, + currentRoutingTable + ) .then(newRoutingTable => { if (newRoutingTable) { this._useSeedRouter = false @@ -177,7 +159,7 @@ export class LoadBalancer extends ConnectionProvider { ) }) .then(newRoutingTable => { - this._applyRoutingTableIfPossible(newRoutingTable) + this._applyRoutingTableIfPossible(currentRoutingTable, newRoutingTable) return newRoutingTable }) } @@ -198,11 +180,12 @@ export class LoadBalancer extends ConnectionProvider { // none of the known routers returned a valid routing table - try to use seed router address for rediscovery return this._fetchRoutingTableUsingSeedRouter( knownRouters, - this._seedRouter + this._seedRouter, + currentRoutingTable ) }) .then(newRoutingTable => { - this._applyRoutingTableIfPossible(newRoutingTable) + this._applyRoutingTableIfPossible(currentRoutingTable, newRoutingTable) return newRoutingTable }) } @@ -218,7 +201,7 @@ export class LoadBalancer extends ConnectionProvider { // returned routing table was undefined, this means a connection error happened and the last known // router did not return a valid routing table, so we need to forget it const lastRouterIndex = knownRouters.length - 1 - LoadBalancer._forgetRouter( + RoutingConnectionProvider._forgetRouter( currentRoutingTable, knownRouters, lastRouterIndex @@ -229,14 +212,14 @@ export class LoadBalancer extends ConnectionProvider { ) } - _fetchRoutingTableUsingSeedRouter (seenRouters, seedRouter) { - const resolvedAddresses = this._hostNameResolver.resolve(seedRouter) + _fetchRoutingTableUsingSeedRouter (seenRouters, seedRouter, routingTable) { + const resolvedAddresses = this._resolveSeedRouter(seedRouter) return resolvedAddresses.then(resolvedRouterAddresses => { // filter out all addresses that we've already tried const newAddresses = resolvedRouterAddresses.filter( address => seenRouters.indexOf(address) < 0 ) - return this._fetchRoutingTable(newAddresses, null) + return this._fetchRoutingTable(newAddresses, routingTable) }) } @@ -265,7 +248,7 @@ export class LoadBalancer extends ConnectionProvider { // returned routing table was undefined, this means a connection error happened and we need to forget the // previous router and try the next one const previousRouterIndex = currentIndex - 1 - LoadBalancer._forgetRouter( + RoutingConnectionProvider._forgetRouter( routingTable, routerAddresses, previousRouterIndex @@ -277,8 +260,16 @@ export class LoadBalancer extends ConnectionProvider { session => { if (session) { return this._rediscovery - .lookupRoutingTableOnRouter(session, currentRouter) + .lookupRoutingTableOnRouter( + session, + routingTable.database, + currentRouter + ) .catch(error => { + if (error && error.code === DATABASE_NOT_FOUND_ERROR_CODE) { + // not finding the target database is a sign of a configuration issue + throw error + } this._log.warn( `unable to fetch routing table because of an error ${error}` ) @@ -302,25 +293,37 @@ export class LoadBalancer extends ConnectionProvider { .acquire(routerAddress) .then(connection => { const connectionProvider = new SingleConnectionProvider(connection) - return new Session({ mode: READ, connectionProvider }) + + if (connection.version().compareTo(VERSION_4_0_0) < 0) { + return new Session({ mode: READ, connectionProvider }) + } + + return new Session({ + mode: READ, + database: SYSTEM_DB_NAME, + connectionProvider + }) }) .catch(error => { // unable to acquire connection towards the given router - if (error && error.code === UNAUTHORIZED_ERROR_CODE) { - // auth error is a sign of a configuration issue, rediscovery should not proceed + if ( + error && + (error.code === UNAUTHORIZED_ERROR_CODE || + error.code === DATABASE_NOT_FOUND_ERROR_CODE) + ) { + // auth error and not finding system database is a sign of a configuration issue + // discovery should not proceed throw error } return null }) } - _applyRoutingTableIfPossible (newRoutingTable) { + _applyRoutingTableIfPossible (currentRoutingTable, newRoutingTable) { if (!newRoutingTable) { // none of routing servers returned valid routing table, throw exception throw newError( - `Could not perform discovery. No routing servers available. Known routing table: ${ - this._routingTable - }`, + `Could not perform discovery. No routing servers available. Known routing table: ${currentRoutingTable}`, SERVICE_UNAVAILABLE ) } @@ -339,7 +342,7 @@ export class LoadBalancer extends ConnectionProvider { this._connectionPool.keepAll(newRoutingTable.allServers()) // make this driver instance aware of the new table - this._routingTable = newRoutingTable + this._routingTables[newRoutingTable.database] = newRoutingTable this._log.info(`Updated routing table ${newRoutingTable}`) } @@ -350,16 +353,3 @@ export class LoadBalancer extends ConnectionProvider { } } } - -export class SingleConnectionProvider extends ConnectionProvider { - constructor (connection) { - super() - this._connection = connection - } - - acquireConnection (mode, database) { - const connection = this._connection - this._connection = null - return Promise.resolve(connection) - } -} diff --git a/src/internal/connection-provider-single.js b/src/internal/connection-provider-single.js new file mode 100644 index 000000000..e13c5132c --- /dev/null +++ b/src/internal/connection-provider-single.js @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ConnectionProvider from './connection-provider' + +export default class SingleConnectionProvider extends ConnectionProvider { + constructor (connection) { + super() + this._connection = connection + } + + acquireConnection (mode, database) { + const connection = this._connection + this._connection = null + return Promise.resolve(connection) + } +} diff --git a/src/internal/connection-provider.js b/src/internal/connection-provider.js new file mode 100644 index 000000000..cad587e67 --- /dev/null +++ b/src/internal/connection-provider.js @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class ConnectionProvider { + acquireConnection (accessMode, database) { + throw new Error('Abstract function') + } + + _withAdditionalOnErrorCallback (connectionPromise, driverOnErrorCallback) { + // install error handler from the driver on the connection promise; this callback is installed separately + // so that it does not handle errors, instead it is just an additional error reporting facility. + connectionPromise.catch(error => { + driverOnErrorCallback(error) + }) + // return the original connection promise + return connectionPromise + } +} diff --git a/src/internal/connection.js b/src/internal/connection.js index bf65c2f70..9cbf832cc 100644 --- a/src/internal/connection.js +++ b/src/internal/connection.js @@ -198,6 +198,16 @@ export default class Connection { return this._protocol } + /** + * Get the version of the connected server. + * Available only after initialization + * + * @returns {ServerVersion} version + */ + version () { + return ServerVersion.fromString(this.server.version) + } + /** * Write a message to the network channel. * @param {RequestMessage} message the message to write. diff --git a/src/internal/rediscovery.js b/src/internal/rediscovery.js index 7a3e77ea2..d1e572a31 100644 --- a/src/internal/rediscovery.js +++ b/src/internal/rediscovery.js @@ -32,12 +32,13 @@ export default class Rediscovery { /** * Try to fetch new routing table from the given router. * @param {Session} session the session to use. + * @param {string} database the database for which to lookup routing table. * @param {string} routerAddress the URL of the router. * @return {Promise} promise resolved with new routing table or null when connection error happened. */ - lookupRoutingTableOnRouter (session, routerAddress) { + lookupRoutingTableOnRouter (session, database, routerAddress) { return this._routingUtil - .callRoutingProcedure(session, routerAddress) + .callRoutingProcedure(session, database, routerAddress) .then(records => { if (records === null) { // connection error happened, unable to retrieve routing table from this router, next one should be queried @@ -70,7 +71,13 @@ export default class Rediscovery { // case with no writers is processed higher in the promise chain because only RoutingDriver knows // how to deal with such table and how to treat router that returned such table - return new RoutingTable(routers, readers, writers, expirationTime) + return new RoutingTable({ + database, + routers, + readers, + writers, + expirationTime + }) }) } diff --git a/src/internal/routing-table.js b/src/internal/routing-table.js index b8cb8699d..9516b8703 100644 --- a/src/internal/routing-table.js +++ b/src/internal/routing-table.js @@ -22,7 +22,8 @@ import { READ, WRITE } from '../driver' const MIN_ROUTERS = 1 export default class RoutingTable { - constructor (routers, readers, writers, expirationTime) { + constructor ({ database, routers, readers, writers, expirationTime } = {}) { + this.database = database this.routers = routers || [] this.readers = readers || [] this.writers = writers || [] @@ -67,6 +68,7 @@ export default class RoutingTable { toString () { return ( `RoutingTable[` + + `database=${this.database}, ` + `expirationTime=${this.expirationTime}, ` + `currentTime=${Date.now()}, ` + `routers=[${this.routers}], ` + diff --git a/src/internal/routing-util.js b/src/internal/routing-util.js index 0a8217a49..4d17a53e0 100644 --- a/src/internal/routing-util.js +++ b/src/internal/routing-util.js @@ -19,15 +19,17 @@ import { newError, PROTOCOL_ERROR, SERVICE_UNAVAILABLE } from '../error' import Integer, { int } from '../integer' -import { ServerVersion, VERSION_3_2_0 } from './server-version' +import { ServerVersion, VERSION_3_2_0, VERSION_4_0_0 } from './server-version' import Bookmark from './bookmark' import TxConfig from './tx-config' import { ACCESS_MODE_WRITE } from './constants' import ServerAddress from './server-address' +const CONTEXT = 'context' const CALL_GET_SERVERS = 'CALL dbms.cluster.routing.getServers' -const CALL_GET_ROUTING_TABLE = - 'CALL dbms.cluster.routing.getRoutingTable($context)' +const CALL_GET_ROUTING_TABLE = `CALL dbms.cluster.routing.getRoutingTable($${CONTEXT})` +const DATABASE = 'database' +const CALL_GET_ROUTING_TABLE_MULTI_DB = `CALL dbms.routing.getRoutingTable($${CONTEXT}, $${DATABASE})` const PROCEDURE_NOT_FOUND_CODE = 'Neo.ClientError.Procedure.ProcedureNotFound' export default class RoutingUtil { @@ -42,8 +44,8 @@ export default class RoutingUtil { * @return {Promise} promise resolved with records returned by the procedure call or null if * connection error happened. */ - callRoutingProcedure (session, routerAddress) { - return this._callAvailableRoutingProcedure(session) + callRoutingProcedure (session, database, routerAddress) { + return this._callAvailableRoutingProcedure(session, database) .then(result => { session.close() return result.records @@ -128,17 +130,22 @@ export default class RoutingUtil { } } - _callAvailableRoutingProcedure (session) { + _callAvailableRoutingProcedure (session, database) { return session._run(null, null, (connection, streamObserver) => { - const serverVersionString = connection.server.version - const serverVersion = ServerVersion.fromString(serverVersionString) + const serverVersion = connection.version() let query let params - if (serverVersion.compareTo(VERSION_3_2_0) >= 0) { + if (serverVersion.compareTo(VERSION_4_0_0) >= 0) { + query = CALL_GET_ROUTING_TABLE_MULTI_DB + params = {} + params[CONTEXT] = this._routingContext + params[DATABASE] = database + } else if (serverVersion.compareTo(VERSION_3_2_0) >= 0) { query = CALL_GET_ROUTING_TABLE - params = { context: this._routingContext } + params = {} + params[CONTEXT] = this._routingContext } else { query = CALL_GET_SERVERS params = {} diff --git a/src/routing-driver.js b/src/routing-driver.js index 5c63c859b..514013a48 100644 --- a/src/routing-driver.js +++ b/src/routing-driver.js @@ -19,7 +19,7 @@ import { Driver } from './driver' import { newError, SESSION_EXPIRED } from './error' -import { LoadBalancer } from './internal/connection-providers' +import RoutingConnectionProvider from './internal/connection-provider-routing' import LeastConnectedLoadBalancingStrategy from './internal/least-connected-load-balancing-strategy' import ConnectionErrorHandler from './internal/connection-error-handler' import ConfiguredCustomResolver from './internal/resolver/configured-custom-resolver' @@ -46,7 +46,7 @@ class RoutingDriver extends Driver { connectionPool ) const resolver = createHostNameResolver(this._config) - return new LoadBalancer( + return new RoutingConnectionProvider( address, this._routingContext, connectionPool, diff --git a/test/internal/connection-holder.test.js b/test/internal/connection-holder.test.js index 5309cba8d..5ddfe8418 100644 --- a/test/internal/connection-holder.test.js +++ b/test/internal/connection-holder.test.js @@ -20,7 +20,7 @@ import ConnectionHolder, { EMPTY_CONNECTION_HOLDER } from '../../src/internal/connection-holder' -import { SingleConnectionProvider } from '../../src/internal/connection-providers' +import SingleConnectionProvider from '../../src/internal/connection-provider-single' import { READ, WRITE } from '../../src/driver' import FakeConnection from './fake-connection' import StreamObserver from '../../src/internal/stream-observer' diff --git a/test/internal/connection-provider-direct.test.js b/test/internal/connection-provider-direct.test.js new file mode 100644 index 000000000..11a734786 --- /dev/null +++ b/test/internal/connection-provider-direct.test.js @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { READ } from '../../src/driver' +import DirectConnectionProvider from '../../src/internal/connection-provider-direct' +import Pool from '../../src/internal/pool' +import ServerAddress from '../../src/internal/server-address' + +const NO_OP_DRIVER_CALLBACK = () => {} + +describe('DirectConnectionProvider', () => { + it('acquires connection from the pool', done => { + const address = ServerAddress.fromUrl('localhost:123') + const pool = newPool() + const connectionProvider = newDirectConnectionProvider(address, pool) + + connectionProvider.acquireConnection(READ).then(connection => { + expect(connection).toBeDefined() + expect(connection.address).toEqual(address) + expect(connection.release).toBeDefined() + expect(pool.has(address)).toBeTruthy() + + done() + }) + }) +}) + +function newDirectConnectionProvider (address, pool) { + return new DirectConnectionProvider(address, pool, NO_OP_DRIVER_CALLBACK) +} + +function newPool () { + return new Pool({ + create: (address, release) => + Promise.resolve(new FakeConnection(address, release)) + }) +} + +class FakeConnection { + constructor (address, release) { + this.address = address + this.release = release + } +} diff --git a/test/internal/connection-providers.test.js b/test/internal/connection-provider-routing.test.js similarity index 73% rename from test/internal/connection-providers.test.js rename to test/internal/connection-provider-routing.test.js index 7215f21a7..4af4e688f 100644 --- a/test/internal/connection-providers.test.js +++ b/test/internal/connection-provider-routing.test.js @@ -21,36 +21,17 @@ import { READ, WRITE } from '../../src/driver' import Integer, { int } from '../../src/integer' import { SERVICE_UNAVAILABLE, SESSION_EXPIRED } from '../../src/error' import RoutingTable from '../../src/internal/routing-table' -import { - DirectConnectionProvider, - LoadBalancer -} from '../../src/internal/connection-providers' import Pool from '../../src/internal/pool' import LeastConnectedLoadBalancingStrategy from '../../src/internal/least-connected-load-balancing-strategy' import Logger from '../../src/internal/logger' import SimpleHostNameResolver from '../../src/internal/browser/browser-host-name-resolver' import ServerAddress from '../../src/internal/server-address' +import RoutingConnectionProvider from '../../src/internal/connection-provider-routing' +import { VERSION_IN_DEV } from '../../src/internal/server-version' const NO_OP_DRIVER_CALLBACK = () => {} -describe('DirectConnectionProvider', () => { - it('acquires connection from the pool', done => { - const address = ServerAddress.fromUrl('localhost:123') - const pool = newPool() - const connectionProvider = newDirectConnectionProvider(address, pool) - - connectionProvider.acquireConnection(READ).then(connection => { - expect(connection).toBeDefined() - expect(connection.address).toEqual(address) - expect(connection.release).toBeDefined() - expect(pool.has(address)).toBeTruthy() - - done() - }) - }) -}) - -describe('LoadBalancer', () => { +describe('RoutingConnectionProvider', () => { let originalTimeout beforeEach(function () { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL @@ -92,28 +73,37 @@ describe('LoadBalancer', () => { const serverABC = ServerAddress.fromUrl('serverABC') it('can forget address', () => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server2], [server2, server4] ) - loadBalancer.forget(server2) + connectionProvider.forget(server2) - expectRoutingTable(loadBalancer, [server1, server2], [server3], [server4]) + expectRoutingTable( + connectionProvider, + '', + [server1, server2], + [server3], + [server4] + ) }) it('can not forget unknown address', () => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6] ) - loadBalancer.forget(server42) + connectionProvider.forget(server42) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [server1, server2], [server3, server4], [server5, server6] @@ -128,31 +118,34 @@ describe('LoadBalancer', () => { pool.acquire(server5) expectPoolToContain(pool, [server1, server3, server5]) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server2], [server2, server4], pool ) - loadBalancer.forget(server1) - loadBalancer.forget(server5) + connectionProvider.forget(server1) + connectionProvider.forget(server5) expectPoolToContain(pool, [server3]) expectPoolToNotContain(pool, [server1, server5]) }) it('can forget writer address', () => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server2], [server2, server4] ) - loadBalancer.forgetWriter(server2) + connectionProvider.forgetWriter(server2) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [server1, server2], [server3, server2], [server4] @@ -160,54 +153,39 @@ describe('LoadBalancer', () => { }) it('can not forget unknown writer address', () => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6] ) - loadBalancer.forgetWriter(server42) + connectionProvider.forgetWriter(server42) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [server1, server2], [server3, server4], [server5, server6] ) }) - it('initializes routing table with the given router', () => { - const connectionPool = newPool() - const loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy( - connectionPool - ) - const loadBalancer = new LoadBalancer( - serverABC, - {}, - connectionPool, - loadBalancingStrategy, - new SimpleHostNameResolver(), - NO_OP_DRIVER_CALLBACK, - Logger.noOp() - ) - - expectRoutingTable(loadBalancer, [], [], []) - }) - it('acquires read connection with up-to-date routing table', done => { const pool = newPool() - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], pool ) - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(server3) expect(pool.has(server3)).toBeTruthy() - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(server4) expect(pool.has(server4)).toBeTruthy() @@ -218,18 +196,19 @@ describe('LoadBalancer', () => { it('acquires write connection with up-to-date routing table', done => { const pool = newPool() - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], pool ) - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(server5) expect(pool.has(server5)).toBeTruthy() - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(server6) expect(pool.has(server6)).toBeTruthy() @@ -239,13 +218,14 @@ describe('LoadBalancer', () => { }) it('throws for illegal access mode', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6] ) - loadBalancer.acquireConnection('WRONG').catch(error => { + connectionProvider.acquireConnection('WRONG', '').catch(error => { expect(error.message).toEqual('Illegal mode WRONG') done() }) @@ -254,11 +234,13 @@ describe('LoadBalancer', () => { it('refreshes stale routing table to get read connection', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -267,11 +249,11 @@ describe('LoadBalancer', () => { { 'server1:7687': updatedRoutingTable } ) - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(serverC) expect(pool.has(serverC)).toBeTruthy() - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(serverD) expect(pool.has(serverD)).toBeTruthy() @@ -283,11 +265,13 @@ describe('LoadBalancer', () => { it('refreshes stale routing table to get write connection', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -296,11 +280,11 @@ describe('LoadBalancer', () => { { 'server1:7687': updatedRoutingTable } ) - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(serverE) expect(pool.has(serverE)).toBeTruthy() - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(serverF) expect(pool.has(serverF)).toBeTruthy() @@ -312,11 +296,13 @@ describe('LoadBalancer', () => { it('refreshes stale routing table to get read connection when one router fails', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -328,11 +314,11 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(serverC) expect(pool.has(serverC)).toBeTruthy() - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(serverD) expect(pool.has(serverD)).toBeTruthy() @@ -344,11 +330,13 @@ describe('LoadBalancer', () => { it('refreshes stale routing table to get write connection when one router fails', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -360,11 +348,11 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(serverE) expect(pool.has(serverE)).toBeTruthy() - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(serverF) expect(pool.has(serverF)).toBeTruthy() @@ -376,11 +364,13 @@ describe('LoadBalancer', () => { it('refreshes routing table without readers to get read connection', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [], // no readers [server3, server4], @@ -392,11 +382,11 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(serverC) expect(pool.has(serverC)).toBeTruthy() - loadBalancer.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection.address).toEqual(serverD) expect(pool.has(serverD)).toBeTruthy() @@ -408,11 +398,13 @@ describe('LoadBalancer', () => { it('refreshes routing table without writers to get write connection', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [], // no writers @@ -424,11 +416,11 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(serverE) expect(pool.has(serverE)).toBeTruthy() - loadBalancer.acquireConnection(WRITE).then(connection => { + connectionProvider.acquireConnection(WRITE, '').then(connection => { expect(connection.address).toEqual(serverF) expect(pool.has(serverF)).toBeTruthy() @@ -438,7 +430,8 @@ describe('LoadBalancer', () => { }) it('throws when all routers return nothing while getting read connection', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -450,14 +443,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) done() }) }) it('throws when all routers return nothing while getting write connection', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -469,7 +463,7 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) done() }) @@ -477,11 +471,13 @@ describe('LoadBalancer', () => { it('throws when all routers return routing tables without readers while getting read connection', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [], // no readers - table can't satisfy connection requirement [serverC, serverD] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -493,7 +489,7 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SESSION_EXPIRED) done() }) @@ -501,11 +497,13 @@ describe('LoadBalancer', () => { it('throws when all routers return routing tables without writers while getting write connection', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [] // no writers - table can't satisfy connection requirement ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -517,14 +515,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SESSION_EXPIRED) done() }) }) it('throws when stale routing table without routers while getting read connection', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [], // no routers [server3, server4], [server5, server6], @@ -532,14 +531,15 @@ describe('LoadBalancer', () => { int(0) // expired routing table ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) done() }) }) it('throws when stale routing table without routers while getting write connection', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [], // no routers [server3, server4], [server5, server6], @@ -547,7 +547,7 @@ describe('LoadBalancer', () => { int(0) // expired routing table ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) done() }) @@ -556,11 +556,13 @@ describe('LoadBalancer', () => { it('updates routing table after refresh', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -571,9 +573,10 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).then(() => { + connectionProvider.acquireConnection(READ, '').then(() => { expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] @@ -591,7 +594,8 @@ describe('LoadBalancer', () => { }) it('forgets all routers when they fail while acquiring read connection', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2, server3], [server4, server5], [server6, server7], @@ -599,10 +603,11 @@ describe('LoadBalancer', () => { int(0) // expired routing table ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], [server4, server5], [server6, server7] @@ -612,7 +617,8 @@ describe('LoadBalancer', () => { }) it('forgets all routers when they fail while acquiring write connection', done => { - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2, server3], [server4, server5], [server6, server7], @@ -620,10 +626,11 @@ describe('LoadBalancer', () => { int(0) // expired routing table ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], [server4, server5], [server6, server7] @@ -634,14 +641,16 @@ describe('LoadBalancer', () => { it('uses seed router address when all existing routers fail', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB, serverC], [serverD, serverE], [serverF, serverG] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server0], // seed router address resolves just to itself + '', [server1, server2, server3], [server4, server5], [server6, server7], @@ -654,14 +663,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).then(connection1 => { + connectionProvider.acquireConnection(READ, '').then(connection1 => { expect(connection1.address).toEqual(serverD) - loadBalancer.acquireConnection(WRITE).then(connection2 => { + connectionProvider.acquireConnection(WRITE, '').then(connection2 => { expect(connection2.address).toEqual(serverF) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB, serverC], [serverD, serverE], [serverF, serverG] @@ -673,14 +683,16 @@ describe('LoadBalancer', () => { it('uses resolved seed router address when all existing routers fail', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01], // seed router address resolves to a different one + '', [server1, server2, server3], [server4, server5], [server6, server7], @@ -693,14 +705,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).then(connection1 => { + connectionProvider.acquireConnection(WRITE, '').then(connection1 => { expect(connection1.address).toEqual(serverE) - loadBalancer.acquireConnection(READ).then(connection2 => { + connectionProvider.acquireConnection(READ, '').then(connection2 => { expect(connection2.address).toEqual(serverC) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] @@ -712,14 +725,16 @@ describe('LoadBalancer', () => { it('uses resolved seed router address that returns correct routing table when all existing routers fail', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC], [serverD, serverE] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01, server02, server03], // seed router address resolves to 3 different addresses + '', [server1], [server2], [server3], @@ -732,14 +747,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).then(connection1 => { + connectionProvider.acquireConnection(WRITE, '').then(connection1 => { expect(connection1.address).toEqual(serverD) - loadBalancer.acquireConnection(WRITE).then(connection2 => { + connectionProvider.acquireConnection(WRITE, '').then(connection2 => { expect(connection2.address).toEqual(serverE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC], [serverD, serverE] @@ -750,9 +766,10 @@ describe('LoadBalancer', () => { }) it('fails when both existing routers and seed router fail to return a routing table', done => { - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server0], // seed router address resolves just to itself + '', [server1, server2, server3], [server4, server5], [server6], @@ -765,21 +782,23 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], // all routers were forgotten because they failed [server4, server5], [server6] ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], // all routers were forgotten because they failed [server4, server5], [server6] @@ -791,9 +810,10 @@ describe('LoadBalancer', () => { }) it('fails when both existing routers and resolved seed router fail to return a routing table', done => { - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01], // seed router address resolves to a different one + '', [server1, server2], [server3], [server4], @@ -805,21 +825,23 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], // all routers were forgotten because they failed [server3], [server4] ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], // all routers were forgotten because they failed [server3], [server4] @@ -831,9 +853,10 @@ describe('LoadBalancer', () => { }) it('fails when both existing routers and all resolved seed routers fail to return a routing table', done => { - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server02, server01], // seed router address resolves to 2 different addresses + '', [server1, server2, server3], [server4], [server5], @@ -847,21 +870,23 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], // all known seed servers failed to return routing tables and were forgotten [server4], [server5] ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SERVICE_UNAVAILABLE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [], // all known seed servers failed to return routing tables and were forgotten [server4], [server5] @@ -874,14 +899,16 @@ describe('LoadBalancer', () => { it('uses seed router when no existing routers', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC], [serverD] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server0], // seed router address resolves just to itself + '', [], // no routers in the known routing table [server1, server2], [server3], @@ -891,14 +918,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).then(connection1 => { + connectionProvider.acquireConnection(WRITE, '').then(connection1 => { expect(connection1.address).toEqual(serverD) - loadBalancer.acquireConnection(READ).then(connection2 => { + connectionProvider.acquireConnection(READ, '').then(connection2 => { expect(connection2.address).toEqual(serverC) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC], [serverD] @@ -910,14 +938,16 @@ describe('LoadBalancer', () => { it('uses resolved seed router when no existing routers', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverF, serverE] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01], // seed router address resolves to a different one + '', [], // no routers in the known routing table [server1, server2], [server3, server4], @@ -927,14 +957,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).then(connection1 => { + connectionProvider.acquireConnection(READ, '').then(connection1 => { expect(connection1.address).toEqual(serverC) - loadBalancer.acquireConnection(WRITE).then(connection2 => { + connectionProvider.acquireConnection(WRITE, '').then(connection2 => { expect(connection2.address).toEqual(serverF) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC, serverD], [serverF, serverE] @@ -946,14 +977,16 @@ describe('LoadBalancer', () => { it('uses resolved seed router that returns routing table when no existing routers exist', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB, serverC], [serverD, serverE], [serverF] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server02, server01, server03], // seed router address resolves to 3 different addresses + '', [], // no routers in the known routing table [server1], [server2, server3], @@ -965,14 +998,15 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).then(connection1 => { + connectionProvider.acquireConnection(WRITE, '').then(connection1 => { expect(connection1.address).toEqual(serverF) - loadBalancer.acquireConnection(READ).then(connection2 => { + connectionProvider.acquireConnection(READ, '').then(connection2 => { expect(connection2.address).toEqual(serverD) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB, serverC], [serverD, serverE], [serverF] @@ -984,14 +1018,16 @@ describe('LoadBalancer', () => { it('ignores already probed routers after seed router resolution', done => { const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server1, server01, server2, server02], // seed router address resolves to 4 different addresses + '', [server1, server2], [server3, server4], [server5, server6], @@ -1004,15 +1040,18 @@ describe('LoadBalancer', () => { } ) // override default use of seed router - loadBalancer._useSeedRouter = false + connectionProvider._useSeedRouter = false const usedRouterArrays = [] - setupLoadBalancerToRememberRouters(loadBalancer, usedRouterArrays) + setupRoutingConnectionProviderToRememberRouters( + connectionProvider, + usedRouterArrays + ) - loadBalancer.acquireConnection(READ).then(connection1 => { + connectionProvider.acquireConnection(READ, '').then(connection1 => { expect(connection1.address).toEqual(serverC) - loadBalancer.acquireConnection(WRITE).then(connection2 => { + connectionProvider.acquireConnection(WRITE, '').then(connection2 => { expect(connection2.address).toEqual(serverE) // two sets of routers probed: @@ -1023,7 +1062,8 @@ describe('LoadBalancer', () => { expect(usedRouterArrays[1]).toEqual([server01, server02]) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC, serverD], [serverE, serverF] @@ -1036,11 +1076,13 @@ describe('LoadBalancer', () => { it('throws session expired when refreshed routing table has no readers', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [], // no readers [serverC, serverD] ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -1051,7 +1093,7 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(READ).catch(error => { + connectionProvider.acquireConnection(READ, '').catch(error => { expect(error.code).toEqual(SESSION_EXPIRED) done() }) @@ -1060,11 +1102,13 @@ describe('LoadBalancer', () => { it('throws session expired when refreshed routing table has no writers', done => { const pool = newPool() const updatedRoutingTable = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [] // no writers ) - const loadBalancer = newLoadBalancer( + const connectionProvider = newRoutingConnectionProvider( + '', [server1, server2], [server3, server4], [server5, server6], @@ -1075,7 +1119,7 @@ describe('LoadBalancer', () => { } ) - loadBalancer.acquireConnection(WRITE).catch(error => { + connectionProvider.acquireConnection(WRITE, '').catch(error => { expect(error.code).toEqual(SESSION_EXPIRED) done() }) @@ -1083,19 +1127,22 @@ describe('LoadBalancer', () => { it('should use resolved seed router after accepting table with no writers', done => { const routingTable1 = newRoutingTable( + '', [serverA, serverB], [serverC, serverD], [] // no writers ) const routingTable2 = newRoutingTable( + '', [serverAA, serverBB], [serverCC, serverDD], [serverEE] ) - const loadBalancer = newLoadBalancerWithSeedRouter( + const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server02, server01], // seed router address resolves to 2 different addresses + '', [server1], [server2, server3], [server4, server5], @@ -1109,26 +1156,28 @@ describe('LoadBalancer', () => { } ) // override default use of seed router - loadBalancer._useSeedRouter = false + connectionProvider._useSeedRouter = false - loadBalancer.acquireConnection(READ).then(connection1 => { + connectionProvider.acquireConnection(READ, '').then(connection1 => { expect(connection1.address).toEqual(serverC) - loadBalancer.acquireConnection(READ).then(connection2 => { + connectionProvider.acquireConnection(READ, '').then(connection2 => { expect(connection2.address).toEqual(serverD) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverA, serverB], [serverC, serverD], [] ) - loadBalancer.acquireConnection(WRITE).then(connection3 => { + connectionProvider.acquireConnection(WRITE, '').then(connection3 => { expect(connection3.address).toEqual(serverEE) expectRoutingTable( - loadBalancer, + connectionProvider, + '', [serverAA, serverBB], [serverCC, serverDD], [serverEE] @@ -1141,11 +1190,8 @@ describe('LoadBalancer', () => { }) }) -function newDirectConnectionProvider (address, pool) { - return new DirectConnectionProvider(address, pool, NO_OP_DRIVER_CALLBACK) -} - -function newLoadBalancer ( +function newRoutingConnectionProvider ( + database, routers, readers, writers, @@ -1154,9 +1200,10 @@ function newLoadBalancer ( routerToRoutingTable = {} ) { const seedRouter = ServerAddress.fromUrl('server-non-existing-seed-router') - return newLoadBalancerWithSeedRouter( + return newRoutingConnectionProviderWithSeedRouter( seedRouter, [seedRouter], + database, routers, readers, writers, @@ -1166,9 +1213,10 @@ function newLoadBalancer ( ) } -function newLoadBalancerWithSeedRouter ( +function newRoutingConnectionProviderWithSeedRouter ( seedRouter, seedRouterResolved, + database, routers, readers, writers, @@ -1178,7 +1226,7 @@ function newLoadBalancerWithSeedRouter ( ) { const pool = connectionPool || newPool() const loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy(pool) - const loadBalancer = new LoadBalancer( + const connectionProvider = new RoutingConnectionProvider( seedRouter, {}, pool, @@ -1187,49 +1235,71 @@ function newLoadBalancerWithSeedRouter ( NO_OP_DRIVER_CALLBACK, Logger.noOp() ) - loadBalancer._routingTable = new RoutingTable( + connectionProvider._routingTables[database] = new RoutingTable({ + database, routers, readers, writers, expirationTime - ) - loadBalancer._rediscovery = new FakeRediscovery(routerToRoutingTable) - loadBalancer._hostNameResolver = new FakeDnsResolver(seedRouterResolved) + }) + connectionProvider._rediscovery = new FakeRediscovery(routerToRoutingTable) + connectionProvider._hostNameResolver = new FakeDnsResolver(seedRouterResolved) if (expirationTime === Integer.ZERO) { - loadBalancer._useSeedRouter = false + connectionProvider._useSeedRouter = false } - return loadBalancer + return connectionProvider } function newRoutingTable ( + database, routers, readers, writers, expirationTime = Integer.MAX_VALUE ) { - return new RoutingTable(routers, readers, writers, expirationTime) + return new RoutingTable({ + database, + routers, + readers, + writers, + expirationTime + }) } -function setupLoadBalancerToRememberRouters (loadBalancer, routersArray) { - const originalFetch = loadBalancer._fetchRoutingTable.bind(loadBalancer) +function setupRoutingConnectionProviderToRememberRouters ( + connectionProvider, + routersArray +) { + const originalFetch = connectionProvider._fetchRoutingTable.bind( + connectionProvider + ) const rememberingFetch = (routerAddresses, routingTable) => { routersArray.push(routerAddresses) return originalFetch(routerAddresses, routingTable) } - loadBalancer._fetchRoutingTable = rememberingFetch + connectionProvider._fetchRoutingTable = rememberingFetch } function newPool () { return new Pool({ create: (address, release) => - Promise.resolve(new FakeConnection(address, release)) + Promise.resolve( + new FakeConnection(address, release, VERSION_IN_DEV.toString()) + ) }) } -function expectRoutingTable (loadBalancer, routers, readers, writers) { - expect(loadBalancer._routingTable.routers).toEqual(routers) - expect(loadBalancer._routingTable.readers).toEqual(readers) - expect(loadBalancer._routingTable.writers).toEqual(writers) +function expectRoutingTable ( + connectionProvider, + database, + routers, + readers, + writers +) { + expect(connectionProvider._routingTables[database].database).toEqual(database) + expect(connectionProvider._routingTables[database].routers).toEqual(routers) + expect(connectionProvider._routingTables[database].readers).toEqual(readers) + expect(connectionProvider._routingTables[database].writers).toEqual(writers) } function expectPoolToContain (pool, addresses) { @@ -1245,9 +1315,10 @@ function expectPoolToNotContain (pool, addresses) { } class FakeConnection { - constructor (address, release) { + constructor (address, release, version) { this.address = address this.release = release + this.version = () => VERSION_IN_DEV } } @@ -1256,7 +1327,7 @@ class FakeRediscovery { this._routerToRoutingTable = routerToRoutingTable } - lookupRoutingTableOnRouter (ignored, router) { + lookupRoutingTableOnRouter (ignored, database, router) { return Promise.resolve(this._routerToRoutingTable[router.asKey()]) } } diff --git a/test/internal/connectivity-verifier.test.js b/test/internal/connectivity-verifier.test.js index 1dd0af9d2..050ab82c4 100644 --- a/test/internal/connectivity-verifier.test.js +++ b/test/internal/connectivity-verifier.test.js @@ -18,7 +18,7 @@ */ import ConnectivityVerifier from '../../src/internal/connectivity-verifier' -import { SingleConnectionProvider } from '../../src/internal/connection-providers' +import SingleConnectionProvider from '../../src/internal/connection-provider-single' import FakeConnection from './fake-connection' describe('ConnectivityVerifier', () => { diff --git a/test/internal/fake-connection.js b/test/internal/fake-connection.js index 2df0b2b4d..68712d791 100644 --- a/test/internal/fake-connection.js +++ b/test/internal/fake-connection.js @@ -17,6 +17,8 @@ * limitations under the License. */ +import { ServerVersion } from '../../src/internal/server-version' + /** * This class is like a mock of {@link Connection} that tracks invocations count. * It tries to maintain same "interface" as {@link Connection}. @@ -36,6 +38,10 @@ export default class FakeConnection { this.server = {} } + version () { + return ServerVersion.fromString(this.server.version) + } + protocol () { // return fake protocol object that simply records seen statements and parameters return { diff --git a/test/internal/node/direct.driver.boltkit.test.js b/test/internal/node/direct.driver.boltkit.test.js index af587495f..27e49a366 100644 --- a/test/internal/node/direct.driver.boltkit.test.js +++ b/test/internal/node/direct.driver.boltkit.test.js @@ -296,7 +296,7 @@ describe('direct driver with stub server', () => { } const server = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_dead.script', 9001 ) diff --git a/test/internal/node/routing.driver.boltkit.test.js b/test/internal/node/routing.driver.boltkit.test.js index 0496617a2..1549a3536 100644 --- a/test/internal/node/routing.driver.boltkit.test.js +++ b/test/internal/node/routing.driver.boltkit.test.js @@ -139,7 +139,7 @@ describe('routing driver with stub server', () => { 9042 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) @@ -281,7 +281,7 @@ describe('routing driver with stub server', () => { 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) @@ -329,11 +329,11 @@ describe('routing driver with stub server', () => { 9003 ) const readServer1 = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9004 ) const readServer2 = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9006 ) @@ -385,11 +385,11 @@ describe('routing driver with stub server', () => { 9001 ) const readServer1 = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) const readServer2 = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9006 ) @@ -438,7 +438,7 @@ describe('routing driver with stub server', () => { 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_dead.script', 9005 ) @@ -471,7 +471,7 @@ describe('routing driver with stub server', () => { 9001 ) const writeServer = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write.script', 9007 ) @@ -504,11 +504,11 @@ describe('routing driver with stub server', () => { 9001 ) const readServer1 = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write.script', 9007 ) const readServer2 = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write.script', 9008 ) @@ -547,7 +547,7 @@ describe('routing driver with stub server', () => { 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_dead.script', 9007 ) @@ -580,7 +580,7 @@ describe('routing driver with stub server', () => { 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) @@ -620,7 +620,7 @@ describe('routing driver with stub server', () => { 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_dead.script', 9005 ) @@ -703,7 +703,7 @@ describe('routing driver with stub server', () => { 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) @@ -748,7 +748,7 @@ describe('routing driver with stub server', () => { session.run('MATCH (n) RETURN n.name').catch(err => { expect(err.code).toEqual(neo4j.error.SERVICE_UNAVAILABLE) expect(err.message).toContain('Could not perform discovery') - assertHasRouters(driver, []) + assertNoRoutingTable(driver) session.close() driver.close() server.exit(code => { @@ -1214,13 +1214,20 @@ describe('routing driver with stub server', () => { ) }) - it('should throw error when multiple records', done => { + it('should throw error when unparsable TTL entry', done => { testForProtocolError( './test/resources/boltstub/unparsable_ttl_get_servers.script', done ) }) + it('should throw error when multiple records', done => { + testForProtocolError( + './test/resources/boltstub/unparsable_multiple_records_get_servers.script', + done + ) + }) + it('should throw error on unparsable record', done => { testForProtocolError( './test/resources/boltstub/unparsable_servers_get_servers.script', @@ -1503,11 +1510,11 @@ describe('routing driver with stub server', () => { 9001 ) const brokenReader = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_tx_dead.script', 9005 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read_tx.script', 9006 ) @@ -1553,11 +1560,11 @@ describe('routing driver with stub server', () => { 9001 ) const brokenWriter = boltStub.start( - './test/resources/boltstub/dead_write_server.script', + './test/resources/boltstub/write_server_v2_write_tx_dead.script', 9007 ) const writer = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write_tx.script', 9008 ) @@ -1603,11 +1610,11 @@ describe('routing driver with stub server', () => { 9001 ) const brokenReader1 = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_tx_dead.script', 9005 ) const brokenReader2 = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_tx_dead.script', 9006 ) @@ -1659,11 +1666,11 @@ describe('routing driver with stub server', () => { 9001 ) const brokenWriter1 = boltStub.start( - './test/resources/boltstub/dead_write_server.script', + './test/resources/boltstub/write_server_v2_write_tx_dead.script', 9007 ) const brokenWriter2 = boltStub.start( - './test/resources/boltstub/dead_write_server.script', + './test/resources/boltstub/write_server_v2_write_tx_dead.script', 9008 ) @@ -1715,11 +1722,11 @@ describe('routing driver with stub server', () => { 9010 ) const brokenReader1 = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_tx_dead.script', 9005 ) const brokenReader2 = boltStub.start( - './test/resources/boltstub/dead_read_server.script', + './test/resources/boltstub/read_server_v2_read_tx_dead.script', 9006 ) const router2 = boltStub.start( @@ -1727,7 +1734,7 @@ describe('routing driver with stub server', () => { 9001 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read_tx.script', 9002 ) @@ -1779,11 +1786,11 @@ describe('routing driver with stub server', () => { 9010 ) const brokenWriter1 = boltStub.start( - './test/resources/boltstub/dead_write_server.script', + './test/resources/boltstub/write_server_v2_write_tx_dead.script', 9007 ) const brokenWriter2 = boltStub.start( - './test/resources/boltstub/dead_write_server.script', + './test/resources/boltstub/write_server_v2_write_tx_dead.script', 9008 ) const router2 = boltStub.start( @@ -1791,7 +1798,7 @@ describe('routing driver with stub server', () => { 9002 ) const writer = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write_tx.script', 9009 ) @@ -2047,11 +2054,11 @@ describe('routing driver with stub server', () => { 9010 ) const reader1 = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9003 ) const reader2 = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9004 ) @@ -2096,7 +2103,7 @@ describe('routing driver with stub server', () => { 9010 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9002 ) @@ -2141,7 +2148,7 @@ describe('routing driver with stub server', () => { 9004 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read_tx.script', 9003 ) @@ -2196,11 +2203,11 @@ describe('routing driver with stub server', () => { ) let router2 = null const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read_tx.script', 9003 ) const writer = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write.script', 9007 ) @@ -2268,11 +2275,11 @@ describe('routing driver with stub server', () => { 9020 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) const writer = boltStub.start( - './test/resources/boltstub/write_server.script', + './test/resources/boltstub/write_server_v2_write.script', 9007 ) @@ -2466,7 +2473,7 @@ describe('routing driver with stub server', () => { 9042 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read_tx.script', 9005 ) @@ -2874,7 +2881,7 @@ describe('routing driver with stub server', () => { const router = boltStub.start(routerScript, 9001) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) @@ -2996,51 +3003,55 @@ describe('routing driver with stub server', () => { return getConnectionPool(driver).has(ServerAddress.fromUrl(address)) } - function hasRouterInRoutingTable (driver, expectedRouter) { + function hasRouterInRoutingTable (driver, expectedRouter, database) { return ( - getRoutingTable(driver).routers.indexOf( + getRoutingTable(driver, database).routers.indexOf( ServerAddress.fromUrl(expectedRouter) ) > -1 ) } - function hasReaderInRoutingTable (driver, expectedReader) { + function hasReaderInRoutingTable (driver, expectedReader, database) { return ( - getRoutingTable(driver).readers.indexOf( + getRoutingTable(driver, database).readers.indexOf( ServerAddress.fromUrl(expectedReader) ) > -1 ) } - function hasWriterInRoutingTable (driver, expectedWriter) { + function hasWriterInRoutingTable (driver, expectedWriter, database) { return ( - getRoutingTable(driver).writers.indexOf( + getRoutingTable(driver, database).writers.indexOf( ServerAddress.fromUrl(expectedWriter) ) > -1 ) } - function assertHasRouters (driver, expectedRouters) { - expect(getRoutingTable(driver).routers.map(s => s.asHostPort())).toEqual( - expectedRouters - ) + function assertNoRoutingTable (driver, database) { + expect(getRoutingTable(driver, database)).toBeFalsy() } - function assertHasReaders (driver, expectedReaders) { - expect(getRoutingTable(driver).readers.map(s => s.asHostPort())).toEqual( - expectedReaders - ) + function assertHasRouters (driver, expectedRouters, database) { + expect( + getRoutingTable(driver, database).routers.map(s => s.asHostPort()) + ).toEqual(expectedRouters) } - function assertHasWriters (driver, expectedWriters) { - expect(getRoutingTable(driver).writers.map(s => s.asHostPort())).toEqual( - expectedWriters - ) + function assertHasReaders (driver, expectedReaders, database) { + expect( + getRoutingTable(driver, database).readers.map(s => s.asHostPort()) + ).toEqual(expectedReaders) } - function setUpMemorizingRoutingTable (driver) { + function assertHasWriters (driver, expectedWriters, database) { + expect( + getRoutingTable(driver, database).writers.map(s => s.asHostPort()) + ).toEqual(expectedWriters) + } + + function setUpMemorizingRoutingTable (driver, database) { const memorizingRoutingTable = new MemorizingRoutingTable( - getRoutingTable(driver) + getRoutingTable(driver, database) ) setRoutingTable(driver, memorizingRoutingTable) return memorizingRoutingTable @@ -3063,14 +3074,16 @@ describe('routing driver with stub server', () => { return connectionProvider._connectionPool } - function getRoutingTable (driver) { + function getRoutingTable (driver, database) { const connectionProvider = driver._getOrCreateConnectionProvider() - return connectionProvider._routingTable + return connectionProvider._routingTables[database || ''] } function setRoutingTable (driver, newRoutingTable) { const connectionProvider = driver._getOrCreateConnectionProvider() - connectionProvider._routingTable = newRoutingTable + connectionProvider._routingTables[ + newRoutingTable.database + ] = newRoutingTable } function joinStrings (array) { @@ -3092,7 +3105,7 @@ describe('routing driver with stub server', () => { 9010 ) const reader = boltStub.start( - './test/resources/boltstub/read_server.script', + './test/resources/boltstub/read_server_v2_read.script', 9005 ) @@ -3172,12 +3185,13 @@ describe('routing driver with stub server', () => { class MemorizingRoutingTable extends RoutingTable { constructor (initialTable) { - super( - initialTable.routers, - initialTable.readers, - initialTable.writers, - initialTable.expirationTime - ) + super({ + database: initialTable.database, + routers: initialTable.routers, + readers: initialTable.readers, + writers: initialTable.writers, + expirationTime: initialTable.expirationTime + }) this._forgottenRouters = [] } diff --git a/test/internal/rediscovery.test.js b/test/internal/rediscovery.test.js index 3e2546631..e72881e7f 100644 --- a/test/internal/rediscovery.test.js +++ b/test/internal/rediscovery.test.js @@ -219,7 +219,7 @@ describe('rediscovery', () => { function lookupRoutingTableOnRouter (routingUtil) { const rediscovery = new Rediscovery(routingUtil) - return rediscovery.lookupRoutingTableOnRouter(null, ROUTER_ADDRESS) + return rediscovery.lookupRoutingTableOnRouter(null, null, ROUTER_ADDRESS) } function expectProtocolError (error, messagePrefix) { diff --git a/test/internal/routing-table.test.js b/test/internal/routing-table.test.js index d3febe1bf..f880874b0 100644 --- a/test/internal/routing-table.test.js +++ b/test/internal/routing-table.test.js @@ -21,7 +21,7 @@ import { int } from '../../src/integer' import { READ, WRITE } from '../../src/driver' import ServerAddress from '../../src/internal/server-address' -describe('routing-table', () => { +describe('RoutingTable', () => { const server1 = ServerAddress.fromUrl('server1') const server2 = ServerAddress.fromUrl('server2') const server3 = ServerAddress.fromUrl('server3') @@ -190,10 +190,11 @@ describe('routing-table', () => { [server1, server2], [server3, server4], [server5, server6], - 42 + 42, + 'myDatabase' ) expect(table.toString()).toEqual( - 'RoutingTable[expirationTime=42, currentTime=4242, routers=[server1:7687,server2:7687], readers=[server3:7687,server4:7687], writers=[server5:7687,server6:7687]]' + 'RoutingTable[database=myDatabase, expirationTime=42, currentTime=4242, routers=[server1:7687,server2:7687], readers=[server3:7687,server4:7687], writers=[server5:7687,server6:7687]]' ) } finally { Date.now = originalDateNow @@ -208,8 +209,13 @@ describe('routing-table', () => { return Date.now() + 3600 // will expire in an hour } - function createTable (routers, readers, writers, expirationTime) { - const expiration = int(expirationTime) - return new RoutingTable(routers, readers, writers, expiration) + function createTable (routers, readers, writers, expirationTime, database) { + return new RoutingTable({ + database, + routers, + readers, + writers, + expirationTime: int(expirationTime) + }) } }) diff --git a/test/internal/routing-util.test.js b/test/internal/routing-util.test.js index d681b6e6e..60ef190de 100644 --- a/test/internal/routing-util.test.js +++ b/test/internal/routing-util.test.js @@ -45,7 +45,7 @@ describe('RoutingUtil', () => { it('should return retrieved records when query succeeds', done => { const session = FakeSession.successful({ records: ['foo', 'bar', 'baz'] }) - callRoutingProcedure(session) + callRoutingProcedure(session, '') .then(records => { expect(records).toEqual(['foo', 'bar', 'baz']) done() @@ -56,7 +56,7 @@ describe('RoutingUtil', () => { it('should close session when query succeeds', done => { const session = FakeSession.successful({ records: ['foo', 'bar', 'baz'] }) - callRoutingProcedure(session) + callRoutingProcedure(session, '') .then(() => { expect(session.isClosed()).toBeTruthy() done() @@ -67,7 +67,7 @@ describe('RoutingUtil', () => { it('should not close session when query fails', done => { const session = FakeSession.failed(newError('Oh no!', SESSION_EXPIRED)) - callRoutingProcedure(session) + callRoutingProcedure(session, '') .then(() => { expect(session.isClosed()).toBeFalsy() done() @@ -78,7 +78,7 @@ describe('RoutingUtil', () => { it('should return null on connection error', done => { const session = FakeSession.failed(newError('Oh no!', SESSION_EXPIRED)) - callRoutingProcedure(session) + callRoutingProcedure(session, '') .then(records => { expect(records).toBeNull() done() @@ -91,7 +91,7 @@ describe('RoutingUtil', () => { newError('Oh no!', 'Neo.ClientError.Procedure.ProcedureNotFound') ) - callRoutingProcedure(session).catch(error => { + callRoutingProcedure(session, '').catch(error => { expect(error.code).toBe(SERVICE_UNAVAILABLE) expect(error.message).toBe( `Server at ${ROUTER_ADDRESS} can't perform routing. Make sure you are connecting to a causal cluster` @@ -104,7 +104,7 @@ describe('RoutingUtil', () => { const connection = new FakeConnection().withServerVersion('Neo4j/3.1.9') const session = FakeSession.withFakeConnection(connection) - callRoutingProcedure(session, {}).then(() => { + callRoutingProcedure(session, '', {}).then(() => { expect(connection.seenStatements).toEqual([ 'CALL dbms.cluster.routing.getServers' ]) @@ -117,7 +117,7 @@ describe('RoutingUtil', () => { const connection = new FakeConnection().withServerVersion('Neo4j/3.2.0') const session = FakeSession.withFakeConnection(connection) - callRoutingProcedure(session, {}).then(() => { + callRoutingProcedure(session, '', {}).then(() => { expect(connection.seenStatements).toEqual([ 'CALL dbms.cluster.routing.getRoutingTable($context)' ]) @@ -130,7 +130,7 @@ describe('RoutingUtil', () => { const connection = new FakeConnection().withServerVersion('Neo4j/3.2.0') const session = FakeSession.withFakeConnection(connection) - callRoutingProcedure(session, { key1: 'value1', key2: 'value2' }).then( + callRoutingProcedure(session, '', { key1: 'value1', key2: 'value2' }).then( () => { expect(connection.seenStatements).toEqual([ 'CALL dbms.cluster.routing.getRoutingTable($context)' @@ -147,7 +147,7 @@ describe('RoutingUtil', () => { const connection = new FakeConnection().withServerVersion('Neo4j/3.3.5') const session = FakeSession.withFakeConnection(connection) - callRoutingProcedure(session, {}).then(() => { + callRoutingProcedure(session, '', {}).then(() => { expect(connection.seenStatements).toEqual([ 'CALL dbms.cluster.routing.getRoutingTable($context)' ]) @@ -160,7 +160,7 @@ describe('RoutingUtil', () => { const connection = new FakeConnection().withServerVersion('Neo4j/3.2.8') const session = FakeSession.withFakeConnection(connection) - callRoutingProcedure(session, { key1: 'foo', key2: 'bar' }).then(() => { + callRoutingProcedure(session, '', { key1: 'foo', key2: 'bar' }).then(() => { expect(connection.seenStatements).toEqual([ 'CALL dbms.cluster.routing.getRoutingTable($context)' ]) @@ -171,6 +171,26 @@ describe('RoutingUtil', () => { }) }) + it('should use getRoutingTable procedure without database and routing context when server version is newer than 4.0.0', done => { + testMultiDbRoutingProcedure({}, '', done) + }) + + it('should use getRoutingTable procedure without database but routing context when server version is newer than 4.0.0', done => { + testMultiDbRoutingProcedure({ key1: 'foo', key2: 'bar' }, '', done) + }) + + it('should use getRoutingTable procedure without routing context but database when server version is newer than 4.0.0', done => { + testMultiDbRoutingProcedure({}, 'myDatabase', done) + }) + + it('should use getRoutingTable procedure with database and routing context when server version is newer than 4.0.0', done => { + testMultiDbRoutingProcedure( + { key1: 'foo', key2: 'bar' }, + 'myDatabase', + done + ) + }) + it('should parse valid ttl', () => { clock = lolex.install() @@ -301,6 +321,19 @@ describe('RoutingUtil', () => { expectProtocolError(() => parseServers(record), done) }) + function testMultiDbRoutingProcedure (context, database, done) { + const connection = new FakeConnection().withServerVersion('Neo4j/4.0.0') + const session = FakeSession.withFakeConnection(connection) + + callRoutingProcedure(session, database, context).then(() => { + expect(connection.seenStatements).toEqual([ + 'CALL dbms.routing.getRoutingTable($context, $database)' + ]) + expect(connection.seenParameters).toEqual([{ context, database }]) + done() + }) + } + function testValidTtlParsing (currentTime, ttlSeconds) { clock.setSystemTime(currentTime) const expectedExpirationTime = currentTime + ttlSeconds * 1000 @@ -334,9 +367,9 @@ describe('RoutingUtil', () => { expect(writers).toEqual(writerAddresses.map(w => ServerAddress.fromUrl(w))) } - function callRoutingProcedure (session, routingContext) { + function callRoutingProcedure (session, database, routingContext) { const util = new RoutingUtil(routingContext || {}) - return util.callRoutingProcedure(session, ROUTER_ADDRESS) + return util.callRoutingProcedure(session, database, ROUTER_ADDRESS) } function parseTtl (record) { diff --git a/test/resources/boltstub/acquire_endpoints.script b/test/resources/boltstub/acquire_endpoints.script index ece22ad3a..6589ecd52 100644 --- a/test/resources/boltstub/acquire_endpoints.script +++ b/test/resources/boltstub/acquire_endpoints.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/acquire_endpoints_and_exit.script b/test/resources/boltstub/acquire_endpoints_and_exit.script index 3ba38fcb5..6349c8367 100644 --- a/test/resources/boltstub/acquire_endpoints_and_exit.script +++ b/test/resources/boltstub/acquire_endpoints_and_exit.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script b/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script index 9846be014..143326ce9 100644 --- a/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script +++ b/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script @@ -1,5 +1,5 @@ +!: BOLT 1 !: AUTO RESET -!: AUTO PULL_ALL C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} S: SUCCESS {"server": "Neo4j/3.1.0"} diff --git a/test/resources/boltstub/acquire_endpoints_v3.script b/test/resources/boltstub/acquire_endpoints_v3.script index 42541782e..aaa1b7e94 100644 --- a/test/resources/boltstub/acquire_endpoints_v3.script +++ b/test/resources/boltstub/acquire_endpoints_v3.script @@ -1,8 +1,7 @@ !: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: HELLO {"scheme": "basic", "principal": "neo4j", "credentials": "password", "user_agent": "neo4j-javascript/0.0.0-dev"} -S: SUCCESS {"server": "Neo4j/9.9.9", "connection_id": "bolt-123456789"} C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} diff --git a/test/resources/boltstub/acquire_endpoints_with_one_of_each.script b/test/resources/boltstub/acquire_endpoints_with_one_of_each.script index 4fd9a46ee..fbc7bcb9d 100644 --- a/test/resources/boltstub/acquire_endpoints_with_one_of_each.script +++ b/test/resources/boltstub/acquire_endpoints_with_one_of_each.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/address_unavailable_template.script.mst b/test/resources/boltstub/address_unavailable_template.script.mst index 7c17ef189..799245ca6 100644 --- a/test/resources/boltstub/address_unavailable_template.script.mst +++ b/test/resources/boltstub/address_unavailable_template.script.mst @@ -1,9 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "ROLLBACK" {} -!: AUTO RUN "BEGIN" {} -!: AUTO RUN "COMMIT" {} C: RUN "{{{query}}}" {} C: PULL_ALL diff --git a/test/resources/boltstub/dead_routing_server.script b/test/resources/boltstub/dead_routing_server.script index fe84ce082..9a0770c97 100644 --- a/test/resources/boltstub/dead_routing_server.script +++ b/test/resources/boltstub/dead_routing_server.script @@ -1,7 +1,7 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} -C: PULL_ALL + PULL_ALL S: diff --git a/test/resources/boltstub/discover_ipv6_servers_and_read.script b/test/resources/boltstub/discover_ipv6_servers_and_read.script index 49ff5775a..449ddbea0 100644 --- a/test/resources/boltstub/discover_ipv6_servers_and_read.script +++ b/test/resources/boltstub/discover_ipv6_servers_and_read.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/discover_new_servers.script b/test/resources/boltstub/discover_new_servers.script index c74980ad3..d14c497cf 100644 --- a/test/resources/boltstub/discover_new_servers.script +++ b/test/resources/boltstub/discover_new_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/discover_no_writers.script b/test/resources/boltstub/discover_no_writers.script index e1b02efe7..1077d40d3 100644 --- a/test/resources/boltstub/discover_no_writers.script +++ b/test/resources/boltstub/discover_no_writers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/discover_one_router.script b/test/resources/boltstub/discover_one_router.script index ec15e4a07..99fd32e5c 100644 --- a/test/resources/boltstub/discover_one_router.script +++ b/test/resources/boltstub/discover_one_router.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/discover_servers.script b/test/resources/boltstub/discover_servers.script index ed355f58f..c482cf66d 100644 --- a/test/resources/boltstub/discover_servers.script +++ b/test/resources/boltstub/discover_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/discover_servers_and_read.script b/test/resources/boltstub/discover_servers_and_read.script index 543f6fd40..89acf19ac 100644 --- a/test/resources/boltstub/discover_servers_and_read.script +++ b/test/resources/boltstub/discover_servers_and_read.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/empty_get_servers_response.script b/test/resources/boltstub/empty_get_servers_response.script index 7fc0029e8..173c151fa 100644 --- a/test/resources/boltstub/empty_get_servers_response.script +++ b/test/resources/boltstub/empty_get_servers_response.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/failed_auth.script b/test/resources/boltstub/failed_auth.script index be445b64b..3bc89f417 100644 --- a/test/resources/boltstub/failed_auth.script +++ b/test/resources/boltstub/failed_auth.script @@ -1,5 +1,5 @@ +!: BOLT 2 !: AUTO RESET -!: AUTO PULL_ALL C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} S: FAILURE {"code": "Neo.ClientError.Security.Unauthorized", "message": "Some server auth error message"} diff --git a/test/resources/boltstub/get_routing_table.script b/test/resources/boltstub/get_routing_table.script index f795641b7..7a550f9e6 100644 --- a/test/resources/boltstub/get_routing_table.script +++ b/test/resources/boltstub/get_routing_table.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL S: SUCCESS {"server": "Neo4j/3.2.2"} C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} diff --git a/test/resources/boltstub/get_routing_table_with_context.script b/test/resources/boltstub/get_routing_table_with_context.script index 4c62ade04..9c663f101 100644 --- a/test/resources/boltstub/get_routing_table_with_context.script +++ b/test/resources/boltstub/get_routing_table_with_context.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL S: SUCCESS {"server": "Neo4j/3.2.3"} C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {"policy": "my_policy", "region": "china"}} diff --git a/test/resources/boltstub/multiple_bookmarks.script b/test/resources/boltstub/multiple_bookmarks.script index 5e7344103..88580188b 100644 --- a/test/resources/boltstub/multiple_bookmarks.script +++ b/test/resources/boltstub/multiple_bookmarks.script @@ -1,16 +1,16 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx94", "bookmarks": ["neo4j:bookmark:v1:tx5", "neo4j:bookmark:v1:tx29", "neo4j:bookmark:v1:tx94", "neo4j:bookmark:v1:tx56", "neo4j:bookmark:v1:tx16", "neo4j:bookmark:v1:tx68"]} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "CREATE (n {name:'Bob'})" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {"bookmark": "neo4j:bookmark:v1:tx95"} C: RUN "COMMIT" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/resources/boltstub/multiple_records_get_servers.script b/test/resources/boltstub/multiple_records_get_servers.script index c1b6d2761..3fed74124 100644 --- a/test/resources/boltstub/multiple_records_get_servers.script +++ b/test/resources/boltstub/multiple_records_get_servers.script @@ -1,6 +1,5 @@ !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/no_readers_get_servers.script b/test/resources/boltstub/no_readers_get_servers.script index b664e9427..9a1084784 100644 --- a/test/resources/boltstub/no_readers_get_servers.script +++ b/test/resources/boltstub/no_readers_get_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/no_routers_get_servers.script b/test/resources/boltstub/no_routers_get_servers.script index 3cec77bcc..7b4a2bd21 100644 --- a/test/resources/boltstub/no_routers_get_servers.script +++ b/test/resources/boltstub/no_routers_get_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/no_servers_entry_get_servers.script b/test/resources/boltstub/no_servers_entry_get_servers.script index 191485641..9cfc845ca 100644 --- a/test/resources/boltstub/no_servers_entry_get_servers.script +++ b/test/resources/boltstub/no_servers_entry_get_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/no_ttl_entry_get_servers.script b/test/resources/boltstub/no_ttl_entry_get_servers.script index 0cd7a4872..162f38040 100644 --- a/test/resources/boltstub/no_ttl_entry_get_servers.script +++ b/test/resources/boltstub/no_ttl_entry_get_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/no_writers.script b/test/resources/boltstub/no_writers.script index 309e842ad..7bba701e0 100644 --- a/test/resources/boltstub/no_writers.script +++ b/test/resources/boltstub/no_writers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/non_discovery.script b/test/resources/boltstub/non_discovery.script index ddef42ae2..630d8f75a 100644 --- a/test/resources/boltstub/non_discovery.script +++ b/test/resources/boltstub/non_discovery.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} C: PULL_ALL diff --git a/test/resources/boltstub/not_able_to_write.script b/test/resources/boltstub/not_able_to_write.script index 6f14544b5..43fd25273 100644 --- a/test/resources/boltstub/not_able_to_write.script +++ b/test/resources/boltstub/not_able_to_write.script @@ -1,12 +1,8 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO DISCARD_ALL -!: AUTO RUN "ROLLBACK" {} -!: AUTO RUN "BEGIN" {} -!: AUTO PULL_ALL C: RUN "CREATE ()" {} -C: PULL_ALL + PULL_ALL S: FAILURE {"code": "Neo.ClientError.Cluster.NotALeader", "message": "blabla"} -S: IGNORED \ No newline at end of file + IGNORED diff --git a/test/resources/boltstub/not_able_to_write_in_transaction.script b/test/resources/boltstub/not_able_to_write_in_transaction.script index a09382494..55da234ee 100644 --- a/test/resources/boltstub/not_able_to_write_in_transaction.script +++ b/test/resources/boltstub/not_able_to_write_in_transaction.script @@ -1,14 +1,14 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO DISCARD_ALL -!: AUTO RUN "ROLLBACK" {} -!: AUTO RUN "BEGIN" {} -!: AUTO PULL_ALL -C: RUN "CREATE ()" {} -C: PULL_ALL +C: RUN "BEGIN" {} + PULL_ALL + RUN "CREATE ()" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} S: FAILURE {"code": "Neo.ClientError.Cluster.NotALeader", "message": "blabla"} S: IGNORED C: RUN "COMMIT" {} -S: IGNORED \ No newline at end of file +S: IGNORED diff --git a/test/resources/boltstub/one_of_each_template.script.mst b/test/resources/boltstub/one_of_each_template.script.mst index 17c24a18f..519b11ead 100644 --- a/test/resources/boltstub/one_of_each_template.script.mst +++ b/test/resources/boltstub/one_of_each_template.script.mst @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/query_with_error.script b/test/resources/boltstub/query_with_error.script index 1c0b51bfc..3b24f6aa6 100644 --- a/test/resources/boltstub/query_with_error.script +++ b/test/resources/boltstub/query_with_error.script @@ -1,5 +1,5 @@ +!: BOLT 2 !: AUTO INIT -!: AUTO PULL_ALL C: RUN "RETURN 10 / 0" {} C: PULL_ALL diff --git a/test/resources/boltstub/read_server_and_exit.script b/test/resources/boltstub/read_server_and_exit.script index 3f86bd6e0..9144c40da 100644 --- a/test/resources/boltstub/read_server_and_exit.script +++ b/test/resources/boltstub/read_server_and_exit.script @@ -1,9 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "COMMIT" {} -!: AUTO RUN "ROLLBACK" {} -!: AUTO RUN "BEGIN" {} C: RUN "MATCH (n) RETURN n.name" {} PULL_ALL diff --git a/test/resources/boltstub/read_server.script b/test/resources/boltstub/read_server_v2_read.script similarity index 66% rename from test/resources/boltstub/read_server.script rename to test/resources/boltstub/read_server_v2_read.script index 7fb3d6c81..e11588f85 100644 --- a/test/resources/boltstub/read_server.script +++ b/test/resources/boltstub/read_server_v2_read.script @@ -1,9 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "COMMIT" {} -!: AUTO RUN "ROLLBACK" {} -!: AUTO RUN "BEGIN" {} C: RUN "MATCH (n) RETURN n.name" {} PULL_ALL diff --git a/test/resources/boltstub/dead_read_server.script b/test/resources/boltstub/read_server_v2_read_dead.script similarity index 68% rename from test/resources/boltstub/dead_read_server.script rename to test/resources/boltstub/read_server_v2_read_dead.script index 4af7ef3b6..a6a261867 100644 --- a/test/resources/boltstub/dead_read_server.script +++ b/test/resources/boltstub/read_server_v2_read_dead.script @@ -1,7 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "BEGIN" {} C: RUN "MATCH (n) RETURN n.name" {} C: PULL_ALL diff --git a/test/resources/boltstub/read_server_v2_read_tx.script b/test/resources/boltstub/read_server_v2_read_tx.script new file mode 100644 index 000000000..c0903de9c --- /dev/null +++ b/test/resources/boltstub/read_server_v2_read_tx.script @@ -0,0 +1,19 @@ +!: BOLT 2 +!: AUTO INIT +!: AUTO RESET + +C: RUN "BEGIN" {} + PULL_ALL + RUN "MATCH (n) RETURN n.name" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} + SUCCESS {"fields": ["n.name"]} + RECORD ["Bob"] + RECORD ["Alice"] + RECORD ["Tina"] + SUCCESS {} +C: RUN "COMMIT" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {"bookmark": "ABookmark"} diff --git a/test/resources/boltstub/read_server_v2_read_tx_dead.script b/test/resources/boltstub/read_server_v2_read_tx_dead.script new file mode 100644 index 000000000..44367b2fb --- /dev/null +++ b/test/resources/boltstub/read_server_v2_read_tx_dead.script @@ -0,0 +1,11 @@ +!: BOLT 2 +!: AUTO INIT +!: AUTO RESET + +C: RUN "BEGIN" {} + PULL_ALL + RUN "MATCH (n) RETURN n.name" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} + diff --git a/test/resources/boltstub/read_server_with_version.script b/test/resources/boltstub/read_server_with_version.script index b609e2cd9..237de2d0e 100644 --- a/test/resources/boltstub/read_server_with_version.script +++ b/test/resources/boltstub/read_server_with_version.script @@ -1,5 +1,5 @@ +!: BOLT 2 !: AUTO RESET -!: AUTO PULL_ALL C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} S: SUCCESS {"server": "Neo4j/8.8.8"} diff --git a/test/resources/boltstub/read_tx_with_bookmarks.script b/test/resources/boltstub/read_tx_with_bookmarks.script index cb22ffba3..1b450a304 100644 --- a/test/resources/boltstub/read_tx_with_bookmarks.script +++ b/test/resources/boltstub/read_tx_with_bookmarks.script @@ -1,6 +1,5 @@ !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx42", "bookmarks": ["neo4j:bookmark:v1:tx42"]} PULL_ALL diff --git a/test/resources/boltstub/rediscover.script b/test/resources/boltstub/rediscover.script index f5c8404fe..571e56bfc 100644 --- a/test/resources/boltstub/rediscover.script +++ b/test/resources/boltstub/rediscover.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/rediscover_and_read_with_init.script b/test/resources/boltstub/rediscover_and_read_with_init.script index c2ce54c6f..9a39541e2 100644 --- a/test/resources/boltstub/rediscover_and_read_with_init.script +++ b/test/resources/boltstub/rediscover_and_read_with_init.script @@ -1,6 +1,6 @@ +!: BOLT 1 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL S: SUCCESS {"server": "Neo4j/3.1.0"} C: RUN "CALL dbms.cluster.routing.getServers" {} diff --git a/test/resources/boltstub/rediscover_using_initial_router.script b/test/resources/boltstub/rediscover_using_initial_router.script index a5d3e7362..5535536dc 100644 --- a/test/resources/boltstub/rediscover_using_initial_router.script +++ b/test/resources/boltstub/rediscover_using_initial_router.script @@ -1,18 +1,23 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "BEGIN" {} -!: AUTO RUN "COMMIT" {} -!: AUTO RUN "ROLLBACK" {} C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9001","127.0.0.1:9009","127.0.0.1:9010"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9011"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n.name AS name" {} +C: RUN "BEGIN" {} PULL_ALL -S: SUCCESS {"fields": ["name"]} + RUN "MATCH (n) RETURN n.name AS name" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} + SUCCESS {"fields": ["name"]} RECORD ["Bob"] RECORD ["Alice"] SUCCESS {} +C: RUN "COMMIT" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/reset_error.script b/test/resources/boltstub/reset_error.script index e335d5c59..2187f4709 100644 --- a/test/resources/boltstub/reset_error.script +++ b/test/resources/boltstub/reset_error.script @@ -1,3 +1,4 @@ +!: BOLT 2 !: AUTO INIT C: RUN "RETURN 42 AS answer" {} diff --git a/test/resources/boltstub/return_x.script b/test/resources/boltstub/return_x.script index 7995e933e..b628d358f 100644 --- a/test/resources/boltstub/return_x.script +++ b/test/resources/boltstub/return_x.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "RETURN {x}" {"x": 1} PULL_ALL diff --git a/test/resources/boltstub/routing_table_with_zero_ttl.script b/test/resources/boltstub/routing_table_with_zero_ttl.script index 1547ea461..99ae03aaa 100644 --- a/test/resources/boltstub/routing_table_with_zero_ttl.script +++ b/test/resources/boltstub/routing_table_with_zero_ttl.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/short_ttl.script b/test/resources/boltstub/short_ttl.script index 63eae3d82..80d9a50f4 100644 --- a/test/resources/boltstub/short_ttl.script +++ b/test/resources/boltstub/short_ttl.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/single_write_server.script b/test/resources/boltstub/single_write_server.script index 90a541b98..cc2f0b676 100644 --- a/test/resources/boltstub/single_write_server.script +++ b/test/resources/boltstub/single_write_server.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/two_write_responses_server.script b/test/resources/boltstub/two_write_responses_server.script index 8e2e381f1..c58848d7d 100644 --- a/test/resources/boltstub/two_write_responses_server.script +++ b/test/resources/boltstub/two_write_responses_server.script @@ -1,12 +1,12 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CREATE (n {name:'Bob'})" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "CREATE ()" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/resources/boltstub/unparsable_multiple_records_get_servers.script b/test/resources/boltstub/unparsable_multiple_records_get_servers.script new file mode 100644 index 000000000..fe0d07df9 --- /dev/null +++ b/test/resources/boltstub/unparsable_multiple_records_get_servers.script @@ -0,0 +1,10 @@ +!: BOLT 2 +!: AUTO INIT +!: AUTO RESET + +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} + PULL_ALL +S: SUCCESS {"fields": ["ttl", "servers"]} + RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] + RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] + SUCCESS {} diff --git a/test/resources/boltstub/unparsable_servers_get_servers.script b/test/resources/boltstub/unparsable_servers_get_servers.script index 9ca1dbc07..3e3c57bc0 100644 --- a/test/resources/boltstub/unparsable_servers_get_servers.script +++ b/test/resources/boltstub/unparsable_servers_get_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/unparsable_ttl_get_servers.script b/test/resources/boltstub/unparsable_ttl_get_servers.script index 96b4fc5a9..4f135ac51 100644 --- a/test/resources/boltstub/unparsable_ttl_get_servers.script +++ b/test/resources/boltstub/unparsable_ttl_get_servers.script @@ -1,6 +1,6 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} PULL_ALL diff --git a/test/resources/boltstub/write_read_tx_with_bookmark_override.script b/test/resources/boltstub/write_read_tx_with_bookmark_override.script index 238d55b09..7de0f648e 100644 --- a/test/resources/boltstub/write_read_tx_with_bookmark_override.script +++ b/test/resources/boltstub/write_read_tx_with_bookmark_override.script @@ -1,22 +1,22 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx42", "bookmarks": ["neo4j:bookmark:v1:tx42"]} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "CREATE (n {name:'Bob'})" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} C: RUN "COMMIT" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx99", "bookmarks": ["neo4j:bookmark:v1:tx99"]} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "MATCH (n) RETURN n.name AS name" {} PULL_ALL @@ -25,6 +25,6 @@ S: SUCCESS {"fields": ["name"]} SUCCESS {"bookmark": "neo4j:bookmark:v1:tx424242"} C: RUN "COMMIT" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/resources/boltstub/write_read_tx_with_bookmarks.script b/test/resources/boltstub/write_read_tx_with_bookmarks.script index fc4a18e3a..907ce86d5 100644 --- a/test/resources/boltstub/write_read_tx_with_bookmarks.script +++ b/test/resources/boltstub/write_read_tx_with_bookmarks.script @@ -1,22 +1,22 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx42", "bookmarks": ["neo4j:bookmark:v1:tx42"]} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "CREATE (n {name:'Bob'})" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} C: RUN "COMMIT" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx4242", "bookmarks": ["neo4j:bookmark:v1:tx4242"]} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "MATCH (n) RETURN n.name AS name" {} PULL_ALL @@ -25,6 +25,6 @@ S: SUCCESS {"fields": ["name"]} SUCCESS {"bookmark": "neo4j:bookmark:v1:tx424242"} C: RUN "COMMIT" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/resources/boltstub/write_server.script b/test/resources/boltstub/write_server.script deleted file mode 100644 index 4667e3609..000000000 --- a/test/resources/boltstub/write_server.script +++ /dev/null @@ -1,11 +0,0 @@ -!: AUTO INIT -!: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "COMMIT" {} -!: AUTO RUN "ROLLBACK" {} -!: AUTO RUN "BEGIN" {} - -C: RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {} - SUCCESS {} diff --git a/test/resources/boltstub/dead_write_server.script b/test/resources/boltstub/write_server_v2_write.script similarity index 50% rename from test/resources/boltstub/dead_write_server.script rename to test/resources/boltstub/write_server_v2_write.script index ac36bc249..411f7e427 100644 --- a/test/resources/boltstub/dead_write_server.script +++ b/test/resources/boltstub/write_server_v2_write.script @@ -1,8 +1,8 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL -!: AUTO RUN "BEGIN" {} C: RUN "CREATE (n {name:'Bob'})" {} -C: PULL_ALL -S: + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/write_server_v2_write_tx.script b/test/resources/boltstub/write_server_v2_write_tx.script new file mode 100644 index 000000000..25877b95a --- /dev/null +++ b/test/resources/boltstub/write_server_v2_write_tx.script @@ -0,0 +1,16 @@ +!: BOLT 2 +!: AUTO INIT +!: AUTO RESET + +C: RUN "BEGIN" {} + PULL_ALL + RUN "CREATE (n {name:'Bob'})" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {} +C: RUN "COMMIT" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/write_server_v2_write_tx_dead.script b/test/resources/boltstub/write_server_v2_write_tx_dead.script new file mode 100644 index 000000000..81c78817d --- /dev/null +++ b/test/resources/boltstub/write_server_v2_write_tx_dead.script @@ -0,0 +1,11 @@ +!: BOLT 2 +!: AUTO INIT +!: AUTO RESET + +C: RUN "BEGIN" {} + PULL_ALL + RUN "CREATE (n {name:'Bob'})" {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} +S: diff --git a/test/resources/boltstub/write_server_v3_write.script b/test/resources/boltstub/write_server_v3_write.script index be5b735f3..ca37a38c1 100644 --- a/test/resources/boltstub/write_server_v3_write.script +++ b/test/resources/boltstub/write_server_v3_write.script @@ -1,9 +1,8 @@ !: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: HELLO {"scheme": "basic", "principal": "neo4j", "credentials": "password", "user_agent": "neo4j-javascript/0.0.0-dev"} -S: SUCCESS {"server": "Neo4j/9.9.9", "connection_id": "bolt-123456789"} C: RUN "CREATE (n {name:'Bob'})" {} {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/resources/boltstub/write_server_v3_write_tx.script b/test/resources/boltstub/write_server_v3_write_tx.script index 4bb548cf3..b57159066 100644 --- a/test/resources/boltstub/write_server_v3_write_tx.script +++ b/test/resources/boltstub/write_server_v3_write_tx.script @@ -1,13 +1,12 @@ !: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: HELLO {"scheme": "basic", "principal": "neo4j", "credentials": "password", "user_agent": "neo4j-javascript/0.0.0-dev"} -S: SUCCESS {"server": "Neo4j/9.9.9", "connection_id": "bolt-123456789"} C: BEGIN {} S: SUCCESS {} C: RUN "CREATE (n {name:'Bob'})" {} {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: COMMIT S: SUCCESS { "bookmark": "ABookmark" } diff --git a/test/resources/boltstub/write_server_with_version.script b/test/resources/boltstub/write_server_with_version.script index 1432c5150..a22309325 100644 --- a/test/resources/boltstub/write_server_with_version.script +++ b/test/resources/boltstub/write_server_with_version.script @@ -1,9 +1,9 @@ +!: BOLT 2 !: AUTO RESET -!: AUTO PULL_ALL C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} S: SUCCESS {"server": "Neo4j/9.9.9"} C: RUN "CREATE (n {name:'Bob'})" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/resources/boltstub/write_tx_with_bookmarks.script b/test/resources/boltstub/write_tx_with_bookmarks.script index 82269cb37..17ceb54c6 100644 --- a/test/resources/boltstub/write_tx_with_bookmarks.script +++ b/test/resources/boltstub/write_tx_with_bookmarks.script @@ -1,16 +1,16 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET -!: AUTO PULL_ALL C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx42", "bookmarks": ["neo4j:bookmark:v1:tx42"]} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} C: RUN "CREATE (n {name:'Bob'})" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} C: RUN "COMMIT" {} PULL_ALL -S: SUCCESS {} +S: SUCCESS {"fields": []} SUCCESS {} diff --git a/test/session.test.js b/test/session.test.js index 163f88d75..e5663e1f7 100644 --- a/test/session.test.js +++ b/test/session.test.js @@ -21,7 +21,7 @@ import neo4j from '../src' import { statementType } from '../src/result-summary' import Session from '../src/session' import { READ } from '../src/driver' -import { SingleConnectionProvider } from '../src/internal/connection-providers' +import SingleConnectionProvider from '../src/internal/connection-provider-single' import FakeConnection from './internal/fake-connection' import sharedNeo4j from './internal/shared-neo4j' import _ from 'lodash' From 1b3c6e3b16293adb526e2708cc1f0a56df3b5b17 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Fri, 5 Jul 2019 17:38:25 +0100 Subject: [PATCH 03/13] Reorganize stub test scripts --- gulpfile.babel.js | 25 +- package-lock.json | 1127 ++++++++--------- package.json | 2 +- src/session.js | 11 +- test/internal/bolt-stub.js | 10 +- .../node/direct.driver.boltkit.test.js | 841 ++++++------ .../node/routing.driver.boltkit.test.js | 444 +++---- .../boltstub/acquire_endpoints.script | 9 - ...ire_endpoints_old_routing_procedure.script | 10 - .../acquire_endpoints_with_one_of_each.script | 9 - .../boltstub/discover_new_servers.script | 13 - .../boltstub/discover_no_writers.script | 9 - .../boltstub/multiple_bookmarks.script | 16 - .../multiple_records_get_servers.script | 9 - .../not_able_to_write_in_transaction.script | 14 - .../boltstub/read_server_v2_read_tx.script | 19 - .../read_server_v2_read_tx_dead.script | 11 - .../boltstub/read_server_with_version.script | 12 - .../rediscover_and_read_with_init.script | 16 - .../boltstub/single_write_server.script | 9 - .../two_write_responses_server.script | 12 - .../connection_error_on_commit.script} | 2 +- .../boltstub/{ => v2}/query_with_error.script | 0 .../read.script} | 0 .../read_dead.script} | 0 .../{ => v2}/read_tx_with_bookmarks.script | 5 +- .../boltstub/{ => v2}/reset_error.script | 0 .../boltstub/{ => v2}/return_x.script | 2 +- .../write_read_tx_with_bookmarks.script | 0 .../{ => v2}/write_tx_with_bookmarks.script | 0 .../acquire_endpoints.script} | 0 .../acquire_endpoints_and_exit.script | 8 +- .../acquire_endpoints_dead.script} | 0 ...acquire_endpoints_multiple_records.script} | 6 +- .../acquire_endpoints_no_readers.script} | 6 +- .../acquire_endpoints_no_records.script} | 6 +- .../acquire_endpoints_no_routers.script} | 6 +- .../acquire_endpoints_no_servers.script} | 0 ...acquire_endpoints_no_servers_field.script} | 8 +- .../acquire_endpoints_no_ttl_field.script} | 6 +- .../acquire_endpoints_no_writers.script} | 6 +- .../acquire_endpoints_not_supported.script} | 6 +- .../acquire_endpoints_one_router.script} | 6 +- .../acquire_endpoints_rediscover.script} | 8 +- .../acquire_endpoints_self_as_reader.script} | 20 +- .../acquire_endpoints_short_ttl.script} | 0 .../acquire_endpoints_template.script} | 8 +- ...uire_endpoints_three_servers_set_1.script} | 0 ...uire_endpoints_three_servers_set_2.script} | 0 ...uire_endpoints_three_servers_set_3.script} | 9 +- ...cquire_endpoints_two_servers_set_1.script} | 0 ...quire_endpoints_unparsable_servers.script} | 6 +- .../acquire_endpoints_unparsable_ttl.script} | 6 +- .../acquire_endpoints_with_context.script} | 9 +- .../acquire_endpoints_zero_ttl.script} | 12 +- .../connection_error_on_commit.script} | 0 .../discover_ipv6_servers_and_read.script | 8 +- .../{ => v3}/discover_servers_and_read.script | 8 +- .../boltstub/{ => v3}/hello_run_exit.script | 0 .../{failed_auth.script => v3/no_auth.script} | 0 .../boltstub/v3/query_with_error.script | 11 + .../read.script} | 0 .../read_and_exit.script} | 8 +- .../read_database_unavailable.script} | 6 +- test/resources/boltstub/v3/read_dead.script | 7 + .../read_tx.script} | 0 .../resources/boltstub/v3/read_tx_dead.script | 9 + .../boltstub/v3/read_tx_with_bookmarks.script | 14 + .../v3/read_with_server_version.script | 12 + test/resources/boltstub/v3/reset_error.script | 10 + test/resources/boltstub/v3/return_x.script | 9 + .../write.script} | 0 .../v3/write_database_unavailable.script | 8 + test/resources/boltstub/v3/write_dead.script | 7 + .../write_not_a_leader.script} | 6 +- .../v3/write_read_tx_with_bookmarks.script | 22 + .../write_twice.script} | 8 +- test/resources/boltstub/v3/write_tx.script | 12 + .../boltstub/v3/write_tx_dead.script | 9 + .../boltstub/v3/write_tx_not_a_leader.script | 12 + .../v3/write_tx_with_bookmarks.script | 12 + .../write_tx_with_multiple_bookmarks.script | 12 + .../v3/write_with_server_version.script | 9 + .../hello_run_exit.script} | 6 +- .../boltstub/v4/query_with_error.script | 11 + test/resources/boltstub/v4/read.script | 11 + test/resources/boltstub/v4/read_dead.script | 7 + .../boltstub/v4/read_tx_with_bookmarks.script | 14 + test/resources/boltstub/v4/reset_error.script | 10 + test/resources/boltstub/v4/return_x.script | 9 + .../v4/write_read_tx_with_bookmarks.script | 22 + .../v4/write_tx_with_bookmarks.script | 12 + ...rite_read_tx_with_bookmark_override.script | 30 - .../boltstub/write_server_v2_write.script | 8 - .../boltstub/write_server_v2_write_tx.script | 16 - .../write_server_v2_write_tx_dead.script | 11 - .../boltstub/write_server_with_version.script | 9 - 97 files changed, 1495 insertions(+), 1679 deletions(-) delete mode 100644 test/resources/boltstub/acquire_endpoints.script delete mode 100644 test/resources/boltstub/acquire_endpoints_old_routing_procedure.script delete mode 100644 test/resources/boltstub/acquire_endpoints_with_one_of_each.script delete mode 100644 test/resources/boltstub/discover_new_servers.script delete mode 100644 test/resources/boltstub/discover_no_writers.script delete mode 100644 test/resources/boltstub/multiple_bookmarks.script delete mode 100644 test/resources/boltstub/multiple_records_get_servers.script delete mode 100644 test/resources/boltstub/not_able_to_write_in_transaction.script delete mode 100644 test/resources/boltstub/read_server_v2_read_tx.script delete mode 100644 test/resources/boltstub/read_server_v2_read_tx_dead.script delete mode 100644 test/resources/boltstub/read_server_with_version.script delete mode 100644 test/resources/boltstub/rediscover_and_read_with_init.script delete mode 100644 test/resources/boltstub/single_write_server.script delete mode 100644 test/resources/boltstub/two_write_responses_server.script rename test/resources/boltstub/{connection_error_on_commit_v1.script => v2/connection_error_on_commit.script} (95%) rename test/resources/boltstub/{ => v2}/query_with_error.script (100%) rename test/resources/boltstub/{read_server_v2_read.script => v2/read.script} (100%) rename test/resources/boltstub/{read_server_v2_read_dead.script => v2/read_dead.script} (100%) rename test/resources/boltstub/{ => v2}/read_tx_with_bookmarks.script (97%) rename test/resources/boltstub/{ => v2}/reset_error.script (100%) rename test/resources/boltstub/{ => v2}/return_x.script (78%) rename test/resources/boltstub/{ => v2}/write_read_tx_with_bookmarks.script (100%) rename test/resources/boltstub/{ => v2}/write_tx_with_bookmarks.script (100%) rename test/resources/boltstub/{acquire_endpoints_v3.script => v3/acquire_endpoints.script} (100%) rename test/resources/boltstub/{ => v3}/acquire_endpoints_and_exit.script (88%) rename test/resources/boltstub/{dead_routing_server.script => v3/acquire_endpoints_dead.script} (100%) rename test/resources/boltstub/{unparsable_multiple_records_get_servers.script => v3/acquire_endpoints_multiple_records.script} (93%) rename test/resources/boltstub/{no_readers_get_servers.script => v3/acquire_endpoints_no_readers.script} (88%) rename test/resources/boltstub/{empty_get_servers_response.script => v3/acquire_endpoints_no_records.script} (78%) rename test/resources/boltstub/{no_routers_get_servers.script => v3/acquire_endpoints_no_routers.script} (87%) rename test/resources/boltstub/{acquire_endpoints_v3_empty.script => v3/acquire_endpoints_no_servers.script} (100%) rename test/resources/boltstub/{no_servers_entry_get_servers.script => v3/acquire_endpoints_no_servers_field.script} (79%) rename test/resources/boltstub/{no_ttl_entry_get_servers.script => v3/acquire_endpoints_no_ttl_field.script} (90%) rename test/resources/boltstub/{no_writers.script => v3/acquire_endpoints_no_writers.script} (90%) rename test/resources/boltstub/{non_discovery.script => v3/acquire_endpoints_not_supported.script} (82%) rename test/resources/boltstub/{discover_one_router.script => v3/acquire_endpoints_one_router.script} (90%) rename test/resources/boltstub/{rediscover.script => v3/acquire_endpoints_rediscover.script} (91%) rename test/resources/boltstub/{rediscover_using_initial_router.script => v3/acquire_endpoints_self_as_reader.script} (68%) rename test/resources/boltstub/{short_ttl.script => v3/acquire_endpoints_short_ttl.script} (100%) rename test/resources/boltstub/{one_of_each_template.script.mst => v3/acquire_endpoints_template.script} (82%) rename test/resources/boltstub/{acquire_endpoints_v3_three_servers_and_exit.script => v3/acquire_endpoints_three_servers_set_1.script} (100%) rename test/resources/boltstub/{acquire_endpoints_v3_point_to_empty_router_and_exit.script => v3/acquire_endpoints_three_servers_set_2.script} (100%) rename test/resources/boltstub/{discover_servers.script => v3/acquire_endpoints_three_servers_set_3.script} (84%) rename test/resources/boltstub/{get_routing_table.script => v3/acquire_endpoints_two_servers_set_1.script} (100%) rename test/resources/boltstub/{unparsable_servers_get_servers.script => v3/acquire_endpoints_unparsable_servers.script} (90%) rename test/resources/boltstub/{unparsable_ttl_get_servers.script => v3/acquire_endpoints_unparsable_ttl.script} (90%) rename test/resources/boltstub/{get_routing_table_with_context.script => v3/acquire_endpoints_with_context.script} (75%) rename test/resources/boltstub/{routing_table_with_zero_ttl.script => v3/acquire_endpoints_zero_ttl.script} (86%) rename test/resources/boltstub/{connection_error_on_commit_v3.script => v3/connection_error_on_commit.script} (100%) rename test/resources/boltstub/{ => v3}/discover_ipv6_servers_and_read.script (84%) rename test/resources/boltstub/{ => v3}/discover_servers_and_read.script (84%) rename test/resources/boltstub/{ => v3}/hello_run_exit.script (100%) rename test/resources/boltstub/{failed_auth.script => v3/no_auth.script} (100%) create mode 100644 test/resources/boltstub/v3/query_with_error.script rename test/resources/boltstub/{read_server_v3_read.script => v3/read.script} (100%) rename test/resources/boltstub/{read_server_and_exit.script => v3/read_and_exit.script} (61%) rename test/resources/boltstub/{address_unavailable_template.script.mst => v3/read_database_unavailable.script} (72%) create mode 100644 test/resources/boltstub/v3/read_dead.script rename test/resources/boltstub/{read_server_v3_read_tx.script => v3/read_tx.script} (100%) create mode 100644 test/resources/boltstub/v3/read_tx_dead.script create mode 100644 test/resources/boltstub/v3/read_tx_with_bookmarks.script create mode 100644 test/resources/boltstub/v3/read_with_server_version.script create mode 100644 test/resources/boltstub/v3/reset_error.script create mode 100644 test/resources/boltstub/v3/return_x.script rename test/resources/boltstub/{write_server_v3_write.script => v3/write.script} (100%) create mode 100644 test/resources/boltstub/v3/write_database_unavailable.script create mode 100644 test/resources/boltstub/v3/write_dead.script rename test/resources/boltstub/{not_able_to_write.script => v3/write_not_a_leader.script} (70%) create mode 100644 test/resources/boltstub/v3/write_read_tx_with_bookmarks.script rename test/resources/boltstub/{write_server_v3_write_tx.script => v3/write_twice.script} (62%) create mode 100644 test/resources/boltstub/v3/write_tx.script create mode 100644 test/resources/boltstub/v3/write_tx_dead.script create mode 100644 test/resources/boltstub/v3/write_tx_not_a_leader.script create mode 100644 test/resources/boltstub/v3/write_tx_with_bookmarks.script create mode 100644 test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script create mode 100644 test/resources/boltstub/v3/write_with_server_version.script rename test/resources/boltstub/{hello_run_exit_read.script => v4/hello_run_exit.script} (80%) create mode 100644 test/resources/boltstub/v4/query_with_error.script create mode 100644 test/resources/boltstub/v4/read.script create mode 100644 test/resources/boltstub/v4/read_dead.script create mode 100644 test/resources/boltstub/v4/read_tx_with_bookmarks.script create mode 100644 test/resources/boltstub/v4/reset_error.script create mode 100644 test/resources/boltstub/v4/return_x.script create mode 100644 test/resources/boltstub/v4/write_read_tx_with_bookmarks.script create mode 100644 test/resources/boltstub/v4/write_tx_with_bookmarks.script delete mode 100644 test/resources/boltstub/write_read_tx_with_bookmark_override.script delete mode 100644 test/resources/boltstub/write_server_v2_write.script delete mode 100644 test/resources/boltstub/write_server_v2_write_tx.script delete mode 100644 test/resources/boltstub/write_server_v2_write_tx_dead.script delete mode 100644 test/resources/boltstub/write_server_with_version.script diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 8b380e74c..b23ee6f19 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -35,7 +35,7 @@ const file = require('gulp-file') const semver = require('semver') const sharedNeo4j = require('./test/internal/shared-neo4j').default const ts = require('gulp-typescript') -const JasmineConsoleReporter = require('jasmine-console-reporter') +const JasmineReporter = require('jasmine-spec-reporter').SpecReporter const karma = require('karma') const log = require('fancy-log') @@ -218,12 +218,23 @@ function logActiveNodeHandles () { } function newJasmineConsoleReporter () { - return new JasmineConsoleReporter({ - colors: 1, - cleanStack: 1, - verbosity: 4, - listStyle: 'indent', - activity: false + return new JasmineReporter({ + colors: { + enabled: true + }, + spec: { + displayDuration: true, + displayErrorMessages: true, + displayStacktrace: true, + displayFailed: true, + displaySuccessful: true, + displayPending: false + }, + summary: { + displayFailed: true, + displayStacktrace: true, + displayErrorMessages: true + } }) } diff --git a/package-lock.json b/package-lock.json index 9ed24f702..2920ae739 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha1-BuKrGb21NThVWaq7W6WXKUgoAPg=", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { "@babel/highlight": "^7.0.0" @@ -16,7 +16,7 @@ "@babel/core": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.4.tgz", - "integrity": "sha1-hAVXULBfzVD5kVqCa0T6NHqCUlA=", + "integrity": "sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -105,7 +105,7 @@ "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -141,7 +141,7 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "to-fast-properties": { @@ -176,7 +176,7 @@ "@babel/helper-annotate-as-pure": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha1-Mj053QtQ4Qx8Bsp9djjmhk2MXDI=", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -185,7 +185,7 @@ "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha1-a2lijf5Ah3mODE7Zjj1Kay+9L18=", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", "dev": true, "requires": { "@babel/helper-explode-assignable-expression": "^7.1.0", @@ -195,7 +195,7 @@ "@babel/helper-call-delegate": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha1-h8H4yhmtVSpzanonscH8+LH/H0M=", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.4.4", @@ -297,7 +297,7 @@ "@babel/helper-define-map": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz", - "integrity": "sha1-aWnR9XC0a9yQDR66jl1ZxIuiwSo=", + "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -327,7 +327,7 @@ "@babel/helper-explode-assignable-expression": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha1-U3+hP28WdN90WwwA7I/k6ZaByPY=", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", @@ -337,7 +337,7 @@ "@babel/helper-function-name": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha1-oM6wFoX3M1XUNgwSR/WCv6/I/1M=", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.0.0", @@ -348,7 +348,7 @@ "@babel/helper-get-function-arity": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha1-g1ctQyDipGVyY3NBE8QoaLZOScM=", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -357,7 +357,7 @@ "@babel/helper-hoist-variables": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha1-Api18lyMCcUxAtUqxKmPdz6yhQo=", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", "dev": true, "requires": { "@babel/types": "^7.4.4" @@ -385,7 +385,7 @@ "@babel/helper-member-expression-to-functions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", - "integrity": "sha1-jNFLCg33/wDwCefXpDaUX0fHoW8=", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -394,7 +394,7 @@ "@babel/helper-module-imports": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha1-lggbcRHkhtpNLNlxrRpP4hbMLj0=", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -403,7 +403,7 @@ "@babel/helper-module-transforms": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz", - "integrity": "sha1-lhFepCovE55hnpjtRt9gGblEFLg=", + "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -462,7 +462,7 @@ "@babel/helper-optimise-call-expression": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha1-opIMVwKwc8Fd5REGIAqoytIEl9U=", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", "dev": true, "requires": { "@babel/types": "^7.0.0" @@ -471,13 +471,13 @@ "@babel/helper-plugin-utils": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha1-u7P77phmHFaQNCN8wDlnupm08lA=", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", "dev": true }, "@babel/helper-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz", - "integrity": "sha1-pH4CvJH7JZ0uZyfCowAT46wTxKI=", + "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==", "dev": true, "requires": { "lodash": "^4.17.11" @@ -486,7 +486,7 @@ "@babel/helper-remap-async-to-generator": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha1-Nh2AghtvONp1vT8HheziCojF/n8=", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -499,7 +499,7 @@ "@babel/helper-replace-supers": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz", - "integrity": "sha1-ruQXg+vk8tOrOud14cxvGpDO+ic=", + "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.0.0", @@ -602,7 +602,7 @@ "@babel/helper-simple-access": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha1-Ze65VMjCRb6qToWdphiPOdceWFw=", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", "dev": true, "requires": { "@babel/template": "^7.1.0", @@ -621,7 +621,7 @@ "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha1-xOABJEV2nigVtVKW6tQ6lYVJ9vo=", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -633,7 +633,7 @@ "@babel/helpers": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", - "integrity": "sha1-hosO9Zwd1OeHRFYtXOG1nIny8qU=", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", "dev": true, "requires": { "@babel/template": "^7.4.4", @@ -746,7 +746,7 @@ "@babel/highlight": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha1-9xDDjI1Fjm3ZogGvtjf8t4HOmeQ=", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -757,7 +757,7 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -777,13 +777,13 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -800,7 +800,7 @@ "@babel/plugin-proposal-async-generator-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha1-somzBmadzkrSCwJSiJoVdoydQX4=", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -811,7 +811,7 @@ "@babel/plugin-proposal-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha1-Vo7MRGxhSK5rJn8CVREwiR4p8xc=", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -821,7 +821,7 @@ "@babel/plugin-proposal-object-rest-spread": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz", - "integrity": "sha1-HvFz/PJLPi35KmePAnZztV5+MAU=", + "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -831,7 +831,7 @@ "@babel/plugin-proposal-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha1-E12B7baKCB5V5W7EhUHs6AZcOPU=", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -841,7 +841,7 @@ "@babel/plugin-proposal-unicode-property-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", - "integrity": "sha1-UB/9mCbAuR2iJpByByKsfLHKnHg=", + "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -858,7 +858,7 @@ "regexpu-core": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha1-CA2dAiiaqH/hZnpPUTa8mKauuq4=", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "dev": true, "requires": { "regenerate": "^1.4.0", @@ -872,13 +872,13 @@ "regjsgen": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha1-p2NNwI+JIJwgSa3aNSVxH7lyZd0=", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", "dev": true }, "regjsparser": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha1-8eaui32iuulsmTmbhozWyTOiupw=", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -889,7 +889,7 @@ "@babel/plugin-syntax-async-generators": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha1-aeHw2zTG9aDPfiszI78VmnbIy38=", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -898,7 +898,7 @@ "@babel/plugin-syntax-json-strings": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha1-cr0T9v/h0lk4Ep0qGGsR/WKVFHA=", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -907,7 +907,7 @@ "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha1-O3o+czUQxX6CC5FCpleayLDfrS4=", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -916,7 +916,7 @@ "@babel/plugin-syntax-optional-catch-binding": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha1-qUAT1u2okI3+akd+f57ahWVuz1w=", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -925,7 +925,7 @@ "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha1-mur75Nb/xlY7+Pg3IJFijwB3lVA=", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -934,7 +934,7 @@ "@babel/plugin-transform-async-to-generator": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz", - "integrity": "sha1-o/HQHy8hytqyCzOoITMRbxT7WJQ=", + "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -945,7 +945,7 @@ "@babel/plugin-transform-block-scoped-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha1-XTzBHo1d3XUqpkyRSNDbbLef0ZA=", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -954,7 +954,7 @@ "@babel/plugin-transform-block-scoping": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz", - "integrity": "sha1-wTJ5+r9rkWZhUxhBojxLfa4pZG0=", + "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -964,7 +964,7 @@ "@babel/plugin-transform-classes": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz", - "integrity": "sha1-DOQJTNr9cJchB207nDitMcpxXrY=", + "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -1000,7 +1000,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, "to-fast-properties": { @@ -1014,7 +1014,7 @@ "@babel/plugin-transform-computed-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha1-g6ffamWIZbHI9kHVEMbzryICFto=", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1023,7 +1023,7 @@ "@babel/plugin-transform-destructuring": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz", - "integrity": "sha1-nZZHF4KcyeS2AfyCompxpNj68g8=", + "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1032,7 +1032,7 @@ "@babel/plugin-transform-dotall-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", - "integrity": "sha1-NhoUi8lRREMSxpRG127R6o5EUMM=", + "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1080,7 +1080,7 @@ "@babel/plugin-transform-duplicate-keys": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", - "integrity": "sha1-2VLEkw8xKk2//xjwspFOYMNVMLM=", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1089,7 +1089,7 @@ "@babel/plugin-transform-exponentiation-operator": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha1-pjhoKJ5bQAf3BU1GSRr1FDV2YAg=", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", "dev": true, "requires": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", @@ -1099,7 +1099,7 @@ "@babel/plugin-transform-for-of": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha1-Amf8c14kyAi6FzhmxsTRRA/DxVY=", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1108,7 +1108,7 @@ "@babel/plugin-transform-function-name": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha1-4UNhFquwYQwiWQlISHVKxSMJIq0=", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", "dev": true, "requires": { "@babel/helper-function-name": "^7.1.0", @@ -1118,7 +1118,7 @@ "@babel/plugin-transform-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha1-aQNT6B+SZ9rU/Yz9d+r6hqulPqE=", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1127,7 +1127,7 @@ "@babel/plugin-transform-member-expression-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha1-+hCqXFiiy2r88sn/qMtNiz1Imi0=", + "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1136,7 +1136,7 @@ "@babel/plugin-transform-modules-amd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", - "integrity": "sha1-gqm85FuVRB9heiQBHcidEtp/TuY=", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", @@ -1146,7 +1146,7 @@ "@babel/plugin-transform-modules-commonjs": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz", - "integrity": "sha1-C+9HE9MPHXjC5Zs9bbQOYBksrB4=", + "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.4.4", @@ -1157,7 +1157,7 @@ "@babel/plugin-transform-modules-systemjs": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz", - "integrity": "sha1-3IPFZlsH1sKnsiTACsY2Weo2pAU=", + "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.4.4", @@ -1167,7 +1167,7 @@ "@babel/plugin-transform-modules-umd": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", - "integrity": "sha1-dnjOdRafCHe46yI1U4wHQmjdAa4=", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.1.0", @@ -1177,7 +1177,7 @@ "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.4.tgz", - "integrity": "sha1-VhHZbZh9/Eo6gcQ4O7FzNhA31o0=", + "integrity": "sha512-Ki+Y9nXBlKfhD+LXaRS7v95TtTGYRAf9Y1rTDiE75zf8YQz4GDaWRXosMfJBXxnk88mGFjWdCRIeqDbon7spYA==", "dev": true, "requires": { "regexp-tree": "^0.1.0" @@ -1186,7 +1186,7 @@ "@babel/plugin-transform-new-target": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha1-GNEgQ4sMye6VpH8scryXaPvtYKU=", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1195,7 +1195,7 @@ "@babel/plugin-transform-object-super": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", - "integrity": "sha1-s11MEPVrq11lAEfa0PHY6IFLZZg=", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1205,7 +1205,7 @@ "@babel/plugin-transform-parameters": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha1-dVbPA/MYvScZ/kySLS2Ai+VXHhY=", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", "dev": true, "requires": { "@babel/helper-call-delegate": "^7.4.4", @@ -1216,7 +1216,7 @@ "@babel/plugin-transform-property-literals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha1-A+M/ZT9bJcTrVyyYuUhQVbOJ6QU=", + "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1225,7 +1225,7 @@ "@babel/plugin-transform-regenerator": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.4.tgz", - "integrity": "sha1-W02k33k5GJX8qeKPmeh+Is/AIHI=", + "integrity": "sha512-Zz3w+pX1SI0KMIiqshFZkwnVGUhDZzpX2vtPzfJBKQQq8WsP/Xy9DNdELWivxcKOCX/Pywge4SiEaPaLtoDT4g==", "dev": true, "requires": { "regenerator-transform": "^0.13.4" @@ -1234,7 +1234,7 @@ "regenerator-transform": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", - "integrity": "sha1-GPZ2PPE4LGnDbfdsbOEizGlChPs=", + "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", "dev": true, "requires": { "private": "^0.1.6" @@ -1245,7 +1245,7 @@ "@babel/plugin-transform-reserved-words": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha1-R5Kvh8mYpJNnWX0H/t8CY20uFjQ=", + "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1254,7 +1254,7 @@ "@babel/plugin-transform-runtime": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.4.tgz", - "integrity": "sha1-pQ9dFunDpKwYoan5gDwQfDgLzgg=", + "integrity": "sha512-aMVojEjPszvau3NRg+TIH14ynZLvPewH4xhlCW1w6A3rkxTS1m4uwzRclYR9oS+rl/dr+kT+pzbfHuAWP/lc7Q==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -1266,7 +1266,7 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true } } @@ -1274,7 +1274,7 @@ "@babel/plugin-transform-shorthand-properties": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha1-YzOu4vjW7n4oYVRXKYk0o7RhmPA=", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1283,7 +1283,7 @@ "@babel/plugin-transform-spread": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", - "integrity": "sha1-MQOpq+IvdCttQG7NPNSbd0kZtAY=", + "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1292,7 +1292,7 @@ "@babel/plugin-transform-sticky-regex": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha1-oeRUtZlVYKnB4NU338FQYf0mh+E=", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1302,7 +1302,7 @@ "@babel/plugin-transform-template-literals": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha1-nSj+p7vOY3+3YSoHUJidgyHUvLA=", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.0.0", @@ -1312,7 +1312,7 @@ "@babel/plugin-transform-typeof-symbol": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha1-EX0rzsL79ktLWdH5gZiUaC0p8rI=", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" @@ -1321,7 +1321,7 @@ "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", - "integrity": "sha1-q0Y0u08U02cov1l4Mis1WHeHlw8=", + "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1369,7 +1369,7 @@ "@babel/preset-env": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.4.tgz", - "integrity": "sha1-tvaCW/sns+E5TKPeT5JkgnIsHW8=", + "integrity": "sha512-FU1H+ACWqZZqfw1x2G1tgtSSYSfxJLkpaUQL37CenULFARDo+h4xJoVHzRoHbK+85ViLciuI7ME4WTIhFRBBlw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.0.0", @@ -1436,7 +1436,7 @@ "browserslist": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.0.tgz", - "integrity": "sha1-UnQCjCb02TPVsTIzB8HR2lCEyf8=", + "integrity": "sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==", "dev": true, "requires": { "caniuse-lite": "^1.0.30000967", @@ -1473,7 +1473,7 @@ "@babel/register": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.4.4.tgz", - "integrity": "sha1-NwpoujbwjwFaizXUhkF2xrZdeiM=", + "integrity": "sha512-sn51H88GRa00+ZoMqCVgOphmswG4b7mhf9VOB0LUBAieykq2GnRFerlN+JQkO/ntT7wz4jaHNSRPg9IdMPEUkA==", "dev": true, "requires": { "core-js": "^3.0.0", @@ -1511,7 +1511,7 @@ "@babel/runtime": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz", - "integrity": "sha1-3C40mC6yNoA6onoH/qaFevG5Fx0=", + "integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==", "requires": { "regenerator-runtime": "^0.13.2" }, @@ -1519,7 +1519,7 @@ "regenerator-runtime": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", - "integrity": "sha1-MuWcmm+5saSv8JtJMMotRHc0NEc=" + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" } } }, @@ -1596,7 +1596,7 @@ "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha1-7N9I1TLFjqR3rPyrgDSEJPjQZi8=", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", "dev": true, "requires": { "any-observable": "^0.3.0" @@ -1611,13 +1611,13 @@ "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha1-UbHF/mV2o0lTv0slPfnw1JDZ41k=", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", "dev": true, "requires": { "@webassemblyjs/helper-module-context": "1.8.5", @@ -1628,25 +1628,25 @@ "@webassemblyjs/floating-point-hex-parser": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha1-G6kmopI2E+3OSW/VsC6M6KX0lyE=", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", "dev": true }, "@webassemblyjs/helper-api-error": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha1-xJ2tIvZFInxe22EL25aX8aq3Ifc=", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", "dev": true }, "@webassemblyjs/helper-buffer": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha1-/qk+Qphj3V5DOFVfQikjhaZT8gQ=", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", "dev": true }, "@webassemblyjs/helper-code-frame": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha1-mnQP9I4/qjAisd/1RCPfmqKTwl4=", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", "dev": true, "requires": { "@webassemblyjs/wast-printer": "1.8.5" @@ -1655,13 +1655,13 @@ "@webassemblyjs/helper-fsm": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha1-ugt9Oz9+RzPaYFnJMyJ12GBwJFI=", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", "dev": true }, "@webassemblyjs/helper-module-context": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha1-3vS5knsBAdyMu9jR7bW3ucguskU=", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1671,13 +1671,13 @@ "@webassemblyjs/helper-wasm-bytecode": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha1-U3p1Dt31weky83RCBlUckcG5PmE=", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", "dev": true }, "@webassemblyjs/helper-wasm-section": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha1-dMpqa8vhnlCjtrRihH5pUD5r/L8=", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1689,7 +1689,7 @@ "@webassemblyjs/ieee754": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha1-cSMp2+8kDza/V70ve4+5v0FUQh4=", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" @@ -1698,7 +1698,7 @@ "@webassemblyjs/leb128": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha1-BE7es06mefPgTNT9mCTV41dnrhA=", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", "dev": true, "requires": { "@xtuc/long": "4.2.2" @@ -1707,13 +1707,13 @@ "@webassemblyjs/utf8": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha1-qL87XY/+mGx8Hjc8y9wqCRXwztw=", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", "dev": true }, "@webassemblyjs/wasm-edit": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha1-li2hKqWswcExyBxCMpkcgs5W4Bo=", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1729,7 +1729,7 @@ "@webassemblyjs/wasm-gen": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha1-VIQHZsLBAC62TtGr5yCt7XFPmLw=", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1742,7 +1742,7 @@ "@webassemblyjs/wasm-opt": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha1-sk2fa6UDlK8TSfUQr6j/y4pj0mQ=", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1754,7 +1754,7 @@ "@webassemblyjs/wasm-parser": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha1-IVdvDsiLkUJzV7hTY4NmjvfGa40=", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1768,7 +1768,7 @@ "@webassemblyjs/wast-parser": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha1-4Q7s1ULQ5705T2gnxJ899tTu+4w=", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1782,7 +1782,7 @@ "@webassemblyjs/wast-printer": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha1-EUu8SB/RDKDiOzVg+oEnSLC65bw=", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -1799,13 +1799,13 @@ "@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha1-0pHGpOl5ibXGHZrPOWrk/hM6cY0=", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha1-MgjB8I06TZkmGrZPkjArwV4RHKA=", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -1822,13 +1822,13 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "dev": true, "requires": { "mime-types": "~2.1.24", @@ -1855,13 +1855,13 @@ "acorn": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha1-fSWuBbuK0fm2mRCOEJTs14hK3B8=", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, "acorn-dynamic-import": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha1-SCIQFAWCo2uDw+NC4c/ryqkkCUg=", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true }, "acorn-globals": { @@ -1886,13 +1886,13 @@ "acorn-jsx": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, "acorn-node": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", - "integrity": "sha1-t9fOym8i5kF6+TOmLK1N4BBI1dI=", + "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", "dev": true, "requires": { "acorn": "^6.0.2", @@ -1904,7 +1904,7 @@ "acorn-walk": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha1-02O2b1+sXwGP+cOh57b44xDMORM=", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", "dev": true }, "after": { @@ -1928,7 +1928,7 @@ "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", "dev": true }, "ajv-keywords": { @@ -1958,7 +1958,7 @@ "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, "ansi-gray": { @@ -2000,13 +2000,13 @@ "any-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha1-r5M0deWAamfQ198JDdXovvZdEZs=", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", "dev": true }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { "micromatch": "^3.1.4", @@ -2046,7 +2046,7 @@ "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" @@ -2129,7 +2129,7 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true } } @@ -2137,7 +2137,7 @@ "array-last": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha1-eqdwc/7FZd2rJJP1+IGF9ASp0zY=", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", "dev": true, "requires": { "is-number": "^4.0.0" @@ -2146,7 +2146,7 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true } } @@ -2172,7 +2172,7 @@ "array-sort": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha1-5MBTVkU/VvU1EqfR1hI/LFTAqIo=", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", "dev": true, "requires": { "default-compare": "^1.0.0", @@ -2183,7 +2183,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } @@ -2212,7 +2212,7 @@ "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, "arrify": { @@ -2244,7 +2244,7 @@ "assert": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { "object-assign": "^4.1.1", @@ -2283,7 +2283,7 @@ "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, "async": { @@ -2327,7 +2327,7 @@ "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, "async-limiter": { @@ -2354,7 +2354,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, "aws-sign2": { @@ -2383,7 +2383,7 @@ "babel-eslint": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", - "integrity": "sha1-kZaB3AmWFM19MdRciQhpUJKh+u0=", + "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -2473,7 +2473,7 @@ "babelify": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", - "integrity": "sha1-/nOxoiWD8GaA2NBy4loeDR0df7U=", + "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", "dev": true }, "babylon": { @@ -2611,19 +2611,19 @@ "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, "binaryextensions": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", - "integrity": "sha1-yDw9dCM7p2dOTzE8sqK3D1TpS3w=", + "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", "dev": true }, "bl": { @@ -2639,13 +2639,13 @@ "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha1-1oDu7yX4zZGtUz9bAe7UjmTK9oM=", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", "dev": true }, "bluebird": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", - "integrity": "sha1-1sxmFZXeMNWzr1/O3TwLPvbsVxQ=", + "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", "dev": true }, "bn.js": { @@ -2657,7 +2657,7 @@ "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { "bytes": "3.1.0", @@ -2684,7 +2684,7 @@ "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true } } @@ -2775,7 +2775,7 @@ "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha1-m3y7PQ9RDky4a9vXlhJNKLWJCvY=", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, "requires": { "resolve": "1.1.7" @@ -2792,7 +2792,7 @@ "browserify": { "version": "16.2.3", "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", - "integrity": "sha1-fubmVLpPkrzmqzWZw0hbHMegrQs=", + "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", "dev": true, "requires": { "JSONStream": "^1.0.3", @@ -2891,7 +2891,7 @@ "browserify-des": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, "requires": { "cipher-base": "^1.0.1", @@ -2938,7 +2938,7 @@ "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "requires": { "pako": "~1.0.5" @@ -2947,7 +2947,7 @@ "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha1-3Vf6DxCaxZxgJHkETcp7iz0LcdY=", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -2957,7 +2957,7 @@ "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "dev": true, "requires": { "buffer-alloc-unsafe": "^1.1.0", @@ -2967,7 +2967,7 @@ "buffer-alloc-unsafe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "dev": true }, "buffer-crc32": { @@ -2991,7 +2991,7 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "buffer-shims": { @@ -3015,13 +3015,13 @@ "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "cacache": { "version": "11.3.2", "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", - "integrity": "sha1-LYHjCOPSWMo4Eltna5iyrJzmm/o=", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { "bluebird": "^3.5.3", @@ -3043,7 +3043,7 @@ "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { "yallist": "^3.0.2" @@ -3052,13 +3052,13 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha1-tLBJ4xS+VF486AIjbWzSLNkcPek=", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true } } @@ -3083,7 +3083,7 @@ "cached-path-relative": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", - "integrity": "sha1-oT30GW0md2IgzDNW6xR6Utuixts=", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", "dev": true }, "caller-callsite": { @@ -3160,7 +3160,7 @@ "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "cheerio": { @@ -3223,7 +3223,7 @@ "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, "cipher-base": { @@ -3268,12 +3268,6 @@ "restore-cursor": "^2.0.0" } }, - "cli-spinners": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.1.0.tgz", - "integrity": "sha1-IsNLTVH1cyQIhbIB79pOTsn/88c=", - "dev": true - }, "cli-truncate": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", @@ -3372,7 +3366,7 @@ "cloneable-readable": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -3416,7 +3410,7 @@ "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -3487,7 +3481,7 @@ "common-tags": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha1-jjFT5ULUo56bEFVENK+q+YlWqTc=", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", "dev": true }, "commondir": { @@ -3505,7 +3499,7 @@ "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", "dev": true }, "component-inherit": { @@ -3523,7 +3517,7 @@ "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -3574,7 +3568,7 @@ "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -3609,7 +3603,7 @@ "copy-props": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha1-k7scrfr9MdpbuKnUtB9HHsOnLf4=", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", "dev": true, "requires": { "each-props": "^1.3.0", @@ -3766,7 +3760,7 @@ "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { "nice-try": "^1.0.4", @@ -3779,7 +3773,7 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true } } @@ -3825,7 +3819,8 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", "integrity": "sha1-+FIGzuBO+oQfPFmCp0uparINZa0=", - "dev": true + "dev": true, + "optional": true }, "cssstyle": { "version": "0.2.37", @@ -3867,7 +3862,7 @@ "dash-ast": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha1-EgKbpfsviqbwqGF5WyPBtLbCfTc=", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", "dev": true }, "dashdash": { @@ -3882,13 +3877,13 @@ "date-fns": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha1-LnG/CxGRU9u0zE6I2epaz7UNwFw=", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", "dev": true }, "date-format": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz", - "integrity": "sha1-fPexcvHsVk8AA7OeowLFSY+5jI8=", + "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==", "dev": true }, "date-now": { @@ -3943,7 +3938,7 @@ "decompress-tar": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha1-cYy9P8sWIJcW5womuE57pFkuWvE=", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", "dev": true, "requires": { "file-type": "^5.2.0", @@ -3962,7 +3957,7 @@ "decompress-tarbz2": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha1-MIKluIDqQEOBY0nzeLVsUWvho5s=", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", "dev": true, "requires": { "decompress-tar": "^4.1.0", @@ -3975,7 +3970,7 @@ "file-type": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha1-5QzXXTVv/tTjBtxPW89Sp5kDqRk=", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", "dev": true } } @@ -3983,7 +3978,7 @@ "decompress-targz": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha1-wJvDXE0R894J8tLaU+neI+fOHu4=", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", "dev": true, "requires": { "decompress-tar": "^4.1.1", @@ -4044,7 +4039,7 @@ "default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha1-y2ETGESthNhHiPto/QFoHKd4Gi8=", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, "requires": { "kind-of": "^5.0.2" @@ -4053,7 +4048,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } @@ -4064,27 +4059,10 @@ "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", "dev": true }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } - } - }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { "object-keys": "^1.0.12" @@ -4223,7 +4201,7 @@ "detective": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha1-/rKnfoW5BOzepFmtiXzJCpm9Kns=", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", "dev": true, "requires": { "acorn-node": "^1.6.1", @@ -4251,13 +4229,13 @@ "dlv": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.2.tgz", - "integrity": "sha1-Jw9nN7MNJbZlen6WLHhEA/hRN+U=", + "integrity": "sha512-xxD4VSH67GbRvSGUrckvha94RD7hjgOH7rqGxiytLpkaeMvixOHFZTGFK6EkIm3T761OVHT8ABHmGkq9gXgu6Q==", "dev": true }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" @@ -4288,7 +4266,7 @@ "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "domelementtype": { @@ -4328,7 +4306,7 @@ "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -4340,7 +4318,7 @@ "each-props": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha1-6kWkFNFt1c+kGbGoFyDVygaJIzM=", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", "dev": true, "requires": { "is-plain-object": "^2.0.1", @@ -4366,7 +4344,7 @@ "editions": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha1-NmLLWSNHwxaOuOSYoP9zJx1n9Qs=", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", "dev": true }, "ee-first": { @@ -4384,7 +4362,7 @@ "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4399,7 +4377,7 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "emojis-list": { @@ -4417,7 +4395,7 @@ "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -4426,7 +4404,7 @@ "engine.io": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha1-tgKBw1SEpw7gNR6g6/+D7IyVIqI=", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -4440,7 +4418,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4451,7 +4429,7 @@ "engine.io-client": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha1-b1TAR13khxWKGnx30QF4cItq3TY=", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -4476,7 +4454,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4487,7 +4465,7 @@ "engine.io-parser": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha1-dXq5cPvy37Mse3SwMyFtVznveaY=", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", "dev": true, "requires": { "after": "0.8.2", @@ -4532,7 +4510,7 @@ "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" @@ -4541,7 +4519,7 @@ "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "dev": true, "requires": { "es-to-primitive": "^1.2.0", @@ -4555,7 +4533,7 @@ "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -4566,7 +4544,7 @@ "es5-ext": { "version": "0.10.50", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", - "integrity": "sha1-bQ4joKvbJwGOWsT9CbQSvFUXp3g=", + "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -4934,7 +4912,7 @@ "eslint": { "version": "5.16.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha1-oeOsGq5KP72Clvz496tzFMu2q+o=", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -4993,7 +4971,7 @@ "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -5004,7 +4982,7 @@ "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -5019,13 +4997,13 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "strip-ansi": { @@ -5051,13 +5029,13 @@ "eslint-config-standard": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", - "integrity": "sha1-Y4tMZdsL1aQTGflruh8V3a0hB9k=", + "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", "dev": true }, "eslint-import-resolver-node": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha1-WPFfuDm40FdsqYBBNHaqskcttmo=", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", "dev": true, "requires": { "debug": "^2.6.9", @@ -5067,7 +5045,7 @@ "eslint-module-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz", - "integrity": "sha1-i5NJnpsA6rgMy2YU5p8DZ46E4Jo=", + "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==", "dev": true, "requires": { "debug": "^2.6.8", @@ -5077,7 +5055,7 @@ "eslint-plugin-es": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", - "integrity": "sha1-R19luyDJk/wQ6Mj+d9HWAGgHLaY=", + "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", "dev": true, "requires": { "eslint-utils": "^1.3.0", @@ -5087,7 +5065,7 @@ "eslint-plugin-import": { "version": "2.17.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz", - "integrity": "sha1-0ifVxtxn7KcetZDSu2L7ONhun8s=", + "integrity": "sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -5124,7 +5102,7 @@ "eslint-plugin-node": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-9.0.1.tgz", - "integrity": "sha1-k+RGJvpivLbv6lKM7paHZj3AO2I=", + "integrity": "sha512-fljT5Uyy3lkJzuqhxrYanLSsvaILs9I7CmQ31atTtZ0DoIzRbbvInBh4cQ1CrthFHInHYBQxfPmPt6KLHXNXdw==", "dev": true, "requires": { "eslint-plugin-es": "^1.4.0", @@ -5138,7 +5116,7 @@ "ignore": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.1.tgz", - "integrity": "sha1-L8a49Riv9I/vZafzSO2FYyRI5KU=", + "integrity": "sha512-DWjnQIFLenVrwyRCKZT+7a7/U4Cqgar4WG8V++K3hw+lrW1hc/SIwdiGmtxKCVACmHULTuGeBbHJmbwW7/sAvA==", "dev": true } } @@ -5146,13 +5124,13 @@ "eslint-plugin-promise": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.1.1.tgz", - "integrity": "sha1-HgjLaLWyzYg5+NWGTHlvVtgnRts=", + "integrity": "sha512-faAHw7uzlNPy7b45J1guyjazw28M+7gJokKUjC5JSFoYfUEyy6Gw/i7YQvmv2Yk00sUjWcmzXQLpU1Ki/C2IZQ==", "dev": true }, "eslint-plugin-standard": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", - "integrity": "sha1-+EW0UQnJnNkOd3lpQKNEVGyPa1w=", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", "dev": true }, "eslint-scope": { @@ -5168,19 +5146,19 @@ "eslint-utils": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", "dev": true }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, "espree": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha1-XWUm+k/H8HiKXPdbFfMDI+L4H3o=", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { "acorn": "^6.0.7", @@ -5198,7 +5176,7 @@ "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -5228,13 +5206,13 @@ "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha1-LT1I+cNGaY/Og6hdfWZOmFNd9uc=", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, "events": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", - "integrity": "sha1-KpoeGOYQbg6BKqnr1KgZs8KcC6U=", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", "dev": true }, "evp_bytestokey": { @@ -5400,7 +5378,7 @@ "external-editor": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha1-WGbbKal4Jtvkvzr9JAcOrZ6kOic=", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { "chardet": "^0.7.0", @@ -5420,7 +5398,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -5567,7 +5545,7 @@ "figgy-pudding": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha1-hiRwESkBxyeg5JWoB0S9W6odZ5A=", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", "dev": true }, "figures": { @@ -5582,7 +5560,7 @@ "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { "flat-cache": "^2.0.1" @@ -5649,7 +5627,7 @@ "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -5759,7 +5737,7 @@ "findup-sync": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha1-F7EI+e5RLft6XH88iyfqnhqcCNE=", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", "dev": true, "requires": { "detect-file": "^1.0.0", @@ -5771,7 +5749,7 @@ "fined": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha1-0AvszxqitHXRbUI7Aji3E6LEo3s=", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", "dev": true, "requires": { "expand-tilde": "^2.0.2", @@ -5793,13 +5771,13 @@ "flagged-respawn": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha1-595vEnnd2cqarIpZcdYYYGs6q0E=", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { "flatted": "^2.0.0", @@ -5810,13 +5788,13 @@ "flatted": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", "dev": true }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -5832,7 +5810,7 @@ "follow-redirects": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", - "integrity": "sha1-SJ68GY3A5/ZBZ70jsDxMGbV4THY=", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, "requires": { "debug": "^3.2.6" @@ -5841,7 +5819,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -5850,7 +5828,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } @@ -5930,7 +5908,7 @@ "fs-extra": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.0.1.tgz", - "integrity": "sha1-kClAgfl4sfGC80ekQKIJFUNEKFs=", + "integrity": "sha512-W+XLrggcDzlle47X/XnS7FXrXu9sDo+Ze9zpndeBxdgv88FHLm1HtmkhEwavruS6koanBjp098rUpHs65EmG7A==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -5998,7 +5976,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6019,12 +5998,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6039,17 +6020,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6166,7 +6150,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6178,6 +6163,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6192,6 +6178,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6199,12 +6186,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6223,6 +6212,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6303,7 +6293,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6315,6 +6306,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6400,7 +6392,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6436,6 +6429,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6455,6 +6449,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6498,12 +6493,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -6522,7 +6519,7 @@ "g-status": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz", - "integrity": "sha1-Jw/TIRno/JSW8Gb+X+iOCmvHi5c=", + "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==", "dev": true, "requires": { "arrify": "^1.0.1", @@ -6533,19 +6530,19 @@ "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha1-bb9BHeZIy6+NkWnrsNLVdhkeL/E=", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", "dev": true }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, "get-own-enumerable-property-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha1-uHe0mlwWrvrDZV8u0upbaE340gM=", + "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", "dev": true }, "get-stdin": { @@ -6667,7 +6664,7 @@ "glob-watcher": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", - "integrity": "sha1-iKir8cTRMeuTkomUvEpZPC5d1iY=", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -6745,7 +6742,7 @@ "gulp": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha1-VDZRBw/Q9qsKBlDGo+b/WnywnKo=", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", "dev": true, "requires": { "glob-watcher": "^5.0.3", @@ -6757,7 +6754,7 @@ "gulp-cli": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", - "integrity": "sha1-VTMSbut/5BWn4+hKKX0zTVz3Drw=", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -6785,7 +6782,7 @@ "gulp-babel": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-8.0.0.tgz", - "integrity": "sha1-4NqW9PLsSojdOjAw9HbjirISbYc=", + "integrity": "sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ==", "dev": true, "requires": { "plugin-error": "^1.0.1", @@ -6825,7 +6822,7 @@ "gulp-decompress": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-2.0.2.tgz", - "integrity": "sha1-bEH1rNjoznKAn+OuAWdfWi0T790=", + "integrity": "sha512-S0ORQYTqksiKMWClGJtjtIgevrTVUbu7KguP74xxXvIiEINS4v7QjjZ8su8hGYPOJ2zW0WGVysgoct4HzINNqQ==", "dev": true, "requires": { "archive-type": "^4.0.0", @@ -6910,7 +6907,7 @@ "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -7073,7 +7070,7 @@ "gulp-jasmine": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/gulp-jasmine/-/gulp-jasmine-4.0.0.tgz", - "integrity": "sha1-7+VmuDUPQaFPY/+uzGzN+GRnCak=", + "integrity": "sha512-0UqY2fA6RCdUDJDsVym3zXYSWmt0AV7YY/6PAeKb+oGTKEgS7zZOH5w/4gcSKs+2FXiWrucQwLDvtEKIDbpF4A==", "dev": true, "requires": { "arrify": "^1.0.1", @@ -7098,7 +7095,7 @@ "gulp-replace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", - "integrity": "sha1-syvWFlTZe414Qwpns+jOBnt8kUM=", + "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", "dev": true, "requires": { "istextorbinary": "2.2.1", @@ -7109,7 +7106,7 @@ "gulp-typescript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-5.0.1.tgz", - "integrity": "sha1-lsZWWm6zHgjCquHIV7GgeeYibZQ=", + "integrity": "sha512-YuMMlylyJtUSHG1/wuSVTrZp60k1dMEFKYOvDf7OvbAJWrDtxxD4oZon4ancdWwzjj30ztiidhe4VXJniF0pIQ==", "dev": true, "requires": { "ansi-colors": "^3.0.5", @@ -7123,7 +7120,7 @@ "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha1-46PaS/uubIapwoViXeEkojQCb78=", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", "dev": true }, "replace-ext": { @@ -7135,7 +7132,7 @@ "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha1-UwL4FpAxc1ImVECS5kmB91F1A4M=", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true }, "vinyl": { @@ -7157,7 +7154,7 @@ "gulp-uglify": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", - "integrity": "sha1-X1sugzf4ecqd7Jcf6xuCpah4ULA=", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", "dev": true, "requires": { "array-each": "^1.0.1", @@ -7231,7 +7228,7 @@ "gulp-watch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", - "integrity": "sha1-g9N4dS9b+0baAj5zwX7R2nBmIV0=", + "integrity": "sha512-HnTSBdzAOFIT4wmXYPDUn783TaYAq9bpaN05vuZNP5eni3z3aRx0NAKbjhhMYtcq76x4R1wf4oORDGdlrEjuog==", "dev": true, "requires": { "ansi-colors": "1.1.0", @@ -7251,7 +7248,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { "micromatch": "^2.1.5", @@ -7408,7 +7405,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -7512,7 +7509,7 @@ "hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -7539,7 +7536,7 @@ "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha1-dDKYzvTlrz4ZQWH7rcwhUdOgWOg=", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "requires": { "parse-passwd": "^1.0.0" @@ -7548,7 +7545,7 @@ "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "htmlescape": { @@ -7596,7 +7593,7 @@ "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8=", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", @@ -7637,7 +7634,7 @@ "husky": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/husky/-/husky-2.3.0.tgz", - "integrity": "sha1-i3jtJNdjBC33/YmZkZhdZal23RM=", + "integrity": "sha512-A/ZQSEILoq+mQM3yC3RIBSaw1bYXdkKnyyKVSUiJl+iBjVZc5LQEXdGY1ZjrDxC4IzfRPiJ0IqzEQGCN5TQa/A==", "dev": true, "requires": { "cosmiconfig": "^5.2.0", @@ -7679,7 +7676,7 @@ "get-stdin": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha1-jV3pjxUXGhJcXlFmQ8em0OqKlvY=", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", "dev": true }, "get-stream": { @@ -7738,7 +7735,7 @@ "pkg-dir": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.1.0.tgz", - "integrity": "sha1-quuRwNO5xPdKRK2En03jR4GuAd4=", + "integrity": "sha512-55k9QN4saZ8q518lE6EFgYiu95u3BWkSajCifhdQjvLvmr8IpnRbhI+UGpWJQfa0KzDguHeeWT1ccO1PmkOi3A==", "dev": true, "requires": { "find-up": "^3.0.0" @@ -7757,7 +7754,7 @@ "read-pkg": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.1.1.tgz", - "integrity": "sha1-XPI03eekBckMiKUZq3PEZ+nLg/U=", + "integrity": "sha512-dFcTLQi6BZ+aFUaICg7er+/usEoqFdQxiEBsEMNGoipenihtxxtdrQuBXvyANCEI8VuUIVYFgeHGx9sLLvim4w==", "dev": true, "requires": { "@types/normalize-package-data": "^2.4.0", @@ -7769,7 +7766,7 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ=", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true } } @@ -7874,7 +7871,7 @@ "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha1-7BaFWOlaoYH9h9N/VcMrvLZwi4Q=", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, "iferr": { @@ -7886,13 +7883,13 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "import-fresh": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", - "integrity": "sha1-o9iX9CDKsOZxI2iX91vBS0iFw5A=", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -8021,7 +8018,7 @@ "insert-module-globals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", - "integrity": "sha1-7IfltCcoR54ye9XFxxYR3ftHUro=", + "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", "dev": true, "requires": { "JSONStream": "^1.0.3", @@ -8051,7 +8048,7 @@ "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha1-1QYaYiS+WOgIOYX1AU2EQ1lXYpY=", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, "invariant": { @@ -8123,13 +8120,13 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, "requires": { "ci-info": "^2.0.0" @@ -8231,7 +8228,7 @@ "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -8278,7 +8275,7 @@ "is-observable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha1-s+mGyPRN6VCGfKtUA/WjRlAFl14=", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", "dev": true, "requires": { "symbol-observable": "^1.1.0" @@ -8301,7 +8298,7 @@ "is-path-in-cwd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha1-WsSLNF72dTOb1sekipEhELJBz1I=", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { "is-path-inside": "^1.0.0" @@ -8370,7 +8367,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, "is-stream": { @@ -8382,7 +8379,7 @@ "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "requires": { "has-symbols": "^1.0.0" @@ -8430,7 +8427,7 @@ "isbinaryfile": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha1-XW3vPt6/boyoyunDAYOoBLX4voA=", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", "dev": true, "requires": { "buffer-alloc": "^1.2.0" @@ -8457,7 +8454,7 @@ "istextorbinary": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", - "integrity": "sha1-pSMaCO9t0ismjQiVCEz41Ytb7FM=", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", "dev": true, "requires": { "binaryextensions": "2", @@ -8468,70 +8465,36 @@ "jasmine": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.4.0.tgz", - "integrity": "sha1-D6aJA/8MlpdFnNBEtE9NzvXsi9w=", + "integrity": "sha512-sR9b4n+fnBFDEd7VS2el2DeHgKcPiMVn44rtKFumq9q7P/t8WrxsVIZPob4UDdgcDNCwyDqwxCt4k9TDRmjPoQ==", "dev": true, "requires": { "glob": "^7.1.3", "jasmine-core": "~3.4.0" } }, - "jasmine-console-reporter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jasmine-console-reporter/-/jasmine-console-reporter-3.1.0.tgz", - "integrity": "sha1-+c2ZA7aQy3BCjQIqVs1IxfWmH0E=", + "jasmine-core": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz", + "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", + "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "ci-info": "^1.4.0", - "node-emoji": "^1.8.1", - "ora": "^3.0.0", - "perfy": "^1.1.5" + "colors": "1.1.2" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc=", + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, - "jasmine-core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz", - "integrity": "sha1-KnRhjpZgJlMMNRjwPp+EXSZHPOM=", - "dev": true - }, "jasmine-terminal-reporter": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/jasmine-terminal-reporter/-/jasmine-terminal-reporter-1.0.3.tgz", @@ -8545,7 +8508,7 @@ "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha1-xs7ljrNVA3LfjeuF+tXOZs4B1Z0=", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", "dev": true }, "js-string-escape": { @@ -8563,7 +8526,7 @@ "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc=", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -8573,7 +8536,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true } } @@ -8711,7 +8674,7 @@ "karma": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz", - "integrity": "sha1-0HOHyXQ6V1tA+vc+ij61Qhwhk+E=", + "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -8746,13 +8709,13 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -8811,7 +8774,7 @@ "karma-jasmine": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz", - "integrity": "sha1-JuPjHy+vJy3YDrsOGJiRTMOhl2M=", + "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", "dev": true, "requires": { "jasmine-core": "^3.3" @@ -8919,7 +8882,7 @@ "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha1-ybpggfkIZwYH7nkGLXAN8GLFLtM=", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", "dev": true, "requires": { "extend": "^3.0.0", @@ -9060,7 +9023,7 @@ "listr": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha1-L+qQlgTkNL5GTFC926DUlpKPpYY=", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", "dev": true, "requires": { "@samverschueren/stream-to-observable": "^0.3.0", @@ -9077,7 +9040,7 @@ "p-map": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha1-MQko/u+cnsxltosXaTAYpmXOoXU=", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true } } @@ -9091,7 +9054,7 @@ "listr-update-renderer": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha1-Tqg2hUinuK7LfgbYyVy0WuLt5qI=", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", "dev": true, "requires": { "chalk": "^1.1.3", @@ -9134,7 +9097,7 @@ "listr-verbose-renderer": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha1-8RMhZ1NepMEmEQK58o2sfLoeA9s=", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -9189,13 +9152,13 @@ "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", "dev": true }, "loader-utils": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -9206,7 +9169,7 @@ "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -9227,7 +9190,7 @@ "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash._basecopy": { @@ -9433,12 +9396,6 @@ "lodash.escape": "^3.0.0" } }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", - "dev": true - }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", @@ -9448,7 +9405,7 @@ "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { "chalk": "^2.0.1" @@ -9526,7 +9483,7 @@ "log4js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.2.0.tgz", - "integrity": "sha1-ZZqR2VIgU7Hh0LqJrfgcIAW4qZM=", + "integrity": "sha512-1dJ2ORJcdqbzxvzKM2ceqPBh4O6bbICJpB4dvSEUoMcb14s8MqQ/54zNPqekuN5yjGtxO3GUDTvZfQOQhwdqnA==", "dev": true, "requires": { "date-format": "^2.0.0", @@ -9539,7 +9496,7 @@ "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -9548,7 +9505,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } @@ -9572,7 +9529,7 @@ "lolex": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.0.1.tgz", - "integrity": "sha1-SpnCJRV51pPGoINEba4OXDhE0/o=", + "integrity": "sha512-UHuOBZ5jjsKuzbB/gRNNW8Vg8f00Emgskdq2kvZxgBJCS0aqquAuXai/SkWORlKeZEiNQWZjFZOqIUcH9LqKCw==", "dev": true }, "loose-envify": { @@ -9587,7 +9544,7 @@ "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -9614,7 +9571,7 @@ "make-error": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha1-7+ToH22yjK3WBccPKcgxtY73dsg=", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, "make-error-cause": { @@ -9638,7 +9595,7 @@ "make-plural": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", - "integrity": "sha1-8j3gjv2wysLgybqfMVsN/2tMJzU=", + "integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -9709,7 +9666,7 @@ "matcher": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", - "integrity": "sha1-UdgwHhOPhAmCszixFrsMCa9iwcI=", + "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.4" @@ -9718,13 +9675,13 @@ "math-random": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha1-XdaUPJOFSCZwFtTjTwV1gwgMUUw=", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", "dev": true }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { "hash-base": "^3.0.0", @@ -9760,7 +9717,7 @@ "messageformat": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-1.1.1.tgz", - "integrity": "sha1-zqoubIaSnUgHBYJ1pzcrG9ljvfY=", + "integrity": "sha512-Q0uXcDtF5pEZsVSyhzDOGgZZK6ykN79VY9CwU3Nv0gsqx62BjdJW0MT+63UkHQ4exe3HE33ZlxR2/YwoJarRTg==", "dev": true, "requires": { "glob": "~7.0.6", @@ -9789,7 +9746,7 @@ "messageformat-parser": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-1.1.0.tgz", - "integrity": "sha1-E7oiUKdrvejg/KDbs0dflcWUqQo=", + "integrity": "sha512-Hwem6G3MsKDLS1FtBRGIs8T50P1Q00r3srS6QJePCFbad9fq0nYxwf3rnU2BreApRGhmpKMV7oZI06Sy1c9TPA==", "dev": true }, "micromatch": { @@ -9847,7 +9804,7 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimalistic-assert": { @@ -9880,7 +9837,7 @@ "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -9898,7 +9855,7 @@ "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -9958,7 +9915,7 @@ "module-deps": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", - "integrity": "sha1-1BoueQJFzjGRceTnxNjHOZO6PNU=", + "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", "dev": true, "requires": { "JSONStream": "^1.0.3", @@ -10059,13 +10016,13 @@ "mustache": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.0.1.tgz", - "integrity": "sha1-hzhV8jqoqVsVD7ltmDbtvFodJIo=", + "integrity": "sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA==", "dev": true }, "mute-stdout": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha1-rLAwDrTeI6fd7sAU4+lgRLNHIzE=", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", "dev": true }, "mute-stream": { @@ -10084,7 +10041,7 @@ "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -10109,13 +10066,13 @@ "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", "dev": true }, "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha1-rCetpmFn+ohJpq3dg39rGJrSCBw=", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, "next-tick": { @@ -10127,22 +10084,13 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-emoji": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", - "integrity": "sha1-iIar0l2ce7YYAqZYUj0fjSqJsto=", - "dev": true, - "requires": { - "lodash.toarray": "^4.4.0" - } - }, "node-libs-browser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", - "integrity": "sha1-xy9g2dRt4IqUDe27JfP/ovm7qnc=", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", "dev": true, "requires": { "assert": "^1.1.1", @@ -10184,7 +10132,7 @@ "events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha1-mgoN+vYok9krh1uPJpjKQRSXPog=", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", "dev": true }, "path-browserify": { @@ -10217,7 +10165,7 @@ "util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, "requires": { "inherits": "2.0.3" @@ -10243,7 +10191,7 @@ "node-releases": { "version": "1.1.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.19.tgz", - "integrity": "sha1-xJLR44H+oDULM4tkbCeGfojpGz0=", + "integrity": "sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA==", "dev": true, "requires": { "semver": "^5.3.0" @@ -10269,7 +10217,7 @@ "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -10281,7 +10229,7 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha1-eQp89v6lRZuslhELKbYEEtyP+Ws=", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true } } @@ -10298,7 +10246,7 @@ "now-and-later": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha1-jlechoV2SnzALLaAOA6U9DzLH3w=", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", "dev": true, "requires": { "once": "^1.3.2" @@ -10307,7 +10255,7 @@ "npm-path": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha1-xkE0el/51qCeTZvOVYDE9QUnjmQ=", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", "dev": true, "requires": { "which": "^1.2.10" @@ -10436,7 +10384,7 @@ "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { "define-properties": "^1.1.2", @@ -10572,66 +10520,6 @@ "wordwrap": "~1.0.0" } }, - "ora": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", - "integrity": "sha1-vwdSSRBZo+8+1MhQl1Md6f280xg=", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-spinners": "^2.0.0", - "log-symbols": "^2.2.0", - "strip-ansi": "^5.2.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", @@ -10697,7 +10585,7 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha1-5OlPMR6rvIYzoeeZCBZfyiYkG2s=", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, "p-queue": { @@ -10715,7 +10603,7 @@ "pako": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha1-Qyi621CGpCaqkPVBl31JVdpclzI=", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, "parallel-transform": { @@ -10732,7 +10620,7 @@ "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { "callsites": "^3.0.0" @@ -10750,7 +10638,7 @@ "parse-asn1": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", - "integrity": "sha1-N/Zij4I/vesic7TVQENKIvPvH8w=", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { "asn1.js": "^4.0.0", @@ -10813,7 +10701,7 @@ "parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha1-4rXb7eAOf6m8NjYH9TMn6LBzGJs=", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true }, "parse-passwd": { @@ -10852,7 +10740,7 @@ "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "pascalcase": { @@ -10864,7 +10752,7 @@ "path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo=", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "path-dirname": { @@ -10900,7 +10788,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-platform": { @@ -10936,7 +10824,7 @@ "pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -10958,12 +10846,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "perfy": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/perfy/-/perfy-1.1.5.tgz", - "integrity": "sha1-DWKfhwo0o+sYZtPbSF0rP67ynks=", - "dev": true - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -10988,7 +10870,7 @@ "pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha1-ZDqSyviUVm+RsrmG0sZpUKji+4c=", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", "dev": true, "requires": { "node-modules-regexp": "^1.0.0" @@ -11006,7 +10888,7 @@ "please-upgrade-node": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", - "integrity": "sha1-7TIAUd/MUCT65pZxLIKImTWV6Kw=", + "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", "dev": true, "requires": { "semver-compare": "^1.0.0" @@ -11057,7 +10939,7 @@ "prettier-eslint": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-8.8.2.tgz", - "integrity": "sha1-/LKaSKtFJOI0aAeX/nDp0TbMrws=", + "integrity": "sha512-2UzApPuxi2yRoyMlXMazgR6UcH9DKJhNgCviIwY3ixZ9THWSSrUww5vkiZ3C48WvpFl1M1y/oU63deSy1puWEA==", "dev": true, "requires": { "babel-runtime": "^6.26.0", @@ -11078,7 +10960,7 @@ "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "dev": true }, "acorn-jsx": { @@ -11125,7 +11007,7 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -11134,7 +11016,7 @@ "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -11180,7 +11062,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -11189,7 +11071,7 @@ "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { "esutils": "^2.0.2" @@ -11198,7 +11080,7 @@ "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha1-MtHWU+HZBAiFS/spbwdux+GGowA=", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { "ajv": "^5.3.0", @@ -11262,7 +11144,7 @@ "espree": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha1-sPRHGHyKi+2US4FaZgvd9d610ac=", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { "acorn": "^5.5.0", @@ -11272,7 +11154,7 @@ "external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { "chardet": "^0.4.0", @@ -11299,7 +11181,7 @@ "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha1-LC73dSXMKSkAff/6HdMUqpyd7m8=", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, "requires": { "circular-json": "^0.3.1", @@ -11317,7 +11199,7 @@ "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "indent-string": { @@ -11329,7 +11211,7 @@ "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { "ansi-escapes": "^3.0.0", @@ -11367,25 +11249,25 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha1-DjUW3Qt5BPQT0tQZPc5GGMOmias=", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "dev": true }, "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" @@ -11403,7 +11285,7 @@ "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -11412,7 +11294,7 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { "ajv": "^5.2.3", @@ -11426,7 +11308,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -11435,7 +11317,7 @@ "typescript": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha1-HL9h0F1rliaSROtqO85L2RTg8Aw=", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", "dev": true }, "write": { @@ -11452,7 +11334,7 @@ "prettier-eslint-cli": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-4.7.1.tgz", - "integrity": "sha1-PRA8SUuqToC5mtU+K523YgEBhZ8=", + "integrity": "sha512-hQbsGaEVz97oBBcKdsJ46khv0kOGkMyWrXzcFOXW6X8UuetZ/j0yDJkNJgUTVc6PVFbbzBXk+qgd5vos9qzXPQ==", "dev": true, "requires": { "arrify": "^1.0.1", @@ -11478,7 +11360,7 @@ "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "dev": true }, "acorn-jsx": { @@ -11525,7 +11407,7 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -11551,7 +11433,7 @@ "chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { "ansi-styles": "^3.1.0", @@ -11645,7 +11527,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -11654,7 +11536,7 @@ "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { "esutils": "^2.0.2" @@ -11663,7 +11545,7 @@ "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha1-MtHWU+HZBAiFS/spbwdux+GGowA=", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { "ajv": "^5.3.0", @@ -11727,7 +11609,7 @@ "espree": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha1-sPRHGHyKi+2US4FaZgvd9d610ac=", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { "acorn": "^5.5.0", @@ -11737,7 +11619,7 @@ "external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { "chardet": "^0.4.0", @@ -11773,7 +11655,7 @@ "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha1-LC73dSXMKSkAff/6HdMUqpyd7m8=", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", "dev": true, "requires": { "circular-json": "^0.3.1", @@ -11803,7 +11685,7 @@ "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "indent-string": { @@ -11815,7 +11697,7 @@ "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { "ansi-escapes": "^3.0.0", @@ -11875,13 +11757,13 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { "p-try": "^1.0.0" @@ -11911,19 +11793,19 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "regexpp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha1-DjUW3Qt5BPQT0tQZPc5GGMOmias=", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "dev": true }, "rxjs": { "version": "5.5.12", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha1-b6YbinfD15PbrycL7i9D9lLXQcw=", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", "dev": true, "requires": { "symbol-observable": "1.0.1" @@ -11932,7 +11814,7 @@ "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0" @@ -11959,7 +11841,7 @@ "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { "ajv": "^5.2.3", @@ -11973,7 +11855,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -11997,7 +11879,7 @@ "yargs": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz", - "integrity": "sha1-ZULevZCArVF+xQSPtFTv6eTUqq4=", + "integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==", "dev": true, "requires": { "cliui": "^3.2.0", @@ -12019,7 +11901,7 @@ "pretty-format": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha1-XqrI7razO5h7f+YJfqaooUarV2A=", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", "dev": true, "requires": { "ansi-regex": "^3.0.0", @@ -12070,7 +11952,7 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "promise-inflight": { @@ -12082,7 +11964,7 @@ "property-expr": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", - "integrity": "sha1-IuhwaJSgyOKNWHNYBPa6OjZzMU8=", + "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", "dev": true }, "prr": { @@ -12106,7 +11988,7 @@ "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "requires": { "bn.js": "^4.1.0", @@ -12176,7 +12058,7 @@ "randomatic": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha1-t3bvxZN1mE42xTey9RofCv8Noe0=", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, "requires": { "is-number": "^4.0.0", @@ -12195,7 +12077,7 @@ "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -12214,13 +12096,13 @@ "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE=", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, "raw-body": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha1-oc5vucm8NWylLoklarWQWeE9AzI=", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { "bytes": "3.1.0", @@ -12299,7 +12181,7 @@ "readdirp": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -12325,7 +12207,7 @@ "regenerate-unicode-properties": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha1-71Hg8OpK1CS3e/fLQfPgFccKPw4=", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -12365,13 +12247,13 @@ "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha1-wr8eN3Ug0yT2I4kuM8EMrCwlK1M=", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", "dev": true, "requires": { "is-buffer": "^1.1.5", @@ -12410,7 +12292,7 @@ "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { @@ -12584,7 +12466,7 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-options": { @@ -12621,13 +12503,13 @@ "rfdc": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", - "integrity": "sha1-unLME2egzNnPgahws7WL060H+MI=", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", "dev": true }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { "glob": "^7.1.3" @@ -12655,7 +12537,7 @@ "run-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", - "integrity": "sha1-RrULlGoqotSUeuHYhumFb9nKvl4=", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", "dev": true }, "run-queue": { @@ -12670,7 +12552,7 @@ "run-sequence": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.1.tgz", - "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", + "integrity": "sha512-qkzZnQWMZjcKbh3CNly2srtrkaO/2H/SI5f2eliMCapdRD3UhMrwjfOAZJAnZ2H8Ju4aBzFZkBGXUqFs9V0yxw==", "dev": true, "requires": { "chalk": "^1.1.3", @@ -12785,7 +12667,7 @@ "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { "ajv": "^6.1.0", @@ -12805,7 +12687,7 @@ "semver": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha1-BeNZ7lceWtftZBpu7B5Ue6Ut6mU=", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", "dev": true }, "semver-compare": { @@ -12826,7 +12708,7 @@ "serialize-javascript": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha1-1uDfsqODKoyURo5usduX5VoZKmU=", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", "dev": true }, "set-blocking": { @@ -12867,7 +12749,7 @@ "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, "sha.js": { @@ -12932,7 +12814,7 @@ "simple-git": { "version": "1.113.0", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.113.0.tgz", - "integrity": "sha1-ZomJcooenPTsbHK2nqLuzJNIm+o=", + "integrity": "sha512-i9WVsrK2u0G/cASI9nh7voxOk9mhanWY9eGtWBDSYql6m49Yk5/Fan6uZsDr/xmzv8n+eQ8ahKCoEr8cvU3h+g==", "dev": true, "requires": { "debug": "^4.0.1" @@ -12941,7 +12823,7 @@ "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -12964,7 +12846,7 @@ "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, "requires": { "ansi-styles": "^3.2.0", @@ -13093,7 +12975,7 @@ "socket.io": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha1-oGnF/qvuPmshSnW0DOBlLhz7mYA=", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { "debug": "~3.1.0", @@ -13107,7 +12989,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13124,7 +13006,7 @@ "socket.io-client": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha1-3LOBA0NqtFeN2wJmOK4vIbYjZx8=", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", @@ -13152,7 +13034,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13163,7 +13045,7 @@ "socket.io-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha1-58Yii2qh+BTmFIrqMltRqpSZ4Hc=", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { "component-emitter": "1.2.1", @@ -13180,7 +13062,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -13197,7 +13079,7 @@ "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", "dev": true }, "source-map": { @@ -13252,7 +13134,7 @@ "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ=", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -13262,7 +13144,7 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { @@ -13278,7 +13160,7 @@ "spdx-license-ids": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha1-dezRqI3owYTvAV6vtRtbSL/RG7E=", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", "dev": true }, "split-string": { @@ -13316,7 +13198,7 @@ "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { "figgy-pudding": "^3.5.1" @@ -13331,7 +13213,7 @@ "staged-git-files": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", - "integrity": "sha1-QybTOIbcns+immGTv1EbqQpGRUs=", + "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", "dev": true }, "static-extend": { @@ -13404,7 +13286,7 @@ "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { "inherits": "~2.0.1", @@ -13440,7 +13322,7 @@ "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { "builtin-status-codes": "^3.0.0", @@ -13469,7 +13351,7 @@ "streamroller": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz", - "integrity": "sha1-cWYMILBrGnsgTUYIVzGtE8EKVi0=", + "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==", "dev": true, "requires": { "async": "^2.6.2", @@ -13482,7 +13364,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -13491,7 +13373,7 @@ "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -13502,7 +13384,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true } } @@ -13516,7 +13398,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -13552,7 +13434,7 @@ "stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha1-cDBlrvyhkwDTzoivT1s5VtdVZik=", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, "requires": { "get-own-enumerable-property-symbols": "^3.0.0", @@ -13599,7 +13481,7 @@ "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha1-SYdzYmT8NEzyD2w0rKnRPR1O1sU=", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", "dev": true, "requires": { "is-natural-number": "^4.0.1" @@ -13658,7 +13540,7 @@ "synchronous-promise": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.7.tgz", - "integrity": "sha1-NXSz0vroaxRTVqS4kQPhV39kb+M=", + "integrity": "sha512-16GbgwTmFMYFyQMLvtQjvNWh30dsFe1cAW5Fg1wm5+dg84L9Pe36mftsIRU95/W2YsISxsz/xq4VB23sqpgb/A==", "dev": true }, "syntax-error": { @@ -13719,13 +13601,13 @@ "tapable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha1-ofzMBrWNth/XpF2i2kT186Pme6I=", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU=", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "dev": true, "requires": { "bl": "^1.0.0", @@ -13740,7 +13622,7 @@ "terser": { "version": "3.17.0", "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha1-+I/77aDetWN/nSSw2mb04VqxDLI=", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", "dev": true, "requires": { "commander": "^2.19.0", @@ -13751,13 +13633,13 @@ "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha1-1YuytcHuj4ew00ACfp6U4iLFpCI=", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-support": { @@ -13810,7 +13692,7 @@ "textextensions": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", - "integrity": "sha1-ahQ6mFRkOEzCz/Ea6kSM1bAY5ys=", + "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", "dev": true }, "throttleit": { @@ -13837,7 +13719,7 @@ "through2-filter": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha1-cA54bfI2fCyIzYqlvkz5weeDElQ=", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", "dev": true, "requires": { "through2": "~2.0.0", @@ -13874,7 +13756,7 @@ "tmp": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", - "integrity": "sha1-7kNKTiJUMILilLpiAdzG6v76KHc=", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", "dev": true, "requires": { "rimraf": "^2.6.3" @@ -13980,7 +13862,7 @@ "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, "toposort": { @@ -14052,13 +13934,13 @@ "type-fest": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha1-i993dDOF2KTxO6lfYQ9czWjHKPg=", + "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", "dev": true }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", @@ -14068,13 +13950,13 @@ "mime-db": { "version": "1.40.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha1-plBX6ZjbCQ9zKmj2wnbTh9QSbDI=", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", "dev": true }, "mime-types": { "version": "2.1.24", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha1-tvjQs+lR77d97eyhlM/20W9nb4E=", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "dev": true, "requires": { "mime-db": "1.40.0" @@ -14091,13 +13973,13 @@ "typescript": { "version": "3.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", - "integrity": "sha1-LSYY0Qu1ZlcrjXqtUYDYQlfXCpk=", + "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", "dev": true }, "typescript-eslint-parser": { "version": "16.0.1", "resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-16.0.1.tgz", - "integrity": "sha1-tAaBxwQ7IiuXcnSLcAoACyQcAxs=", + "integrity": "sha512-IKawLTu4A2xN3aN/cPLxvZ0bhxZHILGDKTZWvWNJ3sLNhJ3PjfMEDQmR2VMpdRPrmWOadgWXRwjLBzSA8AGsaQ==", "dev": true, "requires": { "lodash.unescape": "4.0.1", @@ -14107,7 +13989,7 @@ "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true } } @@ -14139,7 +14021,7 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, "umd": { @@ -14151,7 +14033,7 @@ "unbzip2-stream": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", - "integrity": "sha1-0VbSBeZw2NjDk+HALr1QZCKHP2o=", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", "dev": true, "requires": { "buffer": "^5.2.1", @@ -14167,7 +14049,7 @@ "undeclared-identifiers": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha1-klTB03vawKwrUt5LZyJ5LSqR4w8=", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", "dev": true, "requires": { "acorn-node": "^1.3.0", @@ -14180,7 +14062,7 @@ "undertaker": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha1-cBZi/4zjWHFTJN/UkqTwNgVd/ks=", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", "dev": true, "requires": { "arr-flatten": "^1.0.1", @@ -14203,13 +14085,13 @@ "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", "dev": true }, "unicode-match-property-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "dev": true, "requires": { "unicode-canonical-property-names-ecmascript": "^1.0.4", @@ -14219,13 +14101,13 @@ "unicode-match-property-value-ecmascript": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha1-W0tCbgjROoA2Xg1lesemwexGonc=", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", "dev": true }, "unicode-property-aliases-ecmascript": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha1-qcxsx85joKMCP8meNBuUQx1AWlc=", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, "union-value": { @@ -14266,7 +14148,7 @@ "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "dev": true, "requires": { "unique-slug": "^2.0.0" @@ -14275,7 +14157,7 @@ "unique-slug": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha1-Xp7cbRzo+yZNsYpQfvm9hURFHKY=", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", "dev": true, "requires": { "imurmurhash": "^0.1.4" @@ -14284,7 +14166,7 @@ "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha1-xl0RDppK35psWUiygFPZqNBMvqw=", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", "dev": true, "requires": { "json-stable-stringify-without-jsonify": "^1.0.1", @@ -14346,7 +14228,7 @@ "upath": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha1-PbZYYA7a7sy+bbXmhNZ+6MKs0Gg=", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", "dev": true }, "uri-js": { @@ -14384,13 +14266,13 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, "useragent": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", "dev": true, "requires": { "lru-cache": "4.1.x", @@ -14400,7 +14282,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -14411,7 +14293,7 @@ "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha1-OqASW/5mikZy3liFfTrOJ+y3aQE=", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, "requires": { "inherits": "2.0.3" @@ -14438,7 +14320,7 @@ "v8flags": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha1-/J3CNSHKIMVDP4HMTrmzAzuxBdg=", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -14447,7 +14329,7 @@ "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -14569,7 +14451,7 @@ "vinyl-fs": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha1-yFhJQF9nQo/qu71cXb3WT0fTG8c=", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", "dev": true, "requires": { "fs-mkdirp-stream": "^1.0.0", @@ -14610,7 +14492,7 @@ "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha1-2FsH2pbkWNJbL/4Z/s6fLKoT7YY=", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { "clone": "^2.1.1", @@ -14714,7 +14596,7 @@ "vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha1-vXbWojMj4sqP+hICjcBFWcdfkBk=", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, "void-elements": { @@ -14726,7 +14608,7 @@ "vue-eslint-parser": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", - "integrity": "sha1-wmjJbG2Uz+PZOKX3WTlZsMozYNE=", + "integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==", "dev": true, "requires": { "debug": "^3.1.0", @@ -14808,15 +14690,6 @@ "neo-async": "^2.5.0" } }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, "webidl-conversions": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", @@ -14908,7 +14781,7 @@ "worker-farm": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag=", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", "dev": true, "requires": { "errno": "~0.1.7" @@ -14955,7 +14828,7 @@ "write": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" @@ -14964,7 +14837,7 @@ "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { "async-limiter": "~1.0.0", @@ -15179,7 +15052,7 @@ "yup": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/yup/-/yup-0.27.0.tgz", - "integrity": "sha1-+MsZjI590hJL7dwkV1cTKQlrBuc=", + "integrity": "sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ==", "dev": true, "requires": { "@babel/runtime": "^7.0.0", diff --git a/package.json b/package.json index fd2620fa9..24847c0c2 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "gulp-uglify": "^3.0.2", "gulp-watch": "^5.0.1", "husky": "^2.3.0", - "jasmine-console-reporter": "^3.1.0", + "jasmine-spec-reporter": "^4.2.1", "karma": "^4.1.0", "karma-browserify": "^6.0.0", "karma-chrome-launcher": "^2.2.0", diff --git a/src/session.js b/src/session.js index 75cd68fa9..08339508b 100644 --- a/src/session.js +++ b/src/session.js @@ -153,16 +153,7 @@ class Session { const arg = transactionConfig let txConfig = TxConfig.empty() - if ( - typeof arg === 'string' || - arg instanceof String || - Array.isArray(arg) - ) { - // argument looks like a single or multiple bookmarks - // bookmarks in this function are deprecated but need to be supported for backwards compatibility - this._updateBookmark(new Bookmark(arg)) - } else if (arg) { - // argument is probably a transaction configuration + if (arg) { txConfig = new TxConfig(arg) } diff --git a/test/internal/bolt-stub.js b/test/internal/bolt-stub.js index 72ba59de3..fd8acb2c2 100644 --- a/test/internal/bolt-stub.js +++ b/test/internal/bolt-stub.js @@ -60,13 +60,13 @@ class SupportedBoltStub extends UnsupportedBoltStub { if (verbose) { boltStub.stdout.on('data', data => { - console.log(`${data}`) + console.warn(`${data}`) }) boltStub.stderr.on('data', data => { - console.log(`${data}`) + console.warn(`${data}`) }) boltStub.on('end', data => { - console.log(data) + console.warn(data) }) } @@ -76,7 +76,7 @@ class SupportedBoltStub extends UnsupportedBoltStub { }) boltStub.on('error', error => { - console.log('Failed to start child process:' + error) + console.warn('Failed to start child process:' + error) }) return new StubServer(() => exitCode) @@ -114,7 +114,7 @@ function newDriver (url, config = {}) { // left here for debugging purposes const logging = { level: (process.env['NEOLOGLEVEL'] || 'error').toLowerCase(), - logger: (level, msg) => console.log(`${level}: ${msg}`) + logger: (level, msg) => console.warn(`${level}: ${msg}`) } // boltstub currently does not support encryption, create driver with encryption turned off const newConfig = Object.assign( diff --git a/test/internal/node/direct.driver.boltkit.test.js b/test/internal/node/direct.driver.boltkit.test.js index 27e49a366..5a56e70fb 100644 --- a/test/internal/node/direct.driver.boltkit.test.js +++ b/test/internal/node/direct.driver.boltkit.test.js @@ -34,519 +34,532 @@ describe('direct driver with stub server', () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout }) - it('should run query', done => { - if (!boltStub.supported) { - done() - return - } + describe('should run query', () => { + function verifyShouldRunQuery (version, done) { + if (!boltStub.supported) { + done() + return + } + + // Given + const server = boltStub.start( + `./test/resources/boltstub/${version}/return_x.script`, + 9001 + ) - // Given - const server = boltStub.start( - './test/resources/boltstub/return_x.script', - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - // When - const session = driver.session() - // Then - session.run('RETURN {x}', { x: 1 }).then(res => { - expect(res.records[0].get('x').toInt()).toEqual(1) - session.close() - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + // When + const session = driver.session() + // Then + session.run('RETURN $x', { x: 1 }).then(res => { + expect(res.records[0].get('x').toInt()).toEqual(1) + session.close() + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) }) + } + + it('v2', done => { + verifyShouldRunQuery('v2', done) + }) + + it('v3', done => { + verifyShouldRunQuery('v3', done) + }) + + it('v4', done => { + verifyShouldRunQuery('v4', done) }) }) - it('should send and receive bookmark for read transaction', done => { - if (!boltStub.supported) { - done() - return - } + describe('should send and receive bookmark for read transaction', () => { + function verifyBookmarkForReadTxc (version, done) { + if (!boltStub.supported) { + done() + return + } - const server = boltStub.start( - './test/resources/boltstub/read_tx_with_bookmarks.script', - 9001 - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/read_tx_with_bookmarks.script`, + 9001 + ) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session({ - defaultAccessMode: READ, - bookmarks: ['neo4j:bookmark:v1:tx42'] - }) - const tx = session.beginTransaction() - tx.run('MATCH (n) RETURN n.name AS name').then(result => { - const records = result.records - expect(records.length).toEqual(2) - expect(records[0].get('name')).toEqual('Bob') - expect(records[1].get('name')).toEqual('Alice') - - tx.commit().then(() => { - expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') - - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session({ + defaultAccessMode: READ, + bookmarks: ['neo4j:bookmark:v1:tx42'] + }) + const tx = session.beginTransaction() + tx.run('MATCH (n) RETURN n.name AS name').then(result => { + const records = result.records + expect(records.length).toEqual(2) + expect(records[0].get('name')).toEqual('Bob') + expect(records[1].get('name')).toEqual('Alice') + + tx.commit().then(() => { + expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') + + session.close(() => { + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) }) }) }) + } + + it('v2', done => { + verifyBookmarkForReadTxc('v2', done) + }) + + it('v3', done => { + verifyBookmarkForReadTxc('v3', done) + }) + + it('v4', done => { + verifyBookmarkForReadTxc('v4', done) }) }) - it('should send and receive bookmark for write transaction', done => { - if (!boltStub.supported) { - done() - return - } + describe('should send and receive bookmark for write transaction', () => { + function verifyBookmarkForWriteTxc (version, done) { + if (!boltStub.supported) { + done() + return + } - const server = boltStub.start( - './test/resources/boltstub/write_tx_with_bookmarks.script', - 9001 - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/write_tx_with_bookmarks.script`, + 9001 + ) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session({ - defaultAccessMode: WRITE, - bookmarks: ['neo4j:bookmark:v1:tx42'] - }) - const tx = session.beginTransaction() - tx.run("CREATE (n {name:'Bob'})").then(result => { - const records = result.records - expect(records.length).toEqual(0) - - tx.commit().then(() => { - expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') - - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session({ + defaultAccessMode: WRITE, + bookmarks: ['neo4j:bookmark:v1:tx42'] + }) + const tx = session.beginTransaction() + tx.run("CREATE (n {name:'Bob'})").then(result => { + const records = result.records + expect(records.length).toEqual(0) + + tx.commit().then(() => { + expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') + + session.close(() => { + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) }) }) }) - }) - }) - - it('should send and receive bookmark between write and read transactions', done => { - if (!boltStub.supported) { - done() - return } - const server = boltStub.start( - './test/resources/boltstub/write_read_tx_with_bookmarks.script', - 9001 - ) + it('v2', done => { + verifyBookmarkForWriteTxc('v2', done) + }) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session({ - defaultAccessMode: WRITE, - bookmarks: ['neo4j:bookmark:v1:tx42'] - }) - const writeTx = session.beginTransaction() - writeTx.run("CREATE (n {name:'Bob'})").then(result => { - const records = result.records - expect(records.length).toEqual(0) + it('v3', done => { + verifyBookmarkForWriteTxc('v3', done) + }) - writeTx.commit().then(() => { - expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') + it('v4', done => { + verifyBookmarkForWriteTxc('v4', done) + }) + }) - const readTx = session.beginTransaction() - readTx.run('MATCH (n) RETURN n.name AS name').then(result => { - const records = result.records - expect(records.length).toEqual(1) - expect(records[0].get('name')).toEqual('Bob') + describe('should send and receive bookmark between write and read transactions', () => { + function verifyBookmark (version, done) { + if (!boltStub.supported) { + done() + return + } - readTx.commit().then(() => { - expect(session.lastBookmark()).toEqual( - 'neo4j:bookmark:v1:tx424242' - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/write_read_tx_with_bookmarks.script`, + 9001 + ) - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session({ + defaultAccessMode: WRITE, + bookmarks: ['neo4j:bookmark:v1:tx42'] + }) + const writeTx = session.beginTransaction() + writeTx.run("CREATE (n {name:'Bob'})").then(result => { + const records = result.records + expect(records.length).toEqual(0) + + writeTx.commit().then(() => { + expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') + + const readTx = session.beginTransaction() + readTx.run('MATCH (n) RETURN n.name AS name').then(result => { + const records = result.records + expect(records.length).toEqual(1) + expect(records[0].get('name')).toEqual('Bob') + + readTx.commit().then(() => { + expect(session.lastBookmark()).toEqual( + 'neo4j:bookmark:v1:tx424242' + ) + + session.close(() => { + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) }) }) }) }) }) - }) - }) - - it('should be possible to override bookmark', done => { - if (!boltStub.supported) { - done() - return } - const server = boltStub.start( - './test/resources/boltstub/write_read_tx_with_bookmark_override.script', - 9001 - ) + it('v2', done => { + verifyBookmark('v2', done) + }) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session({ - defaultAccessMode: WRITE, - bookmarks: ['neo4j:bookmark:v1:tx42'] - }) - const writeTx = session.beginTransaction() - writeTx.run("CREATE (n {name:'Bob'})").then(result => { - const records = result.records - expect(records.length).toEqual(0) + it('v3', done => { + verifyBookmark('v3', done) + }) - writeTx.commit().then(() => { - expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') + it('v4', done => { + verifyBookmark('v4', done) + }) + }) - const readTx = session.beginTransaction('neo4j:bookmark:v1:tx99') - readTx.run('MATCH (n) RETURN n.name AS name').then(result => { - const records = result.records - expect(records.length).toEqual(1) - expect(records[0].get('name')).toEqual('Bob') + describe('should throw service unavailable when server dies', () => { + function verifyServiceUnavailable (version, done) { + if (!boltStub.supported) { + done() + return + } - readTx.commit().then(() => { - expect(session.lastBookmark()).toEqual( - 'neo4j:bookmark:v1:tx424242' - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/read_dead.script`, + 9001 + ) - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() - }) - }) - }) + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session({ defaultAccessMode: READ }) + session.run('MATCH (n) RETURN n.name').catch(error => { + expect(error.code).toEqual(neo4j.error.SERVICE_UNAVAILABLE) + + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() }) }) }) + } + + it('v2', done => { + verifyServiceUnavailable('v2', done) }) - }) - it('should not be possible to override bookmark with null', done => { - if (!boltStub.supported) { - done() - return - } + it('v3', done => { + verifyServiceUnavailable('v3', done) + }) - const server = boltStub.start( - './test/resources/boltstub/write_read_tx_with_bookmarks.script', - 9001 - ) + it('v4', done => { + verifyServiceUnavailable('v4', done) + }) + }) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session({ - defaultAccessMode: WRITE, - bookmarks: ['neo4j:bookmark:v1:tx42'] - }) - const writeTx = session.beginTransaction() - writeTx.run("CREATE (n {name:'Bob'})").then(result => { - const records = result.records - expect(records.length).toEqual(0) + describe('should close connection when RESET fails', () => { + function verifyCloseConnection (version, done) { + if (!boltStub.supported) { + done() + return + } + + const server = boltStub.start( + `./test/resources/boltstub/${version}/reset_error.script`, + 9001 + ) - writeTx.commit().then(() => { - expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session() - const readTx = session.beginTransaction(null) - readTx.run('MATCH (n) RETURN n.name AS name').then(result => { + session + .run('RETURN 42 AS answer') + .then(result => { const records = result.records expect(records.length).toEqual(1) - expect(records[0].get('name')).toEqual('Bob') - - readTx.commit().then(() => { - expect(session.lastBookmark()).toEqual( - 'neo4j:bookmark:v1:tx424242' - ) - - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() - }) + expect(records[0].get(0).toNumber()).toEqual(42) + session.close(() => { + expect(driver._pool._pools['127.0.0.1:9001'].length).toEqual(0) + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() }) }) }) - }) + .catch(error => done.fail(error)) }) + } + + it('v2', done => { + verifyCloseConnection('v2', done) }) - }) - it('should throw service unavailable when server dies', done => { - if (!boltStub.supported) { - done() - return - } + it('v3', done => { + verifyCloseConnection('v3', done) + }) - const server = boltStub.start( - './test/resources/boltstub/read_server_v2_read_dead.script', - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session() - session.run('MATCH (n) RETURN n.name').catch(error => { - expect(error.code).toEqual(neo4j.error.SERVICE_UNAVAILABLE) - - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() - }) - }) + it('v4', done => { + verifyCloseConnection('v4', done) }) }) - it('should close connection when RESET fails', done => { - if (!boltStub.supported) { - done() - return - } + describe('should send RESET on error', () => { + function verifyReset (version, done) { + if (!boltStub.supported) { + done() + return + } - const server = boltStub.start( - './test/resources/boltstub/reset_error.script', - 9001 - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/query_with_error.script`, + 9001 + ) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session() + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session() - session - .run('RETURN 42 AS answer') - .then(result => { - const records = result.records - expect(records.length).toEqual(1) - expect(records[0].get(0).toNumber()).toEqual(42) - session.close(() => { - expect(driver._pool._pools['127.0.0.1:9001'].length).toEqual(0) - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() + session + .run('RETURN 10 / 0') + .then(result => { + done.fail( + 'Should fail but received a result: ' + JSON.stringify(result) + ) + }) + .catch(error => { + expect(error.code).toEqual( + 'Neo.ClientError.Statement.ArithmeticError' + ) + expect(error.message).toEqual('/ by zero') + + session.close(() => { + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) }) - }) - .catch(error => done.fail(error)) + }) + } + + it('v2', done => { + verifyReset('v2', done) + }) + + it('v3', done => { + verifyReset('v3', done) + }) + + it('v4', done => { + verifyReset('v4', done) }) }) - it('should send RESET on error', done => { - if (!boltStub.supported) { - done() - return - } + describe('should include database connection id in logs', () => { + function verifyConnectionId (version, done) { + if (!boltStub.supported) { + done() + return + } - const server = boltStub.start( - './test/resources/boltstub/query_with_error.script', - 9001 - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/hello_run_exit.script`, + 9001 + ) - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session() + boltStub.run(() => { + const messages = [] + const logging = { + level: 'debug', + logger: (level, message) => messages.push(message) + } - session - .run('RETURN 10 / 0') - .then(result => { - done.fail( - 'Should fail but received a result: ' + JSON.stringify(result) - ) + const driver = boltStub.newDriver('bolt://127.0.0.1:9001', { + logging: logging }) - .catch(error => { - expect(error.code).toEqual( - 'Neo.ClientError.Statement.ArithmeticError' - ) - expect(error.message).toEqual('/ by zero') - - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() + const session = driver.session() + + session + .run('MATCH (n) RETURN n.name') + .then(result => { + const names = result.records.map(record => record.get(0)) + expect(names).toEqual(['Foo', 'Bar']) + session.close(() => { + driver.close() + server.exit(code => { + expect(code).toEqual(0) + + // logged messages should contain connection_id supplied by the database + const containsDbConnectionIdMessage = messages.find(message => + message.match(/Connection \[[0-9]+]\[bolt-123456789]/) + ) + if (!containsDbConnectionIdMessage) { + console.log(messages) + } + expect(containsDbConnectionIdMessage).toBeTruthy() + + done() + }) }) }) - }) + .catch(error => done.fail(error)) + }) + } + + it('v3', done => { + verifyConnectionId('v3', done) + }) + + it('v4', done => { + verifyConnectionId('v4', done) }) }) - it('should include database connection id in logs', done => { - if (!boltStub.supported) { - done() - return - } + describe('should close connection if it dies sitting idle in connection pool', () => { + function verifyConnectionCleanup (version, done) { + if (!boltStub.supported) { + done() + return + } - const server = boltStub.start( - './test/resources/boltstub/hello_run_exit.script', - 9001 - ) + const server = boltStub.start( + `./test/resources/boltstub/${version}/read.script`, + 9001 + ) - boltStub.run(() => { - const messages = [] - const logging = { - level: 'debug', - logger: (level, message) => messages.push(message) - } + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session({ defaultAccessMode: READ }) - const driver = boltStub.newDriver('bolt://127.0.0.1:9001', { - logging: logging - }) - const session = driver.session() - - session - .run('MATCH (n) RETURN n.name') - .then(result => { - const names = result.records.map(record => record.get(0)) - expect(names).toEqual(['Foo', 'Bar']) - session.close(() => { - driver.close() - server.exit(code => { - expect(code).toEqual(0) - - // logged messages should contain connection_id supplied by the database - const containsDbConnectionIdMessage = messages.find(message => - message.match(/Connection \[[0-9]+]\[bolt-123456789]/) + session + .run('MATCH (n) RETURN n.name') + .then(result => { + const records = result.records + expect(records.length).toEqual(3) + expect(records[0].get(0)).toBe('Bob') + expect(records[1].get(0)).toBe('Alice') + expect(records[2].get(0)).toBe('Tina') + + const connectionKey = Object.keys(driver._openConnections)[0] + expect(connectionKey).toBeTruthy() + + const connection = driver._openConnections[connectionKey] + session.close(() => { + // generate a fake fatal error + connection._handleFatalError( + newError('connection reset', SERVICE_UNAVAILABLE) ) - if (!containsDbConnectionIdMessage) { - console.log(messages) - } - expect(containsDbConnectionIdMessage).toBeTruthy() - done() + // expect that the connection to be removed from the pool + expect(driver._pool._pools['127.0.0.1:9001'].length).toEqual(0) + expect( + driver._pool._activeResourceCounts['127.0.0.1:9001'] + ).toBeFalsy() + // expect that the connection to be unregistered from the open connections registry + expect(driver._openConnections[connectionKey]).toBeFalsy() + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) }) - }) - .catch(error => done.fail(error)) - }) - }) - - it('should close connection if it dies sitting idle in connection pool', done => { - if (!boltStub.supported) { - done() - return + .catch(error => done.fail(error)) + }) } - const server = boltStub.start( - './test/resources/boltstub/read_server_v3_read.script', - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session({ defaultAccessMode: READ }) + it('v2', done => { + verifyConnectionCleanup('v2', done) + }) - session - .run('MATCH (n) RETURN n.name') - .then(result => { - const records = result.records - expect(records.length).toEqual(3) - expect(records[0].get(0)).toBe('Bob') - expect(records[1].get(0)).toBe('Alice') - expect(records[2].get(0)).toBe('Tina') - - const connectionKey = Object.keys(driver._openConnections)[0] - expect(connectionKey).toBeTruthy() - - const connection = driver._openConnections[connectionKey] - session.close(() => { - // generate a fake fatal error - connection._handleFatalError( - newError('connection reset', SERVICE_UNAVAILABLE) - ) + it('v3', done => { + verifyConnectionCleanup('v3', done) + }) - // expect that the connection to be removed from the pool - expect(driver._pool._pools['127.0.0.1:9001'].length).toEqual(0) - expect( - driver._pool._activeResourceCounts['127.0.0.1:9001'] - ).toBeFalsy() - // expect that the connection to be unregistered from the open connections registry - expect(driver._openConnections[connectionKey]).toBeFalsy() - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() - }) - }) - }) - .catch(error => done.fail(error)) + it('v4', done => { + verifyConnectionCleanup('v4', done) }) }) describe('should fail if commit fails due to broken connection', () => { - it('v1', done => { - verifyFailureOnConnectionFailureWhenExplicitTransactionIsCommitted( - 'v1', - done - ) - }) + function verifyFailureOnCommit (version, done) { + if (!boltStub.supported) { + done() + return + } - it('v3', done => { - verifyFailureOnConnectionFailureWhenExplicitTransactionIsCommitted( - 'v3', - done + const server = boltStub.start( + `./test/resources/boltstub/${version}/connection_error_on_commit.script`, + 9001 ) - }) - }) - function verifyFailureOnConnectionFailureWhenExplicitTransactionIsCommitted ( - version, - done - ) { - if (!boltStub.supported) { - done() - return - } + boltStub.run(() => { + const driver = boltStub.newDriver('bolt://127.0.0.1:9001') + const session = driver.session() + + const writeTx = session.beginTransaction() - const server = boltStub.start( - `./test/resources/boltstub/connection_error_on_commit_${version}.script`, - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver('bolt://127.0.0.1:9001') - const session = driver.session() - - const writeTx = session.beginTransaction() - - writeTx - .run("CREATE (n {name: 'Bob'})") - .then(() => - writeTx.commit().then( - result => fail('expected an error'), - error => { - expect(error.code).toBe(SERVICE_UNAVAILABLE) - } + writeTx + .run("CREATE (n {name: 'Bob'})") + .then(() => + writeTx.commit().then( + result => fail('expected an error'), + error => { + expect(error.code).toBe(SERVICE_UNAVAILABLE) + } + ) ) - ) - .then(() => - session.close(() => { - driver.close() - - server.exit(code => { - expect(code).toEqual(0) - done() + .then(() => + session.close(() => { + driver.close() + + server.exit(code => { + expect(code).toEqual(0) + done() + }) }) - }) - ) - .catch(error => done.fail(error)) + ) + .catch(error => done.fail(error)) + }) + } + + it('v2', done => { + verifyFailureOnCommit('v2', done) }) - } + + it('v3', done => { + verifyFailureOnCommit('v3', done) + }) + }) }) diff --git a/test/internal/node/routing.driver.boltkit.test.js b/test/internal/node/routing.driver.boltkit.test.js index 1549a3536..990069f93 100644 --- a/test/internal/node/routing.driver.boltkit.test.js +++ b/test/internal/node/routing.driver.boltkit.test.js @@ -45,7 +45,7 @@ describe('routing driver with stub server', () => { } // Given const server = boltStub.start( - './test/resources/boltstub/discover_servers_and_read.script', + './test/resources/boltstub/v3/discover_servers_and_read.script', 9001 ) @@ -83,7 +83,7 @@ describe('routing driver with stub server', () => { } const server = boltStub.start( - './test/resources/boltstub/discover_ipv6_servers_and_read.script', + './test/resources/boltstub/v3/discover_ipv6_servers_and_read.script', 9001 ) @@ -135,11 +135,11 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9042 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) @@ -166,48 +166,14 @@ describe('routing driver with stub server', () => { }) }) - it('should discover new servers', done => { + it('should discover servers using subscribe', done => { if (!boltStub.supported) { done() return } // Given const server = boltStub.start( - './test/resources/boltstub/discover_new_servers.script', - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') - // When - const session = driver.session() - session.run('MATCH (n) RETURN n.name').then(() => { - // Then - assertHasRouters(driver, [ - '127.0.0.1:9004', - '127.0.0.1:9002', - '127.0.0.1:9003' - ]) - assertHasReaders(driver, ['127.0.0.1:9005', '127.0.0.1:9003']) - assertHasWriters(driver, ['127.0.0.1:9001']) - - driver.close() - server.exit(code => { - expect(code).toEqual(0) - done() - }) - }) - }) - }) - - it('should discover new servers using subscribe', done => { - if (!boltStub.supported) { - done() - return - } - // Given - const server = boltStub.start( - './test/resources/boltstub/discover_new_servers.script', + './test/resources/boltstub/v3/discover_servers_and_read.script', 9001 ) @@ -219,11 +185,11 @@ describe('routing driver with stub server', () => { onCompleted: () => { // Then assertHasRouters(driver, [ - '127.0.0.1:9004', + '127.0.0.1:9001', '127.0.0.1:9002', '127.0.0.1:9003' ]) - assertHasReaders(driver, ['127.0.0.1:9005', '127.0.0.1:9003']) + assertHasReaders(driver, ['127.0.0.1:9002', '127.0.0.1:9003']) assertHasWriters(driver, ['127.0.0.1:9001']) driver.close() @@ -243,7 +209,7 @@ describe('routing driver with stub server', () => { } // Given const server = boltStub.start( - './test/resources/boltstub/empty_get_servers_response.script', + './test/resources/boltstub/v3/acquire_endpoints_no_records.script', 9001 ) @@ -277,11 +243,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) @@ -321,19 +287,19 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/short_ttl.script', + './test/resources/boltstub/v3/acquire_endpoints_short_ttl.script', 9999 ) const nextRouter = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9003 ) const readServer1 = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9004 ) const readServer2 = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9006 ) @@ -381,15 +347,15 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer1 = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) const readServer2 = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9006 ) @@ -434,11 +400,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v2_read_dead.script', + './test/resources/boltstub/v3/read_dead.script', 9005 ) @@ -467,11 +433,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writeServer = boltStub.start( - './test/resources/boltstub/write_server_v2_write.script', + './test/resources/boltstub/v3/write.script', 9007 ) @@ -500,15 +466,15 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer1 = boltStub.start( - './test/resources/boltstub/write_server_v2_write.script', + './test/resources/boltstub/v3/write.script', 9007 ) const readServer2 = boltStub.start( - './test/resources/boltstub/write_server_v2_write.script', + './test/resources/boltstub/v3/write.script', 9008 ) @@ -543,11 +509,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v2_read_dead.script', + './test/resources/boltstub/v3/write_dead.script', 9007 ) @@ -555,7 +521,7 @@ describe('routing driver with stub server', () => { const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') // When const session = driver.session({ defaultAccessMode: WRITE }) - session.run('MATCH (n) RETURN n.name').catch(err => { + session.run('CREATE ()').catch(err => { expect(err.code).toEqual(neo4j.error.SESSION_EXPIRED) driver.close() seedServer.exit(code1 => { @@ -576,11 +542,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) @@ -616,11 +582,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v2_read_dead.script', + './test/resources/boltstub/v3/read_dead.script', 9005 ) @@ -661,7 +627,7 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) @@ -699,22 +665,20 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/rediscover.script', + './test/resources/boltstub/v3/acquire_endpoints_rediscover.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) boltStub.run(() => { const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') // When - const session1 = driver.session({ defaultAccessMode: neo4j.session.READ }) + const session1 = driver.session({ defaultAccessMode: READ }) session1.run('MATCH (n) RETURN n.name').catch(() => { - const session2 = driver.session({ - defaultAccessMode: neo4j.session.READ - }) + const session2 = driver.session({ defaultAccessMode: READ }) session2.run('MATCH (n) RETURN n.name').then(() => { driver.close() seedServer.exit(code1 => { @@ -737,7 +701,7 @@ describe('routing driver with stub server', () => { // Given const server = boltStub.start( - './test/resources/boltstub/non_discovery.script', + './test/resources/boltstub/v3/acquire_endpoints_not_supported.script', 9001 ) @@ -766,11 +730,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/not_able_to_write.script', + './test/resources/boltstub/v3/write_not_a_leader.script', 9007 ) @@ -802,11 +766,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/not_able_to_write_in_transaction.script', + './test/resources/boltstub/v3/write_tx_not_a_leader.script', 9007 ) @@ -841,7 +805,7 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/no_writers.script', + './test/resources/boltstub/v3/acquire_endpoints_no_writers.script', 9001 ) @@ -867,19 +831,19 @@ describe('routing driver with stub server', () => { } const server1 = boltStub.start( - './test/resources/boltstub/routing_table_with_zero_ttl.script', + './test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script', 9999 ) const server2 = boltStub.start( - './test/resources/boltstub/dead_routing_server.script', + './test/resources/boltstub/v3/acquire_endpoints_dead.script', 9091 ) const server3 = boltStub.start( - './test/resources/boltstub/dead_routing_server.script', + './test/resources/boltstub/v3/acquire_endpoints_dead.script', 9092 ) const server4 = boltStub.start( - './test/resources/boltstub/dead_routing_server.script', + './test/resources/boltstub/v3/acquire_endpoints_dead.script', 9093 ) @@ -938,11 +902,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/single_write_server.script', + './test/resources/boltstub/v3/acquire_endpoints_three_servers_set_1.script', 9002 ) const writeServer = boltStub.start( - './test/resources/boltstub/two_write_responses_server.script', + './test/resources/boltstub/v3/write_twice.script', 9001 ) @@ -986,15 +950,15 @@ describe('routing driver with stub server', () => { // Given const routingServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writeServer = boltStub.start( - './test/resources/boltstub/write_server_with_version.script', + './test/resources/boltstub/v3/write_with_server_version.script', 9007 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_with_version.script', + './test/resources/boltstub/v3/read_with_server_version.script', 9005 ) @@ -1042,15 +1006,15 @@ describe('routing driver with stub server', () => { // Given const routingServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writeServer = boltStub.start( - './test/resources/boltstub/write_server_with_version.script', + './test/resources/boltstub/v3/write_with_server_version.script', 9007 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_with_version.script', + './test/resources/boltstub/v3/read_with_server_version.script', 9005 ) @@ -1102,7 +1066,7 @@ describe('routing driver with stub server', () => { } const server = boltStub.start( - './test/resources/boltstub/routing_table_with_zero_ttl.script', + './test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script', 9999 ) @@ -1152,7 +1116,7 @@ describe('routing driver with stub server', () => { // server is both router and writer const server = boltStub.start( - './test/resources/boltstub/discover_new_servers.script', + './test/resources/boltstub/v3/discover_servers_and_read.script', 9001 ) @@ -1195,56 +1159,56 @@ describe('routing driver with stub server', () => { it('should throw error when no records', done => { testForProtocolError( - './test/resources/boltstub/empty_get_servers_response.script', + './test/resources/boltstub/v3/acquire_endpoints_no_records.script', done ) }) it('should throw error when no TTL entry', done => { testForProtocolError( - './test/resources/boltstub/no_ttl_entry_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script', done ) }) it('should throw error when no servers entry', done => { testForProtocolError( - './test/resources/boltstub/no_servers_entry_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script', done ) }) it('should throw error when unparsable TTL entry', done => { testForProtocolError( - './test/resources/boltstub/unparsable_ttl_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script', done ) }) it('should throw error when multiple records', done => { testForProtocolError( - './test/resources/boltstub/unparsable_multiple_records_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_multiple_records.script', done ) }) it('should throw error on unparsable record', done => { testForProtocolError( - './test/resources/boltstub/unparsable_servers_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script', done ) }) it('should throw error when no routers', done => { testForProtocolError( - './test/resources/boltstub/no_routers_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_no_routers.script', done ) }) it('should throw error when no readers', done => { testForProtocolError( - './test/resources/boltstub/no_readers_get_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_no_readers.script', done ) }) @@ -1352,19 +1316,19 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writer = boltStub.start( - './test/resources/boltstub/write_tx_with_bookmarks.script', + './test/resources/boltstub/v3/write_tx_with_bookmarks.script', 9007 ) boltStub.run(() => { const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') - const session = driver.session() - const tx = session.beginTransaction('neo4j:bookmark:v1:tx42') + const session = driver.session({ bookmarks: ['neo4j:bookmark:v1:tx42'] }) + const tx = session.beginTransaction() tx.run("CREATE (n {name:'Bob'})").then(() => { tx.commit().then(() => { expect(session.lastBookmark()).toEqual('neo4j:bookmark:v1:tx4242') @@ -1407,11 +1371,11 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writer = boltStub.start( - './test/resources/boltstub/read_tx_with_bookmarks.script', + './test/resources/boltstub/v3/read_tx_with_bookmarks.script', 9005 ) @@ -1454,12 +1418,12 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints_with_one_of_each.script', + './test/resources/boltstub/v3/acquire_endpoints_three_servers_set_2.script', 9001 ) const writer = boltStub.start( - './test/resources/boltstub/write_read_tx_with_bookmarks.script', - 9007 + './test/resources/boltstub/v3/write_read_tx_with_bookmarks.script', + 9010 ) boltStub.run(() => { @@ -1506,15 +1470,15 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const brokenReader = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx_dead.script', + './test/resources/boltstub/v3/read_tx_dead.script', 9005 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx.script', + './test/resources/boltstub/v3/read_tx.script', 9006 ) @@ -1556,15 +1520,15 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const brokenWriter = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx_dead.script', + './test/resources/boltstub/v3/write_tx_dead.script', 9007 ) const writer = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx.script', + './test/resources/boltstub/v3/write_tx.script', 9008 ) @@ -1606,15 +1570,15 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const brokenReader1 = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx_dead.script', + './test/resources/boltstub/v3/read_tx_dead.script', 9005 ) const brokenReader2 = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx_dead.script', + './test/resources/boltstub/v3/read_tx_dead.script', 9006 ) @@ -1662,15 +1626,15 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const brokenWriter1 = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx_dead.script', + './test/resources/boltstub/v3/write_tx_dead.script', 9007 ) const brokenWriter2 = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx_dead.script', + './test/resources/boltstub/v3/write_tx_dead.script', 9008 ) @@ -1718,23 +1682,23 @@ describe('routing driver with stub server', () => { } const router1 = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9010 ) const brokenReader1 = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx_dead.script', + './test/resources/boltstub/v3/read_tx_dead.script', 9005 ) const brokenReader2 = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx_dead.script', + './test/resources/boltstub/v3/read_tx_dead.script', 9006 ) const router2 = boltStub.start( - './test/resources/boltstub/discover_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_three_servers_set_3.script', 9001 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx.script', + './test/resources/boltstub/v3/read_tx.script', 9002 ) @@ -1782,23 +1746,23 @@ describe('routing driver with stub server', () => { } const router1 = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9010 ) const brokenWriter1 = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx_dead.script', + './test/resources/boltstub/v3/write_tx_dead.script', 9007 ) const brokenWriter2 = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx_dead.script', + './test/resources/boltstub/v3/write_tx_dead.script', 9008 ) const router2 = boltStub.start( - './test/resources/boltstub/discover_servers.script', + './test/resources/boltstub/v3/acquire_endpoints_three_servers_set_3.script', 9002 ) const writer = boltStub.start( - './test/resources/boltstub/write_server_v2_write_tx.script', + './test/resources/boltstub/v3/write_tx.script', 9009 ) @@ -1847,11 +1811,11 @@ describe('routing driver with stub server', () => { // use scripts that exit eagerly when they are executed to simulate failed servers const router1 = boltStub.start( - './test/resources/boltstub/acquire_endpoints_and_exit.script', + './test/resources/boltstub/v3/acquire_endpoints_and_exit.script', 9010 ) const tmpReader = boltStub.start( - './test/resources/boltstub/read_server_and_exit.script', + './test/resources/boltstub/v3/read_and_exit.script', 9005 ) @@ -1872,7 +1836,7 @@ describe('routing driver with stub server', () => { // start new router on the same port with different script that contains itself as reader const router2 = boltStub.start( - './test/resources/boltstub/rediscover_using_initial_router.script', + './test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script', 9010 ) @@ -1910,13 +1874,13 @@ describe('routing driver with stub server', () => { } const router1 = boltStub.start( - './test/resources/boltstub/acquire_endpoints_and_exit.script', + './test/resources/boltstub/v3/acquire_endpoints_and_exit.script', 9011 ) // start new router on a different port to emulate host name resolution // this router uses different script that contains itself as reader const router2 = boltStub.start( - './test/resources/boltstub/rediscover_using_initial_router.script', + './test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script', 9009 ) @@ -1952,35 +1916,6 @@ describe('routing driver with stub server', () => { }) }) - it('should invoke procedure get routing table when server version permits', done => { - if (!boltStub.supported) { - done() - return - } - - const router = boltStub.start( - './test/resources/boltstub/get_routing_table.script', - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') - const session = driver.session() - session.run('MATCH (n) RETURN n.name AS name').then(result => { - const names = result.records.map(record => record.get('name')) - expect(names).toEqual(['Alice', 'Bob', 'Eve']) - - session.close(() => { - driver.close() - router.exit(code => { - expect(code).toEqual(0) - done() - }) - }) - }) - }) - }) - it('should send routing context to server', done => { if (!boltStub.supported) { done() @@ -1988,7 +1923,7 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/get_routing_table_with_context.script', + './test/resources/boltstub/v3/acquire_endpoints_with_context.script', 9001 ) @@ -2012,37 +1947,6 @@ describe('routing driver with stub server', () => { }) }) - it('should ignore routing context when server does not support it', done => { - if (!boltStub.supported) { - done() - return - } - - const router = boltStub.start( - './test/resources/boltstub/rediscover_and_read_with_init.script', - 9001 - ) - - boltStub.run(() => { - const driver = boltStub.newDriver( - 'neo4j://127.0.0.1:9001/?policy=my_policy' - ) - const session = driver.session() - session.run('MATCH (n) RETURN n.name').then(result => { - const names = result.records.map(record => record.get(0)) - expect(names).toEqual(['Bob', 'Tina']) - - session.close(() => { - driver.close() - router.exit(code => { - expect(code).toEqual(0) - done() - }) - }) - }) - }) - }) - it('should treat routing table with single router as valid', done => { if (!boltStub.supported) { done() @@ -2050,15 +1954,15 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/discover_one_router.script', + './test/resources/boltstub/v3/acquire_endpoints_one_router.script', 9010 ) const reader1 = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9003 ) const reader2 = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9004 ) @@ -2099,16 +2003,16 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/discover_no_writers.script', - 9010 + './test/resources/boltstub/v3/acquire_endpoints_no_writers.script', + 9001 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', - 9002 + './test/resources/boltstub/v3/read.script', + 9005 ) boltStub.run(() => { - const driver = boltStub.newDriver('neo4j://127.0.0.1:9010') + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') const session = driver.session({ defaultAccessMode: READ }) session.run('MATCH (n) RETURN n.name').then(result => { @@ -2140,20 +2044,20 @@ describe('routing driver with stub server', () => { } const router1 = boltStub.start( - './test/resources/boltstub/discover_no_writers.script', - 9010 + './test/resources/boltstub/v3/acquire_endpoints_no_writers.script', + 9001 ) const router2 = boltStub.start( - './test/resources/boltstub/discover_no_writers.script', - 9004 + './test/resources/boltstub/v3/acquire_endpoints_no_writers.script', + 9002 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx.script', - 9003 + './test/resources/boltstub/v3/read_tx.script', + 9005 ) boltStub.run(() => { - const driver = boltStub.newDriver('neo4j://127.0.0.1:9010') + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') const readSession = driver.session() @@ -2198,21 +2102,21 @@ describe('routing driver with stub server', () => { // first router does not have itself in the resulting routing table so connection // towards it will be closed after rediscovery const router1 = boltStub.start( - './test/resources/boltstub/discover_no_writers.script', - 9010 + './test/resources/boltstub/v3/acquire_endpoints_no_writers.script', + 9001 ) let router2 = null const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx.script', - 9003 + './test/resources/boltstub/v3/read_tx.script', + 9005 ) const writer = boltStub.start( - './test/resources/boltstub/write_server_v2_write.script', + './test/resources/boltstub/v3/write.script', 9007 ) boltStub.run(() => { - const driver = boltStub.newDriver('neo4j://127.0.0.1:9010') + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') const readSession = driver.session() @@ -2228,8 +2132,8 @@ describe('routing driver with stub server', () => { // start another router which knows about writes, use same address as the initial router router2 = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', - 9010 + './test/resources/boltstub/v3/acquire_endpoints.script', + 9002 ) boltStub.run(() => { const writeSession = driver.session({ defaultAccessMode: WRITE }) @@ -2267,24 +2171,24 @@ describe('routing driver with stub server', () => { } const seedRouter = boltStub.start( - './test/resources/boltstub/no_writers.script', - 9010 + './test/resources/boltstub/v3/acquire_endpoints_no_writers.script', + 9001 ) const resolvedSeedRouter = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9020 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) const writer = boltStub.start( - './test/resources/boltstub/write_server_v2_write.script', + './test/resources/boltstub/v3/write.script', 9007 ) boltStub.run(() => { - const driver = boltStub.newDriver('neo4j://127.0.0.1:9010') + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') const readSession = driver.session({ defaultAccessMode: READ }) readSession.run('MATCH (n) RETURN n.name').then(result => { @@ -2295,7 +2199,7 @@ describe('routing driver with stub server', () => { 'Tina' ]) - setupFakeHostNameResolution(driver, '127.0.0.1:9010', [ + setupFakeHostNameResolution(driver, '127.0.0.1:9001', [ '127.0.0.1:9020' ]) @@ -2333,7 +2237,7 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/failed_auth.script', + './test/resources/boltstub/v3/no_auth.script', 9010 ) @@ -2362,11 +2266,11 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9010 ) const writer = boltStub.start( - './test/resources/boltstub/multiple_bookmarks.script', + './test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script', 9007 ) @@ -2404,11 +2308,21 @@ describe('routing driver with stub server', () => { }) it('should forget writer on database unavailable error', done => { - testAddressPurgeOnDatabaseError(`CREATE (n {name:'Bob'})`, WRITE, done) + testAddressPurgeOnDatabaseError( + './test/resources/boltstub/v3/write_database_unavailable.script', + `CREATE (n {name:'Bob'})`, + WRITE, + done + ) }) it('should forget reader on database unavailable error', done => { - testAddressPurgeOnDatabaseError(`RETURN 1`, READ, done) + testAddressPurgeOnDatabaseError( + './test/resources/boltstub/v3/read_database_unavailable.script', + `RETURN 1`, + READ, + done + ) }) it('should use resolver function that returns array during first discovery', done => { @@ -2465,15 +2379,15 @@ describe('routing driver with stub server', () => { } const router1 = boltStub.start( - './test/resources/boltstub/get_routing_table.script', + './test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script', 9001 ) const router2 = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9042 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read_tx.script', + './test/resources/boltstub/v3/read_tx.script', 9005 ) @@ -2539,17 +2453,9 @@ describe('routing driver with stub server', () => { }) }) - it('should rediscover using older getServers procedure when server is old', done => { - testDiscoveryAndReadQueryInAutoCommitTx( - './test/resources/boltstub/acquire_endpoints_old_routing_procedure.script', - {}, - done - ) - }) - it('should connect to cluster when disableLosslessIntegers is on', done => { testDiscoveryAndReadQueryInAutoCommitTx( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', { disableLosslessIntegers: true }, done ) @@ -2562,11 +2468,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v3_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) @@ -2600,11 +2506,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const readServer = boltStub.start( - './test/resources/boltstub/read_server_v3_read_tx.script', + './test/resources/boltstub/v3/read_tx.script', 9005 ) @@ -2640,11 +2546,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writeServer = boltStub.start( - './test/resources/boltstub/write_server_v3_write.script', + './test/resources/boltstub/v3/write.script', 9007 ) @@ -2673,11 +2579,11 @@ describe('routing driver with stub server', () => { } // Given const seedServer = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writeServer = boltStub.start( - './test/resources/boltstub/write_server_v3_write_tx.script', + './test/resources/boltstub/v3/write_tx.script', 9007 ) @@ -2711,22 +2617,22 @@ describe('routing driver with stub server', () => { // the returned routing table includes a non-reachable read-server and points to only one router // which will return an invalid routing table const router1 = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3_point_to_empty_router_and_exit.script', + './test/resources/boltstub/v3/acquire_endpoints_three_servers_set_2.script', 9001 ) // returns an empty routing table const router2 = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3_empty.script', + './test/resources/boltstub/v3/acquire_endpoints_no_servers.script', 9004 ) // returns a normal routing table const router3 = boltStub.start( - './test/resources/boltstub/acquire_endpoints_v3_three_servers_and_exit.script', + './test/resources/boltstub/v3/acquire_endpoints_three_servers_set_1.script', 9003 ) // ordinary read server const reader = boltStub.start( - './test/resources/boltstub/read_server_v3_read_tx.script', + './test/resources/boltstub/v3/read_tx.script', 9002 ) @@ -2759,26 +2665,20 @@ describe('routing driver with stub server', () => { }) }) - function testAddressPurgeOnDatabaseError (query, accessMode, done) { + function testAddressPurgeOnDatabaseError (script, query, accessMode, done) { if (!boltStub.supported) { done() return } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9010 ) const serverPort = accessMode === READ ? 9005 : 9007 const serverAddress = '127.0.0.1:' + serverPort - const serverTemplateScript = - './test/resources/boltstub/address_unavailable_template.script.mst' - const server = boltStub.startWithTemplate( - serverTemplateScript, - { query: query }, - serverPort - ) + const server = boltStub.start(script, serverPort) boltStub.run(() => { const driver = boltStub.newDriver('neo4j://127.0.0.1:9010') @@ -2834,11 +2734,11 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9001 ) const writer = boltStub.start( - './test/resources/boltstub/write_tx_with_bookmarks.script', + './test/resources/boltstub/v3/write_tx_with_bookmarks.script', 9007 ) @@ -2881,7 +2781,7 @@ describe('routing driver with stub server', () => { const router = boltStub.start(routerScript, 9001) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) @@ -2950,7 +2850,7 @@ describe('routing driver with stub server', () => { writers: joinStrings(writers) } const server = boltStub.startWithTemplate( - './test/resources/boltstub/one_of_each_template.script.mst', + './test/resources/boltstub/v3/acquire_endpoints_template.script', params, port ) @@ -3101,11 +3001,11 @@ describe('routing driver with stub server', () => { } const router = boltStub.start( - './test/resources/boltstub/acquire_endpoints.script', + './test/resources/boltstub/v3/acquire_endpoints.script', 9010 ) const reader = boltStub.start( - './test/resources/boltstub/read_server_v2_read.script', + './test/resources/boltstub/v3/read.script', 9005 ) diff --git a/test/resources/boltstub/acquire_endpoints.script b/test/resources/boltstub/acquire_endpoints.script deleted file mode 100644 index 6589ecd52..000000000 --- a/test/resources/boltstub/acquire_endpoints.script +++ /dev/null @@ -1,9 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007","127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] - SUCCESS {} diff --git a/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script b/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script deleted file mode 100644 index 143326ce9..000000000 --- a/test/resources/boltstub/acquire_endpoints_old_routing_procedure.script +++ /dev/null @@ -1,10 +0,0 @@ -!: BOLT 1 -!: AUTO RESET - -C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} -S: SUCCESS {"server": "Neo4j/3.1.0"} -C: RUN "CALL dbms.cluster.routing.getServers" {} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007","127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] - SUCCESS {} diff --git a/test/resources/boltstub/acquire_endpoints_with_one_of_each.script b/test/resources/boltstub/acquire_endpoints_with_one_of_each.script deleted file mode 100644 index fbc7bcb9d..000000000 --- a/test/resources/boltstub/acquire_endpoints_with_one_of_each.script +++ /dev/null @@ -1,9 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] - SUCCESS {} diff --git a/test/resources/boltstub/discover_new_servers.script b/test/resources/boltstub/discover_new_servers.script deleted file mode 100644 index d14c497cf..000000000 --- a/test/resources/boltstub/discover_new_servers.script +++ /dev/null @@ -1,13 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9004","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] - SUCCESS {} -C: RUN "MATCH (n) RETURN n.name" {} - PULL_ALL -S: SUCCESS {"fields": ["n.name"]} - SUCCESS {} diff --git a/test/resources/boltstub/discover_no_writers.script b/test/resources/boltstub/discover_no_writers.script deleted file mode 100644 index 1077d40d3..000000000 --- a/test/resources/boltstub/discover_no_writers.script +++ /dev/null @@ -1,9 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": [],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9004","127.0.0.1:9005"], "role": "ROUTE"}]] - SUCCESS {} diff --git a/test/resources/boltstub/multiple_bookmarks.script b/test/resources/boltstub/multiple_bookmarks.script deleted file mode 100644 index 88580188b..000000000 --- a/test/resources/boltstub/multiple_bookmarks.script +++ /dev/null @@ -1,16 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx94", "bookmarks": ["neo4j:bookmark:v1:tx5", "neo4j:bookmark:v1:tx29", "neo4j:bookmark:v1:tx94", "neo4j:bookmark:v1:tx56", "neo4j:bookmark:v1:tx16", "neo4j:bookmark:v1:tx68"]} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -C: RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {"bookmark": "neo4j:bookmark:v1:tx95"} -C: RUN "COMMIT" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} diff --git a/test/resources/boltstub/multiple_records_get_servers.script b/test/resources/boltstub/multiple_records_get_servers.script deleted file mode 100644 index 3fed74124..000000000 --- a/test/resources/boltstub/multiple_records_get_servers.script +++ /dev/null @@ -1,9 +0,0 @@ -!: AUTO INIT -!: AUTO RESET - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9005"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001"], "role": "ROUTE"}]] - SUCCESS {} diff --git a/test/resources/boltstub/not_able_to_write_in_transaction.script b/test/resources/boltstub/not_able_to_write_in_transaction.script deleted file mode 100644 index 55da234ee..000000000 --- a/test/resources/boltstub/not_able_to_write_in_transaction.script +++ /dev/null @@ -1,14 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {} - PULL_ALL - RUN "CREATE ()" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -S: FAILURE {"code": "Neo.ClientError.Cluster.NotALeader", "message": "blabla"} -S: IGNORED -C: RUN "COMMIT" {} -S: IGNORED diff --git a/test/resources/boltstub/read_server_v2_read_tx.script b/test/resources/boltstub/read_server_v2_read_tx.script deleted file mode 100644 index c0903de9c..000000000 --- a/test/resources/boltstub/read_server_v2_read_tx.script +++ /dev/null @@ -1,19 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {} - PULL_ALL - RUN "MATCH (n) RETURN n.name" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} - SUCCESS {"fields": ["n.name"]} - RECORD ["Bob"] - RECORD ["Alice"] - RECORD ["Tina"] - SUCCESS {} -C: RUN "COMMIT" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {"bookmark": "ABookmark"} diff --git a/test/resources/boltstub/read_server_v2_read_tx_dead.script b/test/resources/boltstub/read_server_v2_read_tx_dead.script deleted file mode 100644 index 44367b2fb..000000000 --- a/test/resources/boltstub/read_server_v2_read_tx_dead.script +++ /dev/null @@ -1,11 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {} - PULL_ALL - RUN "MATCH (n) RETURN n.name" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} - diff --git a/test/resources/boltstub/read_server_with_version.script b/test/resources/boltstub/read_server_with_version.script deleted file mode 100644 index 237de2d0e..000000000 --- a/test/resources/boltstub/read_server_with_version.script +++ /dev/null @@ -1,12 +0,0 @@ -!: BOLT 2 -!: AUTO RESET - -C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} -S: SUCCESS {"server": "Neo4j/8.8.8"} -C: RUN "MATCH (n) RETURN n.name" {} - PULL_ALL -S: SUCCESS {"fields": ["n.name"]} - RECORD ["Bob"] - RECORD ["Alice"] - RECORD ["Tina"] - SUCCESS {} diff --git a/test/resources/boltstub/rediscover_and_read_with_init.script b/test/resources/boltstub/rediscover_and_read_with_init.script deleted file mode 100644 index 9a39541e2..000000000 --- a/test/resources/boltstub/rediscover_and_read_with_init.script +++ /dev/null @@ -1,16 +0,0 @@ -!: BOLT 1 -!: AUTO INIT -!: AUTO RESET - -S: SUCCESS {"server": "Neo4j/3.1.0"} -C: RUN "CALL dbms.cluster.routing.getServers" {} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] - SUCCESS {} -C: RUN "MATCH (n) RETURN n.name" {} - PULL_ALL -S: SUCCESS {"fields": ["n.name"]} - RECORD ["Bob"] - RECORD ["Tina"] - SUCCESS {} diff --git a/test/resources/boltstub/single_write_server.script b/test/resources/boltstub/single_write_server.script deleted file mode 100644 index cc2f0b676..000000000 --- a/test/resources/boltstub/single_write_server.script +++ /dev/null @@ -1,9 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9004","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] - SUCCESS {} diff --git a/test/resources/boltstub/two_write_responses_server.script b/test/resources/boltstub/two_write_responses_server.script deleted file mode 100644 index c58848d7d..000000000 --- a/test/resources/boltstub/two_write_responses_server.script +++ /dev/null @@ -1,12 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -C: RUN "CREATE ()" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} diff --git a/test/resources/boltstub/connection_error_on_commit_v1.script b/test/resources/boltstub/v2/connection_error_on_commit.script similarity index 95% rename from test/resources/boltstub/connection_error_on_commit_v1.script rename to test/resources/boltstub/v2/connection_error_on_commit.script index 800efcdac..7c574c5ab 100644 --- a/test/resources/boltstub/connection_error_on_commit_v1.script +++ b/test/resources/boltstub/v2/connection_error_on_commit.script @@ -1,4 +1,4 @@ -!: BOLT 1 +!: BOLT 2 !: AUTO INIT !: AUTO RESET diff --git a/test/resources/boltstub/query_with_error.script b/test/resources/boltstub/v2/query_with_error.script similarity index 100% rename from test/resources/boltstub/query_with_error.script rename to test/resources/boltstub/v2/query_with_error.script diff --git a/test/resources/boltstub/read_server_v2_read.script b/test/resources/boltstub/v2/read.script similarity index 100% rename from test/resources/boltstub/read_server_v2_read.script rename to test/resources/boltstub/v2/read.script diff --git a/test/resources/boltstub/read_server_v2_read_dead.script b/test/resources/boltstub/v2/read_dead.script similarity index 100% rename from test/resources/boltstub/read_server_v2_read_dead.script rename to test/resources/boltstub/v2/read_dead.script diff --git a/test/resources/boltstub/read_tx_with_bookmarks.script b/test/resources/boltstub/v2/read_tx_with_bookmarks.script similarity index 97% rename from test/resources/boltstub/read_tx_with_bookmarks.script rename to test/resources/boltstub/v2/read_tx_with_bookmarks.script index 1b450a304..92d479451 100644 --- a/test/resources/boltstub/read_tx_with_bookmarks.script +++ b/test/resources/boltstub/v2/read_tx_with_bookmarks.script @@ -1,3 +1,4 @@ +!: BOLT 2 !: AUTO INIT !: AUTO RESET @@ -10,8 +11,8 @@ C: RUN "MATCH (n) RETURN n.name AS name" {} S: SUCCESS {"fields": ["name"]} RECORD ["Bob"] RECORD ["Alice"] - SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} + SUCCESS {} C: RUN "COMMIT" {} PULL_ALL S: SUCCESS {} - SUCCESS {} + SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} diff --git a/test/resources/boltstub/reset_error.script b/test/resources/boltstub/v2/reset_error.script similarity index 100% rename from test/resources/boltstub/reset_error.script rename to test/resources/boltstub/v2/reset_error.script diff --git a/test/resources/boltstub/return_x.script b/test/resources/boltstub/v2/return_x.script similarity index 78% rename from test/resources/boltstub/return_x.script rename to test/resources/boltstub/v2/return_x.script index b628d358f..e846cdada 100644 --- a/test/resources/boltstub/return_x.script +++ b/test/resources/boltstub/v2/return_x.script @@ -2,7 +2,7 @@ !: AUTO INIT !: AUTO RESET -C: RUN "RETURN {x}" {"x": 1} +C: RUN "RETURN $x" {"x": 1} PULL_ALL S: SUCCESS {"fields": ["x"]} RECORD [1] diff --git a/test/resources/boltstub/write_read_tx_with_bookmarks.script b/test/resources/boltstub/v2/write_read_tx_with_bookmarks.script similarity index 100% rename from test/resources/boltstub/write_read_tx_with_bookmarks.script rename to test/resources/boltstub/v2/write_read_tx_with_bookmarks.script diff --git a/test/resources/boltstub/write_tx_with_bookmarks.script b/test/resources/boltstub/v2/write_tx_with_bookmarks.script similarity index 100% rename from test/resources/boltstub/write_tx_with_bookmarks.script rename to test/resources/boltstub/v2/write_tx_with_bookmarks.script diff --git a/test/resources/boltstub/acquire_endpoints_v3.script b/test/resources/boltstub/v3/acquire_endpoints.script similarity index 100% rename from test/resources/boltstub/acquire_endpoints_v3.script rename to test/resources/boltstub/v3/acquire_endpoints.script diff --git a/test/resources/boltstub/acquire_endpoints_and_exit.script b/test/resources/boltstub/v3/acquire_endpoints_and_exit.script similarity index 88% rename from test/resources/boltstub/acquire_endpoints_and_exit.script rename to test/resources/boltstub/v3/acquire_endpoints_and_exit.script index 6349c8367..399938f90 100644 --- a/test/resources/boltstub/acquire_endpoints_and_exit.script +++ b/test/resources/boltstub/v3/acquire_endpoints_and_exit.script @@ -1,10 +1,10 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007","127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] SUCCESS {} -S: + diff --git a/test/resources/boltstub/dead_routing_server.script b/test/resources/boltstub/v3/acquire_endpoints_dead.script similarity index 100% rename from test/resources/boltstub/dead_routing_server.script rename to test/resources/boltstub/v3/acquire_endpoints_dead.script diff --git a/test/resources/boltstub/unparsable_multiple_records_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_multiple_records.script similarity index 93% rename from test/resources/boltstub/unparsable_multiple_records_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_multiple_records.script index fe0d07df9..66647d257 100644 --- a/test/resources/boltstub/unparsable_multiple_records_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_multiple_records.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/no_readers_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_no_readers.script similarity index 88% rename from test/resources/boltstub/no_readers_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_no_readers.script index 9a1084784..db6bac919 100644 --- a/test/resources/boltstub/no_readers_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_readers.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/empty_get_servers_response.script b/test/resources/boltstub/v3/acquire_endpoints_no_records.script similarity index 78% rename from test/resources/boltstub/empty_get_servers_response.script rename to test/resources/boltstub/v3/acquire_endpoints_no_records.script index 173c151fa..9c2a1bc5d 100644 --- a/test/resources/boltstub/empty_get_servers_response.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_records.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} SUCCESS {} diff --git a/test/resources/boltstub/no_routers_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_no_routers.script similarity index 87% rename from test/resources/boltstub/no_routers_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_no_routers.script index 7b4a2bd21..43cd8ff08 100644 --- a/test/resources/boltstub/no_routers_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_routers.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"},{"addresses": ["127.0.0.1:9001"], "role": "READ"}]] diff --git a/test/resources/boltstub/acquire_endpoints_v3_empty.script b/test/resources/boltstub/v3/acquire_endpoints_no_servers.script similarity index 100% rename from test/resources/boltstub/acquire_endpoints_v3_empty.script rename to test/resources/boltstub/v3/acquire_endpoints_no_servers.script diff --git a/test/resources/boltstub/no_servers_entry_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script similarity index 79% rename from test/resources/boltstub/no_servers_entry_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script index 9cfc845ca..4da56833a 100644 --- a/test/resources/boltstub/no_servers_entry_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script @@ -1,9 +1,9 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL -S: SUCCESS {"fields": ["ttl", "notServers"]} +S: SUCCESS {"fields": ["notTtl", "noServers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] SUCCESS {} diff --git a/test/resources/boltstub/no_ttl_entry_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script similarity index 90% rename from test/resources/boltstub/no_ttl_entry_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script index 162f38040..7504b473e 100644 --- a/test/resources/boltstub/no_ttl_entry_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["notTtl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/no_writers.script b/test/resources/boltstub/v3/acquire_endpoints_no_writers.script similarity index 90% rename from test/resources/boltstub/no_writers.script rename to test/resources/boltstub/v3/acquire_endpoints_no_writers.script index 7bba701e0..ad36238bc 100644 --- a/test/resources/boltstub/no_writers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_writers.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": [],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/non_discovery.script b/test/resources/boltstub/v3/acquire_endpoints_not_supported.script similarity index 82% rename from test/resources/boltstub/non_discovery.script rename to test/resources/boltstub/v3/acquire_endpoints_not_supported.script index 630d8f75a..fa4f867a6 100644 --- a/test/resources/boltstub/non_discovery.script +++ b/test/resources/boltstub/v3/acquire_endpoints_not_supported.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} C: PULL_ALL S: FAILURE {"code": "Neo.ClientError.Procedure.ProcedureNotFound", "message": "blabla"} S: IGNORED diff --git a/test/resources/boltstub/discover_one_router.script b/test/resources/boltstub/v3/acquire_endpoints_one_router.script similarity index 90% rename from test/resources/boltstub/discover_one_router.script rename to test/resources/boltstub/v3/acquire_endpoints_one_router.script index 99fd32e5c..ff3a8bd7d 100644 --- a/test/resources/boltstub/discover_one_router.script +++ b/test/resources/boltstub/v3/acquire_endpoints_one_router.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9003","127.0.0.1:9004"], "role": "READ"},{"addresses": ["127.0.0.1:9005"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/rediscover.script b/test/resources/boltstub/v3/acquire_endpoints_rediscover.script similarity index 91% rename from test/resources/boltstub/rediscover.script rename to test/resources/boltstub/v3/acquire_endpoints_rediscover.script index 571e56bfc..eae2a6ea4 100644 --- a/test/resources/boltstub/rediscover.script +++ b/test/resources/boltstub/v3/acquire_endpoints_rediscover.script @@ -1,13 +1,13 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9004"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005"], "role": "READ"},{"addresses": ["127.0.0.1:9002","127.0.0.1:9003","127.0.0.1:9004"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/rediscover_using_initial_router.script b/test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script similarity index 68% rename from test/resources/boltstub/rediscover_using_initial_router.script rename to test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script index 5535536dc..29096d914 100644 --- a/test/resources/boltstub/rediscover_using_initial_router.script +++ b/test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script @@ -1,23 +1,19 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9001","127.0.0.1:9009","127.0.0.1:9010"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9011"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "BEGIN" {} +C: BEGIN {"mode": "r"} + RUN "MATCH (n) RETURN n.name AS name" {} {"mode": "r"} PULL_ALL - RUN "MATCH (n) RETURN n.name AS name" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} +S: SUCCESS {} SUCCESS {"fields": ["name"]} RECORD ["Bob"] RECORD ["Alice"] SUCCESS {} -C: RUN "COMMIT" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} +C: COMMIT +S: SUCCESS {} diff --git a/test/resources/boltstub/short_ttl.script b/test/resources/boltstub/v3/acquire_endpoints_short_ttl.script similarity index 100% rename from test/resources/boltstub/short_ttl.script rename to test/resources/boltstub/v3/acquire_endpoints_short_ttl.script diff --git a/test/resources/boltstub/one_of_each_template.script.mst b/test/resources/boltstub/v3/acquire_endpoints_template.script similarity index 82% rename from test/resources/boltstub/one_of_each_template.script.mst rename to test/resources/boltstub/v3/acquire_endpoints_template.script index 519b11ead..40d47398a 100644 --- a/test/resources/boltstub/one_of_each_template.script.mst +++ b/test/resources/boltstub/v3/acquire_endpoints_template.script @@ -1,13 +1,13 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": {{{writers}}},"role": "WRITE"}, {"addresses": {{{readers}}}, "role": "READ"},{"addresses": {{{routers}}}, "role": "ROUTE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n.name" {} +C: RUN "MATCH (n) RETURN n.name" {} {} PULL_ALL S: SUCCESS {"fields": ["n.name"]} SUCCESS {} diff --git a/test/resources/boltstub/acquire_endpoints_v3_three_servers_and_exit.script b/test/resources/boltstub/v3/acquire_endpoints_three_servers_set_1.script similarity index 100% rename from test/resources/boltstub/acquire_endpoints_v3_three_servers_and_exit.script rename to test/resources/boltstub/v3/acquire_endpoints_three_servers_set_1.script diff --git a/test/resources/boltstub/acquire_endpoints_v3_point_to_empty_router_and_exit.script b/test/resources/boltstub/v3/acquire_endpoints_three_servers_set_2.script similarity index 100% rename from test/resources/boltstub/acquire_endpoints_v3_point_to_empty_router_and_exit.script rename to test/resources/boltstub/v3/acquire_endpoints_three_servers_set_2.script diff --git a/test/resources/boltstub/discover_servers.script b/test/resources/boltstub/v3/acquire_endpoints_three_servers_set_3.script similarity index 84% rename from test/resources/boltstub/discover_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_three_servers_set_3.script index c482cf66d..c48e69aa0 100644 --- a/test/resources/boltstub/discover_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_three_servers_set_3.script @@ -1,9 +1,12 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9009"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] SUCCESS {} +C: RESET +S: SUCCESS {} + diff --git a/test/resources/boltstub/get_routing_table.script b/test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script similarity index 100% rename from test/resources/boltstub/get_routing_table.script rename to test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script diff --git a/test/resources/boltstub/unparsable_servers_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script similarity index 90% rename from test/resources/boltstub/unparsable_servers_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script index 3e3c57bc0..d71c3d8d6 100644 --- a/test/resources/boltstub/unparsable_servers_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"notAddresses": ["127.0.0.1:9001"],"memberRole": "WRITER"}, {"notAddresses": ["127.0.0.1:9002","127.0.0.1:9003"], "memberRole": "READER"},{"notAddresses": ["127.0.0.1:9001","127.0.0.1:9002"], "memberRole": "ROUTER"}]] diff --git a/test/resources/boltstub/unparsable_ttl_get_servers.script b/test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script similarity index 90% rename from test/resources/boltstub/unparsable_ttl_get_servers.script rename to test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script index 4f135ac51..272e48b1e 100644 --- a/test/resources/boltstub/unparsable_ttl_get_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [{ttl: 9223372036854775807}, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/get_routing_table_with_context.script b/test/resources/boltstub/v3/acquire_endpoints_with_context.script similarity index 75% rename from test/resources/boltstub/get_routing_table_with_context.script rename to test/resources/boltstub/v3/acquire_endpoints_with_context.script index 9c663f101..025a80497 100644 --- a/test/resources/boltstub/get_routing_table_with_context.script +++ b/test/resources/boltstub/v3/acquire_endpoints_with_context.script @@ -1,14 +1,13 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -S: SUCCESS {"server": "Neo4j/3.2.3"} -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {"policy": "my_policy", "region": "china"}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {"policy": "my_policy", "region": "china"}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"], "role": "READ"},{"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n.name AS name" {} +C: RUN "MATCH (n) RETURN n.name AS name" {} {} PULL_ALL S: SUCCESS {"fields": ["name"]} RECORD ["Alice"] diff --git a/test/resources/boltstub/routing_table_with_zero_ttl.script b/test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script similarity index 86% rename from test/resources/boltstub/routing_table_with_zero_ttl.script rename to test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script index 99ae03aaa..56ce16dd9 100644 --- a/test/resources/boltstub/routing_table_with_zero_ttl.script +++ b/test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script @@ -1,22 +1,22 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [0, [{"addresses": ["127.0.0.1:9091","127.0.0.1:9092","127.0.0.1:9093","127.0.0.1:9999"],"role": "ROUTE"}, {"addresses": ["127.0.0.1:9999"], "role": "READ"},{"addresses": ["127.0.0.1:9999"], "role": "WRITE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n" {} +C: RUN "MATCH (n) RETURN n" {} {} PULL_ALL S: SUCCESS {"fields": ["n"]} SUCCESS {} -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [0, [{"addresses": ["127.0.0.1:9999"],"role": "ROUTE"}, {"addresses": ["127.0.0.1:9999"], "role": "READ"},{"addresses": ["127.0.0.1:9999"], "role": "WRITE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n" {} +C: RUN "MATCH (n) RETURN n" {} {} PULL_ALL S: SUCCESS {"fields": ["n"]} SUCCESS {} diff --git a/test/resources/boltstub/connection_error_on_commit_v3.script b/test/resources/boltstub/v3/connection_error_on_commit.script similarity index 100% rename from test/resources/boltstub/connection_error_on_commit_v3.script rename to test/resources/boltstub/v3/connection_error_on_commit.script diff --git a/test/resources/boltstub/discover_ipv6_servers_and_read.script b/test/resources/boltstub/v3/discover_ipv6_servers_and_read.script similarity index 84% rename from test/resources/boltstub/discover_ipv6_servers_and_read.script rename to test/resources/boltstub/v3/discover_ipv6_servers_and_read.script index 449ddbea0..0c8bfd618 100644 --- a/test/resources/boltstub/discover_ipv6_servers_and_read.script +++ b/test/resources/boltstub/v3/discover_ipv6_servers_and_read.script @@ -1,13 +1,13 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001", "[::1]:9001"],"role": "READ"}, {"addresses": ["[2001:db8:a0b:12f0::1]:9002","[3731:54:65fe:2::a7]:9003"], "role": "WRITE"},{"addresses": ["[ff02::1]:9001","[684D:1111:222:3333:4444:5555:6:77]:9002","[::1]:9003"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n.name" {} +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} PULL_ALL S: SUCCESS {"fields": ["n.name"]} SUCCESS {} diff --git a/test/resources/boltstub/discover_servers_and_read.script b/test/resources/boltstub/v3/discover_servers_and_read.script similarity index 84% rename from test/resources/boltstub/discover_servers_and_read.script rename to test/resources/boltstub/v3/discover_servers_and_read.script index 89acf19ac..ccfbe94e3 100644 --- a/test/resources/boltstub/discover_servers_and_read.script +++ b/test/resources/boltstub/v3/discover_servers_and_read.script @@ -1,13 +1,13 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n.name" {} +C: RUN "MATCH (n) RETURN n.name" {} {} PULL_ALL S: SUCCESS {"fields": ["n.name"]} SUCCESS {} diff --git a/test/resources/boltstub/hello_run_exit.script b/test/resources/boltstub/v3/hello_run_exit.script similarity index 100% rename from test/resources/boltstub/hello_run_exit.script rename to test/resources/boltstub/v3/hello_run_exit.script diff --git a/test/resources/boltstub/failed_auth.script b/test/resources/boltstub/v3/no_auth.script similarity index 100% rename from test/resources/boltstub/failed_auth.script rename to test/resources/boltstub/v3/no_auth.script diff --git a/test/resources/boltstub/v3/query_with_error.script b/test/resources/boltstub/v3/query_with_error.script new file mode 100644 index 000000000..bffa97df3 --- /dev/null +++ b/test/resources/boltstub/v3/query_with_error.script @@ -0,0 +1,11 @@ +!: BOLT 3 +!: AUTO HELLO + +C: RUN "RETURN 10 / 0" {} {} +C: PULL_ALL +S: FAILURE {"code": "Neo.ClientError.Statement.ArithmeticError", "message": "/ by zero"} +S: IGNORED +C: RESET +S: SUCCESS {} +C: RESET +S: SUCCESS {} diff --git a/test/resources/boltstub/read_server_v3_read.script b/test/resources/boltstub/v3/read.script similarity index 100% rename from test/resources/boltstub/read_server_v3_read.script rename to test/resources/boltstub/v3/read.script diff --git a/test/resources/boltstub/read_server_and_exit.script b/test/resources/boltstub/v3/read_and_exit.script similarity index 61% rename from test/resources/boltstub/read_server_and_exit.script rename to test/resources/boltstub/v3/read_and_exit.script index 9144c40da..58bd9f9a5 100644 --- a/test/resources/boltstub/read_server_and_exit.script +++ b/test/resources/boltstub/v3/read_and_exit.script @@ -1,12 +1,12 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "MATCH (n) RETURN n.name" {} +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} PULL_ALL S: SUCCESS {"fields": ["n.name"]} RECORD ["Bob"] RECORD ["Alice"] RECORD ["Tina"] SUCCESS {} -S: + diff --git a/test/resources/boltstub/address_unavailable_template.script.mst b/test/resources/boltstub/v3/read_database_unavailable.script similarity index 72% rename from test/resources/boltstub/address_unavailable_template.script.mst rename to test/resources/boltstub/v3/read_database_unavailable.script index 799245ca6..a32b5bc6b 100644 --- a/test/resources/boltstub/address_unavailable_template.script.mst +++ b/test/resources/boltstub/v3/read_database_unavailable.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "{{{query}}}" {} +C: RUN "RETURN 1" {} {"mode": "r"} C: PULL_ALL S: FAILURE {"code": "Neo.TransientError.General.DatabaseUnavailable", "message": "Database is busy doing store copy"} S: IGNORED diff --git a/test/resources/boltstub/v3/read_dead.script b/test/resources/boltstub/v3/read_dead.script new file mode 100644 index 000000000..3b03188b2 --- /dev/null +++ b/test/resources/boltstub/v3/read_dead.script @@ -0,0 +1,7 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} +C: PULL_ALL +S: diff --git a/test/resources/boltstub/read_server_v3_read_tx.script b/test/resources/boltstub/v3/read_tx.script similarity index 100% rename from test/resources/boltstub/read_server_v3_read_tx.script rename to test/resources/boltstub/v3/read_tx.script diff --git a/test/resources/boltstub/v3/read_tx_dead.script b/test/resources/boltstub/v3/read_tx_dead.script new file mode 100644 index 000000000..ffb0093a3 --- /dev/null +++ b/test/resources/boltstub/v3/read_tx_dead.script @@ -0,0 +1,9 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"mode": "r"} + RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} + PULL_ALL +S: SUCCESS {"fields": []} + diff --git a/test/resources/boltstub/v3/read_tx_with_bookmarks.script b/test/resources/boltstub/v3/read_tx_with_bookmarks.script new file mode 100644 index 000000000..3f2bcd289 --- /dev/null +++ b/test/resources/boltstub/v3/read_tx_with_bookmarks.script @@ -0,0 +1,14 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"], "mode": "r"} +C: RUN "MATCH (n) RETURN n.name AS name" {} {"mode": "r"} + PULL_ALL +S: SUCCESS {} + SUCCESS {"fields": ["name"]} + RECORD ["Bob"] + RECORD ["Alice"] + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} diff --git a/test/resources/boltstub/v3/read_with_server_version.script b/test/resources/boltstub/v3/read_with_server_version.script new file mode 100644 index 000000000..f541da98d --- /dev/null +++ b/test/resources/boltstub/v3/read_with_server_version.script @@ -0,0 +1,12 @@ +!: BOLT 3 +!: AUTO RESET + +C: HELLO {"credentials": "password", "scheme": "basic", "user_agent": "neo4j-javascript/0.0.0-dev", "principal": "neo4j"} +S: SUCCESS {"server": "Neo4j/8.8.8", "connection_id": "bolt-123456789"} +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} + PULL_ALL +S: SUCCESS {"fields": ["n.name"]} + RECORD ["Bob"] + RECORD ["Alice"] + RECORD ["Tina"] + SUCCESS {} diff --git a/test/resources/boltstub/v3/reset_error.script b/test/resources/boltstub/v3/reset_error.script new file mode 100644 index 000000000..6ccc707e5 --- /dev/null +++ b/test/resources/boltstub/v3/reset_error.script @@ -0,0 +1,10 @@ +!: BOLT 3 +!: AUTO HELLO + +C: RUN "RETURN 42 AS answer" {} {} + PULL_ALL +S: SUCCESS {"fields": ["answer"]} + RECORD [42] + SUCCESS {} +C: RESET +S: FAILURE {"code": "Neo.TransientError.General.DatabaseUnavailable", "message": "Unable to reset"} diff --git a/test/resources/boltstub/v3/return_x.script b/test/resources/boltstub/v3/return_x.script new file mode 100644 index 000000000..bd1da7a69 --- /dev/null +++ b/test/resources/boltstub/v3/return_x.script @@ -0,0 +1,9 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "RETURN $x" {"x": 1} {} + PULL_ALL +S: SUCCESS {"fields": ["x"]} + RECORD [1] + SUCCESS {} diff --git a/test/resources/boltstub/write_server_v3_write.script b/test/resources/boltstub/v3/write.script similarity index 100% rename from test/resources/boltstub/write_server_v3_write.script rename to test/resources/boltstub/v3/write.script diff --git a/test/resources/boltstub/v3/write_database_unavailable.script b/test/resources/boltstub/v3/write_database_unavailable.script new file mode 100644 index 000000000..7ceea3baf --- /dev/null +++ b/test/resources/boltstub/v3/write_database_unavailable.script @@ -0,0 +1,8 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "CREATE (n {name:'Bob'})" {} {} +C: PULL_ALL +S: FAILURE {"code": "Neo.TransientError.General.DatabaseUnavailable", "message": "Database is busy doing store copy"} +S: IGNORED diff --git a/test/resources/boltstub/v3/write_dead.script b/test/resources/boltstub/v3/write_dead.script new file mode 100644 index 000000000..9254e7216 --- /dev/null +++ b/test/resources/boltstub/v3/write_dead.script @@ -0,0 +1,7 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "CREATE ()" {} {} +C: PULL_ALL +S: diff --git a/test/resources/boltstub/not_able_to_write.script b/test/resources/boltstub/v3/write_not_a_leader.script similarity index 70% rename from test/resources/boltstub/not_able_to_write.script rename to test/resources/boltstub/v3/write_not_a_leader.script index 43fd25273..c7df15894 100644 --- a/test/resources/boltstub/not_able_to_write.script +++ b/test/resources/boltstub/v3/write_not_a_leader.script @@ -1,8 +1,8 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CREATE ()" {} +C: RUN "CREATE ()" {} {} PULL_ALL S: FAILURE {"code": "Neo.ClientError.Cluster.NotALeader", "message": "blabla"} IGNORED diff --git a/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script b/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script new file mode 100644 index 000000000..d3eedbadb --- /dev/null +++ b/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script @@ -0,0 +1,22 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} + RUN "CREATE (n {name:'Bob'})" {} {} + PULL_ALL +S: SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx4242"]} + RUN "MATCH (n) RETURN n.name AS name" {} {} + PULL_ALL +S: SUCCESS {} + SUCCESS {"fields": ["name"]} + RECORD ["Bob"] + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx424242"} + diff --git a/test/resources/boltstub/write_server_v3_write_tx.script b/test/resources/boltstub/v3/write_twice.script similarity index 62% rename from test/resources/boltstub/write_server_v3_write_tx.script rename to test/resources/boltstub/v3/write_twice.script index b57159066..09e126263 100644 --- a/test/resources/boltstub/write_server_v3_write_tx.script +++ b/test/resources/boltstub/v3/write_twice.script @@ -2,11 +2,11 @@ !: AUTO HELLO !: AUTO RESET -C: BEGIN {} -S: SUCCESS {} C: RUN "CREATE (n {name:'Bob'})" {} {} PULL_ALL S: SUCCESS {"fields": []} SUCCESS {} -C: COMMIT -S: SUCCESS { "bookmark": "ABookmark" } +C: RUN "CREATE ()" {} {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/v3/write_tx.script b/test/resources/boltstub/v3/write_tx.script new file mode 100644 index 000000000..f03f11751 --- /dev/null +++ b/test/resources/boltstub/v3/write_tx.script @@ -0,0 +1,12 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {} + RUN "CREATE (n {name:'Bob'})" {} {} + PULL_ALL +S: SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {} +C: COMMIT +S: SUCCESS {} diff --git a/test/resources/boltstub/v3/write_tx_dead.script b/test/resources/boltstub/v3/write_tx_dead.script new file mode 100644 index 000000000..feb1686c2 --- /dev/null +++ b/test/resources/boltstub/v3/write_tx_dead.script @@ -0,0 +1,9 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {} + RUN "CREATE (n {name:'Bob'})" {} {} + PULL_ALL +S: SUCCESS {} + diff --git a/test/resources/boltstub/v3/write_tx_not_a_leader.script b/test/resources/boltstub/v3/write_tx_not_a_leader.script new file mode 100644 index 000000000..68d5d113f --- /dev/null +++ b/test/resources/boltstub/v3/write_tx_not_a_leader.script @@ -0,0 +1,12 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {} + RUN "CREATE ()" {} {} + PULL_ALL +S: SUCCESS {} + FAILURE {"code": "Neo.ClientError.Cluster.NotALeader", "message": "blabla"} + IGNORED +C: COMMIT +S: IGNORED diff --git a/test/resources/boltstub/v3/write_tx_with_bookmarks.script b/test/resources/boltstub/v3/write_tx_with_bookmarks.script new file mode 100644 index 000000000..a52af8148 --- /dev/null +++ b/test/resources/boltstub/v3/write_tx_with_bookmarks.script @@ -0,0 +1,12 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} +C: RUN "CREATE (n {name:'Bob'})" {} {} + PULL_ALL +S: SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} diff --git a/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script b/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script new file mode 100644 index 000000000..d8a10334d --- /dev/null +++ b/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script @@ -0,0 +1,12 @@ +!: BOLT 3 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx5", "neo4j:bookmark:v1:tx29", "neo4j:bookmark:v1:tx94", "neo4j:bookmark:v1:tx56", "neo4j:bookmark:v1:tx16", "neo4j:bookmark:v1:tx68"]} +C: RUN "CREATE (n {name:'Bob'})" {} {} + PULL_ALL +S: SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {"bookmark": "neo4j:bookmark:v1:tx95"} +C: COMMIT +S: SUCCESS {} diff --git a/test/resources/boltstub/v3/write_with_server_version.script b/test/resources/boltstub/v3/write_with_server_version.script new file mode 100644 index 000000000..65264ff9b --- /dev/null +++ b/test/resources/boltstub/v3/write_with_server_version.script @@ -0,0 +1,9 @@ +!: BOLT 3 +!: AUTO RESET + +C: HELLO {"credentials": "password", "scheme": "basic", "user_agent": "neo4j-javascript/0.0.0-dev", "principal": "neo4j"} +S: SUCCESS {"server": "Neo4j/9.9.9", "connection_id": "bolt-123456789"} +C: RUN "CREATE (n {name:'Bob'})" {} {} + PULL_ALL +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/hello_run_exit_read.script b/test/resources/boltstub/v4/hello_run_exit.script similarity index 80% rename from test/resources/boltstub/hello_run_exit_read.script rename to test/resources/boltstub/v4/hello_run_exit.script index 0fda9d750..c6f10a29a 100644 --- a/test/resources/boltstub/hello_run_exit_read.script +++ b/test/resources/boltstub/v4/hello_run_exit.script @@ -1,10 +1,10 @@ -!: BOLT 3 +!: BOLT 4 !: AUTO RESET C: HELLO {"credentials": "password", "scheme": "basic", "user_agent": "neo4j-javascript/0.0.0-dev", "principal": "neo4j"} S: SUCCESS {"server": "Neo4j/9.9.9", "connection_id": "bolt-123456789"} -C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} - PULL_ALL +C: RUN "MATCH (n) RETURN n.name" {} {} + PULL {"n": -1} S: SUCCESS {"fields": ["n.name"]} RECORD ["Foo"] RECORD ["Bar"] diff --git a/test/resources/boltstub/v4/query_with_error.script b/test/resources/boltstub/v4/query_with_error.script new file mode 100644 index 000000000..d5ead6d9e --- /dev/null +++ b/test/resources/boltstub/v4/query_with_error.script @@ -0,0 +1,11 @@ +!: BOLT 4 +!: AUTO HELLO + +C: RUN "RETURN 10 / 0" {} {} +C: PULL {"n": -1} +S: FAILURE {"code": "Neo.ClientError.Statement.ArithmeticError", "message": "/ by zero"} +S: IGNORED +C: RESET +S: SUCCESS {} +C: RESET +S: SUCCESS {} diff --git a/test/resources/boltstub/v4/read.script b/test/resources/boltstub/v4/read.script new file mode 100644 index 000000000..6c731f83c --- /dev/null +++ b/test/resources/boltstub/v4/read.script @@ -0,0 +1,11 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} + PULL {"n": -1} +S: SUCCESS {"fields": ["n.name"]} + RECORD ["Bob"] + RECORD ["Alice"] + RECORD ["Tina"] + SUCCESS {} diff --git a/test/resources/boltstub/v4/read_dead.script b/test/resources/boltstub/v4/read_dead.script new file mode 100644 index 000000000..98c489e73 --- /dev/null +++ b/test/resources/boltstub/v4/read_dead.script @@ -0,0 +1,7 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} +C: PULL {"n": -1} +S: diff --git a/test/resources/boltstub/v4/read_tx_with_bookmarks.script b/test/resources/boltstub/v4/read_tx_with_bookmarks.script new file mode 100644 index 000000000..3f3281d1c --- /dev/null +++ b/test/resources/boltstub/v4/read_tx_with_bookmarks.script @@ -0,0 +1,14 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"], "mode": "r"} +C: RUN "MATCH (n) RETURN n.name AS name" {} {"mode": "r"} + PULL { "n": -1 } +S: SUCCESS {} + SUCCESS {"fields": ["name"]} + RECORD ["Bob"] + RECORD ["Alice"] + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} diff --git a/test/resources/boltstub/v4/reset_error.script b/test/resources/boltstub/v4/reset_error.script new file mode 100644 index 000000000..e5f00738b --- /dev/null +++ b/test/resources/boltstub/v4/reset_error.script @@ -0,0 +1,10 @@ +!: BOLT 4 +!: AUTO HELLO + +C: RUN "RETURN 42 AS answer" {} {} + PULL {"n": -1} +S: SUCCESS {"fields": ["answer"]} + RECORD [42] + SUCCESS {} +C: RESET +S: FAILURE {"code": "Neo.TransientError.General.DatabaseUnavailable", "message": "Unable to reset"} diff --git a/test/resources/boltstub/v4/return_x.script b/test/resources/boltstub/v4/return_x.script new file mode 100644 index 000000000..8e37a970a --- /dev/null +++ b/test/resources/boltstub/v4/return_x.script @@ -0,0 +1,9 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET + +C: RUN "RETURN $x" {"x": 1} {} + PULL { "n": -1 } +S: SUCCESS {"fields": ["x"]} + RECORD [1] + SUCCESS {} diff --git a/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script b/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script new file mode 100644 index 000000000..aa87e88e8 --- /dev/null +++ b/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script @@ -0,0 +1,22 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} + RUN "CREATE (n {name:'Bob'})" {} {} + PULL {"n": -1} +S: SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx4242"]} + RUN "MATCH (n) RETURN n.name AS name" {} {} + PULL {"n": -1} +S: SUCCESS {} + SUCCESS {"fields": ["name"]} + RECORD ["Bob"] + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx424242"} + diff --git a/test/resources/boltstub/v4/write_tx_with_bookmarks.script b/test/resources/boltstub/v4/write_tx_with_bookmarks.script new file mode 100644 index 000000000..1df1584ba --- /dev/null +++ b/test/resources/boltstub/v4/write_tx_with_bookmarks.script @@ -0,0 +1,12 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET + +C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} +C: RUN "CREATE (n {name:'Bob'})" {} {} + PULL {"n": -1} +S: SUCCESS {} + SUCCESS {"fields": []} + SUCCESS {} +C: COMMIT +S: SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} diff --git a/test/resources/boltstub/write_read_tx_with_bookmark_override.script b/test/resources/boltstub/write_read_tx_with_bookmark_override.script deleted file mode 100644 index 7de0f648e..000000000 --- a/test/resources/boltstub/write_read_tx_with_bookmark_override.script +++ /dev/null @@ -1,30 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx42", "bookmarks": ["neo4j:bookmark:v1:tx42"]} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -C: RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {"bookmark": "neo4j:bookmark:v1:tx4242"} -C: RUN "COMMIT" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -C: RUN "BEGIN" {"bookmark": "neo4j:bookmark:v1:tx99", "bookmarks": ["neo4j:bookmark:v1:tx99"]} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -C: RUN "MATCH (n) RETURN n.name AS name" {} - PULL_ALL -S: SUCCESS {"fields": ["name"]} - RECORD ["Bob"] - SUCCESS {"bookmark": "neo4j:bookmark:v1:tx424242"} -C: RUN "COMMIT" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} - diff --git a/test/resources/boltstub/write_server_v2_write.script b/test/resources/boltstub/write_server_v2_write.script deleted file mode 100644 index 411f7e427..000000000 --- a/test/resources/boltstub/write_server_v2_write.script +++ /dev/null @@ -1,8 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} diff --git a/test/resources/boltstub/write_server_v2_write_tx.script b/test/resources/boltstub/write_server_v2_write_tx.script deleted file mode 100644 index 25877b95a..000000000 --- a/test/resources/boltstub/write_server_v2_write_tx.script +++ /dev/null @@ -1,16 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {} - PULL_ALL - RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} - SUCCESS {"fields": []} - SUCCESS {} -C: RUN "COMMIT" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} diff --git a/test/resources/boltstub/write_server_v2_write_tx_dead.script b/test/resources/boltstub/write_server_v2_write_tx_dead.script deleted file mode 100644 index 81c78817d..000000000 --- a/test/resources/boltstub/write_server_v2_write_tx_dead.script +++ /dev/null @@ -1,11 +0,0 @@ -!: BOLT 2 -!: AUTO INIT -!: AUTO RESET - -C: RUN "BEGIN" {} - PULL_ALL - RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} -S: diff --git a/test/resources/boltstub/write_server_with_version.script b/test/resources/boltstub/write_server_with_version.script deleted file mode 100644 index a22309325..000000000 --- a/test/resources/boltstub/write_server_with_version.script +++ /dev/null @@ -1,9 +0,0 @@ -!: BOLT 2 -!: AUTO RESET - -C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} -S: SUCCESS {"server": "Neo4j/9.9.9"} -C: RUN "CREATE (n {name:'Bob'})" {} - PULL_ALL -S: SUCCESS {"fields": []} - SUCCESS {} From af970efb2250f097391bf61939397c4a98d70ab3 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Mon, 8 Jul 2019 10:53:16 +0100 Subject: [PATCH 04/13] Fix test failures regarding bookmark passing to beginTransaction --- test/transaction.test.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test/transaction.test.js b/test/transaction.test.js index 0783557e6..d7cc79eac 100644 --- a/test/transaction.test.js +++ b/test/transaction.test.js @@ -355,13 +355,12 @@ describe('transaction', () => { }) }) - it('should fail for invalid bookmark', done => { - const invalidBookmark = 'hi, this is an invalid bookmark' - const tx = session.beginTransaction(invalidBookmark) - tx.run('RETURN 1').catch(error => { - expect(error.code).toBe('Neo.ClientError.Transaction.InvalidBookmark') - done() - }) + it('should throw when provided string (bookmark) parameter', () => { + expect(() => session.beginTransaction('bookmark')).toThrowError(TypeError) + }) + + it('should throw when provided string[] (bookmark) parameter', () => { + expect(() => session.beginTransaction(['bookmark'])).toThrowError(TypeError) }) it('should fail to run query for unreachable bookmark', done => { @@ -377,7 +376,10 @@ describe('transaction', () => { expectValidLastBookmark(session) const unreachableBookmark = session.lastBookmark() + '0' - const tx2 = session.beginTransaction(unreachableBookmark) + const session2 = driver.session({ + bookmarks: [unreachableBookmark] + }) + const tx2 = session2.beginTransaction() tx2.run('CREATE ()').catch(error => { const message = error.message const expectedPrefix = From 579b6144ac79358dff802db31c2e2ec409083a04 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Mon, 8 Jul 2019 15:21:28 +0100 Subject: [PATCH 05/13] Add multi-db routing stub tests --- src/internal/connection-provider-routing.js | 8 +- src/internal/routing-util.js | 28 +-- .../node/routing.driver.boltkit.test.js | 227 ++++++++++++++++++ test/internal/routing-util.test.js | 17 +- .../boltstub/v3/acquire_endpoints.script | 1 + .../boltstub/v3/acquire_endpoints_dead.script | 6 +- .../acquire_endpoints_multiple_records.script | 1 + .../v3/acquire_endpoints_no_readers.script | 1 + .../v3/acquire_endpoints_no_records.script | 1 + .../v3/acquire_endpoints_no_routers.script | 1 + .../v3/acquire_endpoints_no_servers.script | 1 + .../acquire_endpoints_no_servers_field.script | 1 + .../v3/acquire_endpoints_no_ttl_field.script | 1 + .../v3/acquire_endpoints_no_writers.script | 1 + .../v3/acquire_endpoints_not_supported.script | 1 + .../v3/acquire_endpoints_one_router.script | 1 + .../v3/acquire_endpoints_rediscover.script | 1 + .../acquire_endpoints_self_as_reader.script | 1 + .../v3/acquire_endpoints_short_ttl.script | 7 +- .../v3/acquire_endpoints_template.script | 1 + ...acquire_endpoints_two_servers_set_1.script | 8 +- ...cquire_endpoints_unparsable_servers.script | 1 + .../acquire_endpoints_unparsable_ttl.script | 1 + .../v3/acquire_endpoints_with_context.script | 1 + .../v3/acquire_endpoints_zero_ttl.script | 1 + .../v3/discover_ipv6_servers_and_read.script | 1 + .../v3/discover_servers_and_read.script | 1 + test/resources/boltstub/v3/no_auth.script | 4 +- .../boltstub/v3/query_with_error.script | 1 + test/resources/boltstub/v3/read.script | 1 + .../v3/read_database_unavailable.script | 1 + test/resources/boltstub/v3/read_tx.script | 1 + .../boltstub/v3/read_tx_with_bookmarks.script | 1 + .../v3/read_with_server_version.script | 1 + test/resources/boltstub/v3/reset_error.script | 1 + test/resources/boltstub/v3/return_x.script | 1 + test/resources/boltstub/v3/write.script | 1 + .../v3/write_database_unavailable.script | 1 + .../boltstub/v3/write_not_a_leader.script | 1 + .../v3/write_read_tx_with_bookmarks.script | 1 + test/resources/boltstub/v3/write_twice.script | 1 + test/resources/boltstub/v3/write_tx.script | 1 + .../boltstub/v3/write_tx_not_a_leader.script | 1 + .../v3/write_tx_with_bookmarks.script | 1 + .../write_tx_with_multiple_bookmarks.script | 1 + .../v3/write_with_server_version.script | 1 + .../v4/acquire_endpoints_aDatabase.script | 10 + ...uire_endpoints_aDatabase_no_servers.script | 10 + .../v4/acquire_endpoints_db_not_found.script | 9 + .../acquire_endpoints_default_database.script | 10 + .../boltstub/v4/query_with_error.script | 1 + test/resources/boltstub/v4/read.script | 1 + .../boltstub/v4/read_from_aDatabase.script | 12 + .../boltstub/v4/read_tx_with_bookmarks.script | 1 + test/resources/boltstub/v4/reset_error.script | 1 + test/resources/boltstub/v4/return_x.script | 1 + test/resources/boltstub/v4/write.script | 9 + .../v4/write_read_tx_with_bookmarks.script | 1 + .../boltstub/v4/write_to_aDatabase.script | 9 + .../v4/write_tx_with_bookmarks.script | 1 + 60 files changed, 373 insertions(+), 46 deletions(-) create mode 100644 test/resources/boltstub/v4/acquire_endpoints_aDatabase.script create mode 100644 test/resources/boltstub/v4/acquire_endpoints_aDatabase_no_servers.script create mode 100644 test/resources/boltstub/v4/acquire_endpoints_db_not_found.script create mode 100644 test/resources/boltstub/v4/acquire_endpoints_default_database.script create mode 100644 test/resources/boltstub/v4/read_from_aDatabase.script create mode 100644 test/resources/boltstub/v4/write.script create mode 100644 test/resources/boltstub/v4/write_to_aDatabase.script diff --git a/src/internal/connection-provider-routing.js b/src/internal/connection-provider-routing.js index dfa56c4a9..d02c9cd30 100644 --- a/src/internal/connection-provider-routing.js +++ b/src/internal/connection-provider-routing.js @@ -295,7 +295,7 @@ export default class RoutingConnectionProvider extends ConnectionProvider { const connectionProvider = new SingleConnectionProvider(connection) if (connection.version().compareTo(VERSION_4_0_0) < 0) { - return new Session({ mode: READ, connectionProvider }) + return new Session({ mode: WRITE, connectionProvider }) } return new Session({ @@ -306,11 +306,7 @@ export default class RoutingConnectionProvider extends ConnectionProvider { }) .catch(error => { // unable to acquire connection towards the given router - if ( - error && - (error.code === UNAUTHORIZED_ERROR_CODE || - error.code === DATABASE_NOT_FOUND_ERROR_CODE) - ) { + if (error && error.code === UNAUTHORIZED_ERROR_CODE) { // auth error and not finding system database is a sign of a configuration issue // discovery should not proceed throw error diff --git a/src/internal/routing-util.js b/src/internal/routing-util.js index 4d17a53e0..821dd1a44 100644 --- a/src/internal/routing-util.js +++ b/src/internal/routing-util.js @@ -19,18 +19,18 @@ import { newError, PROTOCOL_ERROR, SERVICE_UNAVAILABLE } from '../error' import Integer, { int } from '../integer' -import { ServerVersion, VERSION_3_2_0, VERSION_4_0_0 } from './server-version' +import { VERSION_4_0_0 } from './server-version' import Bookmark from './bookmark' import TxConfig from './tx-config' -import { ACCESS_MODE_WRITE } from './constants' +import { ACCESS_MODE_READ, ACCESS_MODE_WRITE } from './constants' import ServerAddress from './server-address' const CONTEXT = 'context' -const CALL_GET_SERVERS = 'CALL dbms.cluster.routing.getServers' const CALL_GET_ROUTING_TABLE = `CALL dbms.cluster.routing.getRoutingTable($${CONTEXT})` const DATABASE = 'database' const CALL_GET_ROUTING_TABLE_MULTI_DB = `CALL dbms.routing.getRoutingTable($${CONTEXT}, $${DATABASE})` const PROCEDURE_NOT_FOUND_CODE = 'Neo.ClientError.Procedure.ProcedureNotFound' +const DATABASE_NOT_FOUND_CODE = 'Neo.ClientError.Database.DatabaseNotFound' export default class RoutingUtil { constructor (routingContext) { @@ -51,7 +51,9 @@ export default class RoutingUtil { return result.records }) .catch(error => { - if (error.code === PROCEDURE_NOT_FOUND_CODE) { + if (error.code === DATABASE_NOT_FOUND_CODE) { + throw error + } else if (error.code === PROCEDURE_NOT_FOUND_CODE) { // throw when getServers procedure not found because this is clearly a configuration issue throw newError( `Server at ${routerAddress.asHostPort()} can't perform routing. Make sure you are connecting to a causal cluster`, @@ -139,22 +141,20 @@ export default class RoutingUtil { if (serverVersion.compareTo(VERSION_4_0_0) >= 0) { query = CALL_GET_ROUTING_TABLE_MULTI_DB - params = {} - params[CONTEXT] = this._routingContext - params[DATABASE] = database - } else if (serverVersion.compareTo(VERSION_3_2_0) >= 0) { - query = CALL_GET_ROUTING_TABLE - params = {} - params[CONTEXT] = this._routingContext + params = { + context: this._routingContext, + database: database || null + } } else { - query = CALL_GET_SERVERS - params = {} + query = CALL_GET_ROUTING_TABLE + params = { context: this._routingContext } } connection.protocol().run(query, params, streamObserver, { bookmark: Bookmark.empty(), txConfig: TxConfig.empty(), - mode: ACCESS_MODE_WRITE + mode: session._mode, + database: session._database }) }) } diff --git a/test/internal/node/routing.driver.boltkit.test.js b/test/internal/node/routing.driver.boltkit.test.js index 990069f93..99101bb44 100644 --- a/test/internal/node/routing.driver.boltkit.test.js +++ b/test/internal/node/routing.driver.boltkit.test.js @@ -2665,6 +2665,233 @@ describe('routing driver with stub server', () => { }) }) + describe('Multi-Database', () => { + function verifyDiscoverAndRead (script, database, done) { + if (!boltStub.supported) { + done() + return + } + + // Given + const server = boltStub.start( + `./test/resources/boltstub/v4/acquire_endpoints_${database || + 'default_database'}.script`, + 9001 + ) + const readServer = boltStub.start( + `./test/resources/boltstub/v4/${script}.script`, + 9005 + ) + + boltStub.run(() => { + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') + // When + const session = driver.session({ + database: database, + defaultAccessMode: READ + }) + session.run('MATCH (n) RETURN n.name').then(() => { + session.close() + // Then + expect( + hasAddressInConnectionPool(driver, '127.0.0.1:9001') + ).toBeTruthy() + expect( + hasAddressInConnectionPool(driver, '127.0.0.1:9005') + ).toBeTruthy() + assertHasRouters( + driver, + ['127.0.0.1:9001', '127.0.0.1:9002', '127.0.0.1:9003'], + database + ) + assertHasReaders( + driver, + ['127.0.0.1:9005', '127.0.0.1:9006'], + database + ) + assertHasWriters( + driver, + ['127.0.0.1:9007', '127.0.0.1:9008'], + database + ) + + driver.close() + server.exit(code => { + readServer.exit(readCode => { + expect(code).toEqual(0) + expect(readCode).toEqual(0) + done() + }) + }) + }) + }) + } + + function verifyDiscoverAndWrite (script, database, done) { + if (!boltStub.supported) { + done() + return + } + + // Given + const server = boltStub.start( + `./test/resources/boltstub/v4/acquire_endpoints_${database || + 'default_database'}.script`, + 9001 + ) + const writeServer = boltStub.start( + `./test/resources/boltstub/v4/${script}.script`, + 9007 + ) + + boltStub.run(() => { + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') + // When + const session = driver.session({ database: database }) + session.run("CREATE (n {name:'Bob'})").then(() => { + session.close() + // Then + expect( + hasAddressInConnectionPool(driver, '127.0.0.1:9001') + ).toBeTruthy() + expect( + hasAddressInConnectionPool(driver, '127.0.0.1:9007') + ).toBeTruthy() + assertHasRouters( + driver, + ['127.0.0.1:9001', '127.0.0.1:9002', '127.0.0.1:9003'], + database + ) + assertHasReaders( + driver, + ['127.0.0.1:9005', '127.0.0.1:9006'], + database + ) + assertHasWriters( + driver, + ['127.0.0.1:9007', '127.0.0.1:9008'], + database + ) + + driver.close() + server.exit(code => { + writeServer.exit(writeCode => { + expect(code).toEqual(0) + expect(writeCode).toEqual(0) + done() + }) + }) + }) + }) + } + + it('should discover servers for default database and read', done => { + verifyDiscoverAndRead('read', '', done) + }) + + it('should discover servers for aDatabase and read', done => { + verifyDiscoverAndRead('read_from_aDatabase', 'aDatabase', done) + }) + + it('should discover servers for default database and write', done => { + verifyDiscoverAndWrite('write', '', done) + }) + + it('should discover servers for aDatabase and write', done => { + verifyDiscoverAndWrite('write_to_aDatabase', 'aDatabase', done) + }) + + it('should fail discovery if database not found', done => { + if (!boltStub.supported) { + done() + return + } + + // Given + const server = boltStub.start( + `./test/resources/boltstub/v4/acquire_endpoints_db_not_found.script`, + 9001 + ) + + boltStub.run(() => { + const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') + // When + const session = driver.session({ database: 'aDatabase' }) + + session.run('CREATE ()').catch(error => { + // Then + expect(error.code).toEqual( + 'Neo.ClientError.Database.DatabaseNotFound' + ) + expect(error.message).toEqual('database not found') + + session.close() + driver.close() + server.exit(code => { + expect(code).toEqual(0) + done() + }) + }) + }) + }) + + it('should try next server for empty routing table response', done => { + if (!boltStub.supported) { + done() + return + } + + // Given + const router1 = boltStub.start( + `./test/resources/boltstub/v4/acquire_endpoints_aDatabase_no_servers.script`, + 9001 + ) + const router2 = boltStub.start( + `./test/resources/boltstub/v4/acquire_endpoints_aDatabase.script`, + 9002 + ) + const reader1 = boltStub.start( + `./test/resources/boltstub/v4/read_from_aDatabase.script`, + 9005 + ) + + boltStub.run(() => { + const driver = boltStub.newDriver('neo4j://127.0.0.1:9000', { + resolver: address => [ + 'neo4j://127.0.0.1:9001', + 'neo4j://127.0.0.1:9002' + ] + }) + + // When + const session = driver.session({ + database: 'aDatabase', + defaultAccessMode: READ + }) + session.run('MATCH (n) RETURN n.name').then(result => { + expect(result.records.map(record => record.get(0))).toEqual([ + 'Bob', + 'Alice', + 'Tina' + ]) + + session.close() + driver.close() + router1.exit(code1 => { + router2.exit(code2 => { + reader1.exit(code3 => { + expect(code1).toEqual(0) + expect(code2).toEqual(0) + expect(code3).toEqual(0) + done() + }) + }) + }) + }) + }) + }) + }) + function testAddressPurgeOnDatabaseError (script, query, accessMode, done) { if (!boltStub.supported) { done() diff --git a/test/internal/routing-util.test.js b/test/internal/routing-util.test.js index 60ef190de..1b6181bf4 100644 --- a/test/internal/routing-util.test.js +++ b/test/internal/routing-util.test.js @@ -100,19 +100,6 @@ describe('RoutingUtil', () => { }) }) - it('should use getServers procedure when server version is older than 3.2.0', done => { - const connection = new FakeConnection().withServerVersion('Neo4j/3.1.9') - const session = FakeSession.withFakeConnection(connection) - - callRoutingProcedure(session, '', {}).then(() => { - expect(connection.seenStatements).toEqual([ - 'CALL dbms.cluster.routing.getServers' - ]) - expect(connection.seenParameters).toEqual([{}]) - done() - }) - }) - it('should use getRoutingTable procedure with empty routing context when server version is 3.2.0', done => { const connection = new FakeConnection().withServerVersion('Neo4j/3.2.0') const session = FakeSession.withFakeConnection(connection) @@ -329,7 +316,9 @@ describe('RoutingUtil', () => { expect(connection.seenStatements).toEqual([ 'CALL dbms.routing.getRoutingTable($context, $database)' ]) - expect(connection.seenParameters).toEqual([{ context, database }]) + expect(connection.seenParameters).toEqual([ + { context, database: database || null } + ]) done() }) } diff --git a/test/resources/boltstub/v3/acquire_endpoints.script b/test/resources/boltstub/v3/acquire_endpoints.script index aaa1b7e94..6853efaf5 100644 --- a/test/resources/boltstub/v3/acquire_endpoints.script +++ b/test/resources/boltstub/v3/acquire_endpoints.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_dead.script b/test/resources/boltstub/v3/acquire_endpoints_dead.script index 9a0770c97..ac8ce484b 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_dead.script +++ b/test/resources/boltstub/v3/acquire_endpoints_dead.script @@ -1,7 +1,7 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: diff --git a/test/resources/boltstub/v3/acquire_endpoints_multiple_records.script b/test/resources/boltstub/v3/acquire_endpoints_multiple_records.script index 66647d257..24158655e 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_multiple_records.script +++ b/test/resources/boltstub/v3/acquire_endpoints_multiple_records.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_readers.script b/test/resources/boltstub/v3/acquire_endpoints_no_readers.script index db6bac919..e5ae9f750 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_readers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_readers.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_records.script b/test/resources/boltstub/v3/acquire_endpoints_no_records.script index 9c2a1bc5d..bc5d5ee53 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_records.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_records.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_routers.script b/test/resources/boltstub/v3/acquire_endpoints_no_routers.script index 43cd8ff08..32160a258 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_routers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_routers.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_servers.script b/test/resources/boltstub/v3/acquire_endpoints_no_servers.script index fa079dcf7..5dd042d32 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_servers.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script b/test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script index 4da56833a..e6b7e1756 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_servers_field.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script b/test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script index 7504b473e..3b659cf3c 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_ttl_field.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_writers.script b/test/resources/boltstub/v3/acquire_endpoints_no_writers.script index ad36238bc..7deb5bbe9 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_writers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_writers.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_not_supported.script b/test/resources/boltstub/v3/acquire_endpoints_not_supported.script index fa4f867a6..cc2abca39 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_not_supported.script +++ b/test/resources/boltstub/v3/acquire_endpoints_not_supported.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} C: PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_one_router.script b/test/resources/boltstub/v3/acquire_endpoints_one_router.script index ff3a8bd7d..8d542b7ef 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_one_router.script +++ b/test/resources/boltstub/v3/acquire_endpoints_one_router.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_rediscover.script b/test/resources/boltstub/v3/acquire_endpoints_rediscover.script index eae2a6ea4..b658e2582 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_rediscover.script +++ b/test/resources/boltstub/v3/acquire_endpoints_rediscover.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script b/test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script index 29096d914..889bd4c25 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script +++ b/test/resources/boltstub/v3/acquire_endpoints_self_as_reader.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_short_ttl.script b/test/resources/boltstub/v3/acquire_endpoints_short_ttl.script index 80d9a50f4..1d5549a1f 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_short_ttl.script +++ b/test/resources/boltstub/v3/acquire_endpoints_short_ttl.script @@ -1,8 +1,9 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [0, [{"addresses": ["127.0.0.1:9007","127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9004"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] diff --git a/test/resources/boltstub/v3/acquire_endpoints_template.script b/test/resources/boltstub/v3/acquire_endpoints_template.script index 40d47398a..d2f826df3 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_template.script +++ b/test/resources/boltstub/v3/acquire_endpoints_template.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script b/test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script index 7a550f9e6..c9683beed 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script +++ b/test/resources/boltstub/v3/acquire_endpoints_two_servers_set_1.script @@ -1,14 +1,14 @@ -!: BOLT 2 -!: AUTO INIT +!: BOLT 3 +!: AUTO HELLO !: AUTO RESET S: SUCCESS {"server": "Neo4j/3.2.2"} -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} +C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"], "role": "READ"},{"addresses": ["127.0.0.1:9001", "127.0.0.1:9002"], "role": "ROUTE"}]] SUCCESS {} -C: RUN "MATCH (n) RETURN n.name AS name" {} +C: RUN "MATCH (n) RETURN n.name AS name" {} {"mode": "r"} PULL_ALL S: SUCCESS {"fields": ["name"]} RECORD ["Alice"] diff --git a/test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script b/test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script index d71c3d8d6..4d0cd0b12 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_unparsable_servers.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script b/test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script index 272e48b1e..16a5f94da 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script +++ b/test/resources/boltstub/v3/acquire_endpoints_unparsable_ttl.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_with_context.script b/test/resources/boltstub/v3/acquire_endpoints_with_context.script index 025a80497..be9ee307b 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_with_context.script +++ b/test/resources/boltstub/v3/acquire_endpoints_with_context.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {"policy": "my_policy", "region": "china"}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script b/test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script index 56ce16dd9..4d780cd5c 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script +++ b/test/resources/boltstub/v3/acquire_endpoints_zero_ttl.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/discover_ipv6_servers_and_read.script b/test/resources/boltstub/v3/discover_ipv6_servers_and_read.script index 0c8bfd618..4163aa231 100644 --- a/test/resources/boltstub/v3/discover_ipv6_servers_and_read.script +++ b/test/resources/boltstub/v3/discover_ipv6_servers_and_read.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/discover_servers_and_read.script b/test/resources/boltstub/v3/discover_servers_and_read.script index ccfbe94e3..ccb6e5ab1 100644 --- a/test/resources/boltstub/v3/discover_servers_and_read.script +++ b/test/resources/boltstub/v3/discover_servers_and_read.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} PULL_ALL diff --git a/test/resources/boltstub/v3/no_auth.script b/test/resources/boltstub/v3/no_auth.script index 3bc89f417..c0a2dd6b6 100644 --- a/test/resources/boltstub/v3/no_auth.script +++ b/test/resources/boltstub/v3/no_auth.script @@ -1,6 +1,6 @@ -!: BOLT 2 +!: BOLT 3 !: AUTO RESET -C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "password", "scheme": "basic", "principal": "neo4j"} +C: HELLO {"credentials": "password", "scheme": "basic", "user_agent": "neo4j-javascript/0.0.0-dev", "principal": "neo4j"} S: FAILURE {"code": "Neo.ClientError.Security.Unauthorized", "message": "Some server auth error message"} S: diff --git a/test/resources/boltstub/v3/query_with_error.script b/test/resources/boltstub/v3/query_with_error.script index bffa97df3..6ed49484f 100644 --- a/test/resources/boltstub/v3/query_with_error.script +++ b/test/resources/boltstub/v3/query_with_error.script @@ -1,5 +1,6 @@ !: BOLT 3 !: AUTO HELLO +!: AUTO GOODBYE C: RUN "RETURN 10 / 0" {} {} C: PULL_ALL diff --git a/test/resources/boltstub/v3/read.script b/test/resources/boltstub/v3/read.script index 9507194e4..35d992bfa 100644 --- a/test/resources/boltstub/v3/read.script +++ b/test/resources/boltstub/v3/read.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} PULL_ALL diff --git a/test/resources/boltstub/v3/read_database_unavailable.script b/test/resources/boltstub/v3/read_database_unavailable.script index a32b5bc6b..79d29ac8e 100644 --- a/test/resources/boltstub/v3/read_database_unavailable.script +++ b/test/resources/boltstub/v3/read_database_unavailable.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "RETURN 1" {} {"mode": "r"} C: PULL_ALL diff --git a/test/resources/boltstub/v3/read_tx.script b/test/resources/boltstub/v3/read_tx.script index 2a5772494..8e3ca520a 100644 --- a/test/resources/boltstub/v3/read_tx.script +++ b/test/resources/boltstub/v3/read_tx.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"mode": "r"} S: SUCCESS {} diff --git a/test/resources/boltstub/v3/read_tx_with_bookmarks.script b/test/resources/boltstub/v3/read_tx_with_bookmarks.script index 3f2bcd289..0af7e78e2 100644 --- a/test/resources/boltstub/v3/read_tx_with_bookmarks.script +++ b/test/resources/boltstub/v3/read_tx_with_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"], "mode": "r"} C: RUN "MATCH (n) RETURN n.name AS name" {} {"mode": "r"} diff --git a/test/resources/boltstub/v3/read_with_server_version.script b/test/resources/boltstub/v3/read_with_server_version.script index f541da98d..99f008b01 100644 --- a/test/resources/boltstub/v3/read_with_server_version.script +++ b/test/resources/boltstub/v3/read_with_server_version.script @@ -1,5 +1,6 @@ !: BOLT 3 !: AUTO RESET +!: AUTO GOODBYE C: HELLO {"credentials": "password", "scheme": "basic", "user_agent": "neo4j-javascript/0.0.0-dev", "principal": "neo4j"} S: SUCCESS {"server": "Neo4j/8.8.8", "connection_id": "bolt-123456789"} diff --git a/test/resources/boltstub/v3/reset_error.script b/test/resources/boltstub/v3/reset_error.script index 6ccc707e5..87c3f26ec 100644 --- a/test/resources/boltstub/v3/reset_error.script +++ b/test/resources/boltstub/v3/reset_error.script @@ -1,5 +1,6 @@ !: BOLT 3 !: AUTO HELLO +!: AUTO GOODBYE C: RUN "RETURN 42 AS answer" {} {} PULL_ALL diff --git a/test/resources/boltstub/v3/return_x.script b/test/resources/boltstub/v3/return_x.script index bd1da7a69..6dfbe9b34 100644 --- a/test/resources/boltstub/v3/return_x.script +++ b/test/resources/boltstub/v3/return_x.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "RETURN $x" {"x": 1} {} PULL_ALL diff --git a/test/resources/boltstub/v3/write.script b/test/resources/boltstub/v3/write.script index ca37a38c1..eea147c5c 100644 --- a/test/resources/boltstub/v3/write.script +++ b/test/resources/boltstub/v3/write.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CREATE (n {name:'Bob'})" {} {} PULL_ALL diff --git a/test/resources/boltstub/v3/write_database_unavailable.script b/test/resources/boltstub/v3/write_database_unavailable.script index 7ceea3baf..6bd5c1670 100644 --- a/test/resources/boltstub/v3/write_database_unavailable.script +++ b/test/resources/boltstub/v3/write_database_unavailable.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CREATE (n {name:'Bob'})" {} {} C: PULL_ALL diff --git a/test/resources/boltstub/v3/write_not_a_leader.script b/test/resources/boltstub/v3/write_not_a_leader.script index c7df15894..fcd82f017 100644 --- a/test/resources/boltstub/v3/write_not_a_leader.script +++ b/test/resources/boltstub/v3/write_not_a_leader.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CREATE ()" {} {} PULL_ALL diff --git a/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script b/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script index d3eedbadb..557899f24 100644 --- a/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script +++ b/test/resources/boltstub/v3/write_read_tx_with_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} RUN "CREATE (n {name:'Bob'})" {} {} diff --git a/test/resources/boltstub/v3/write_twice.script b/test/resources/boltstub/v3/write_twice.script index 09e126263..92495963c 100644 --- a/test/resources/boltstub/v3/write_twice.script +++ b/test/resources/boltstub/v3/write_twice.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "CREATE (n {name:'Bob'})" {} {} PULL_ALL diff --git a/test/resources/boltstub/v3/write_tx.script b/test/resources/boltstub/v3/write_tx.script index f03f11751..9cdf869d5 100644 --- a/test/resources/boltstub/v3/write_tx.script +++ b/test/resources/boltstub/v3/write_tx.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {} RUN "CREATE (n {name:'Bob'})" {} {} diff --git a/test/resources/boltstub/v3/write_tx_not_a_leader.script b/test/resources/boltstub/v3/write_tx_not_a_leader.script index 68d5d113f..933e2d016 100644 --- a/test/resources/boltstub/v3/write_tx_not_a_leader.script +++ b/test/resources/boltstub/v3/write_tx_not_a_leader.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {} RUN "CREATE ()" {} {} diff --git a/test/resources/boltstub/v3/write_tx_with_bookmarks.script b/test/resources/boltstub/v3/write_tx_with_bookmarks.script index a52af8148..b72670bdb 100644 --- a/test/resources/boltstub/v3/write_tx_with_bookmarks.script +++ b/test/resources/boltstub/v3/write_tx_with_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} C: RUN "CREATE (n {name:'Bob'})" {} {} diff --git a/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script b/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script index d8a10334d..73bbce666 100644 --- a/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script +++ b/test/resources/boltstub/v3/write_tx_with_multiple_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 3 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx5", "neo4j:bookmark:v1:tx29", "neo4j:bookmark:v1:tx94", "neo4j:bookmark:v1:tx56", "neo4j:bookmark:v1:tx16", "neo4j:bookmark:v1:tx68"]} C: RUN "CREATE (n {name:'Bob'})" {} {} diff --git a/test/resources/boltstub/v3/write_with_server_version.script b/test/resources/boltstub/v3/write_with_server_version.script index 65264ff9b..a35212194 100644 --- a/test/resources/boltstub/v3/write_with_server_version.script +++ b/test/resources/boltstub/v3/write_with_server_version.script @@ -1,5 +1,6 @@ !: BOLT 3 !: AUTO RESET +!: AUTO GOODBYE C: HELLO {"credentials": "password", "scheme": "basic", "user_agent": "neo4j-javascript/0.0.0-dev", "principal": "neo4j"} S: SUCCESS {"server": "Neo4j/9.9.9", "connection_id": "bolt-123456789"} diff --git a/test/resources/boltstub/v4/acquire_endpoints_aDatabase.script b/test/resources/boltstub/v4/acquire_endpoints_aDatabase.script new file mode 100644 index 000000000..1eaef80d6 --- /dev/null +++ b/test/resources/boltstub/v4/acquire_endpoints_aDatabase.script @@ -0,0 +1,10 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "CALL dbms.routing.getRoutingTable($context, $database)" {"context": {}, "database": "aDatabase"} {"mode": "r", "db": "system"} + PULL {"n": -1} +S: SUCCESS {"fields": ["ttl", "servers"]} + RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007","127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] + SUCCESS {} diff --git a/test/resources/boltstub/v4/acquire_endpoints_aDatabase_no_servers.script b/test/resources/boltstub/v4/acquire_endpoints_aDatabase_no_servers.script new file mode 100644 index 000000000..975fbe684 --- /dev/null +++ b/test/resources/boltstub/v4/acquire_endpoints_aDatabase_no_servers.script @@ -0,0 +1,10 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "CALL dbms.routing.getRoutingTable($context, $database)" {"context": {}, "database":"aDatabase"} {"mode": "r", "db": "system"} + PULL {"n": -1} +S: SUCCESS {"fields": ["ttl", "servers"]} + RECORD [9223372036854775807, []] + SUCCESS {} diff --git a/test/resources/boltstub/v4/acquire_endpoints_db_not_found.script b/test/resources/boltstub/v4/acquire_endpoints_db_not_found.script new file mode 100644 index 000000000..38ae86c5f --- /dev/null +++ b/test/resources/boltstub/v4/acquire_endpoints_db_not_found.script @@ -0,0 +1,9 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "CALL dbms.routing.getRoutingTable($context, $database)" {"context": {}, "database": "aDatabase"} {"mode": "r", "db": "system"} + PULL {"n": -1} +S: FAILURE {"code": "Neo.ClientError.Database.DatabaseNotFound", "message": "database not found"} + IGNORED diff --git a/test/resources/boltstub/v4/acquire_endpoints_default_database.script b/test/resources/boltstub/v4/acquire_endpoints_default_database.script new file mode 100644 index 000000000..c8efa4037 --- /dev/null +++ b/test/resources/boltstub/v4/acquire_endpoints_default_database.script @@ -0,0 +1,10 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "CALL dbms.routing.getRoutingTable($context, $database)" {"context": {}, "database": null} {"mode": "r", "db": "system"} + PULL {"n": -1} +S: SUCCESS {"fields": ["ttl", "servers"]} + RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007","127.0.0.1:9008"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] + SUCCESS {} diff --git a/test/resources/boltstub/v4/query_with_error.script b/test/resources/boltstub/v4/query_with_error.script index d5ead6d9e..48c37f036 100644 --- a/test/resources/boltstub/v4/query_with_error.script +++ b/test/resources/boltstub/v4/query_with_error.script @@ -1,5 +1,6 @@ !: BOLT 4 !: AUTO HELLO +!: AUTO GOODBYE C: RUN "RETURN 10 / 0" {} {} C: PULL {"n": -1} diff --git a/test/resources/boltstub/v4/read.script b/test/resources/boltstub/v4/read.script index 6c731f83c..11f0fb56a 100644 --- a/test/resources/boltstub/v4/read.script +++ b/test/resources/boltstub/v4/read.script @@ -1,6 +1,7 @@ !: BOLT 4 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r"} PULL {"n": -1} diff --git a/test/resources/boltstub/v4/read_from_aDatabase.script b/test/resources/boltstub/v4/read_from_aDatabase.script new file mode 100644 index 000000000..910f346c8 --- /dev/null +++ b/test/resources/boltstub/v4/read_from_aDatabase.script @@ -0,0 +1,12 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "MATCH (n) RETURN n.name" {} {"mode": "r", "db": "aDatabase"} + PULL {"n": -1} +S: SUCCESS {"fields": ["n.name"]} + RECORD ["Bob"] + RECORD ["Alice"] + RECORD ["Tina"] + SUCCESS {} diff --git a/test/resources/boltstub/v4/read_tx_with_bookmarks.script b/test/resources/boltstub/v4/read_tx_with_bookmarks.script index 3f3281d1c..50d80c1db 100644 --- a/test/resources/boltstub/v4/read_tx_with_bookmarks.script +++ b/test/resources/boltstub/v4/read_tx_with_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 4 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"], "mode": "r"} C: RUN "MATCH (n) RETURN n.name AS name" {} {"mode": "r"} diff --git a/test/resources/boltstub/v4/reset_error.script b/test/resources/boltstub/v4/reset_error.script index e5f00738b..8b77172b9 100644 --- a/test/resources/boltstub/v4/reset_error.script +++ b/test/resources/boltstub/v4/reset_error.script @@ -1,5 +1,6 @@ !: BOLT 4 !: AUTO HELLO +!: AUTO GOODBYE C: RUN "RETURN 42 AS answer" {} {} PULL {"n": -1} diff --git a/test/resources/boltstub/v4/return_x.script b/test/resources/boltstub/v4/return_x.script index 8e37a970a..5216b685d 100644 --- a/test/resources/boltstub/v4/return_x.script +++ b/test/resources/boltstub/v4/return_x.script @@ -1,6 +1,7 @@ !: BOLT 4 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: RUN "RETURN $x" {"x": 1} {} PULL { "n": -1 } diff --git a/test/resources/boltstub/v4/write.script b/test/resources/boltstub/v4/write.script new file mode 100644 index 000000000..36618e1a4 --- /dev/null +++ b/test/resources/boltstub/v4/write.script @@ -0,0 +1,9 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "CREATE (n {name:'Bob'})" {} {} + PULL {"n": -1} +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script b/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script index aa87e88e8..f3dda0325 100644 --- a/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script +++ b/test/resources/boltstub/v4/write_read_tx_with_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 4 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} RUN "CREATE (n {name:'Bob'})" {} {} diff --git a/test/resources/boltstub/v4/write_to_aDatabase.script b/test/resources/boltstub/v4/write_to_aDatabase.script new file mode 100644 index 000000000..281eb22fa --- /dev/null +++ b/test/resources/boltstub/v4/write_to_aDatabase.script @@ -0,0 +1,9 @@ +!: BOLT 4 +!: AUTO HELLO +!: AUTO RESET +!: AUTO GOODBYE + +C: RUN "CREATE (n {name:'Bob'})" {} {"db": "aDatabase"} + PULL {"n": -1} +S: SUCCESS {"fields": []} + SUCCESS {} diff --git a/test/resources/boltstub/v4/write_tx_with_bookmarks.script b/test/resources/boltstub/v4/write_tx_with_bookmarks.script index 1df1584ba..ed2a0a334 100644 --- a/test/resources/boltstub/v4/write_tx_with_bookmarks.script +++ b/test/resources/boltstub/v4/write_tx_with_bookmarks.script @@ -1,6 +1,7 @@ !: BOLT 4 !: AUTO HELLO !: AUTO RESET +!: AUTO GOODBYE C: BEGIN {"bookmarks": ["neo4j:bookmark:v1:tx42"]} C: RUN "CREATE (n {name:'Bob'})" {} {} From 9d03115f55c2b6765f58ea07b3c9773d4bdfdcfb Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Tue, 9 Jul 2019 18:05:41 +0100 Subject: [PATCH 06/13] Push pooling logic into connection providers --- gulpfile.babel.js | 34 ++ package-lock.json | 22 +- spec/support/jasmine.json | 7 + src/driver.js | 121 +--- src/internal/connection-channel.js | 520 ++++++++++++++++++ src/internal/connection-delegate.js | 92 ++++ src/internal/connection-holder.js | 4 +- src/internal/connection-provider-direct.js | 17 +- src/internal/connection-provider-pooled.js | 126 +++++ src/internal/connection-provider-routing.js | 166 ++++-- src/internal/connection-provider.js | 12 +- src/internal/connection.js | 477 ++-------------- src/internal/routing-util.js | 8 +- src/internal/server-version.js | 32 +- src/routing-driver.js | 72 +-- src/session.js | 2 +- test/auth.test.js | 2 +- test/bolt-v3.test.js | 2 +- test/bolt-v4.test.js | 2 +- test/driver.test.js | 13 +- test/examples.test.js | 2 +- test/integer.test.js | 2 +- test/internal/bolt-protocol-v1.test.js | 2 +- test/internal/bolt-protocol-v3.test.js | 2 +- test/internal/bolt-protocol-v4.test.js | 2 +- test/internal/bolt-stub.js | 3 +- test/internal/bookmark.test.js | 2 +- test/internal/browser/browser-channel.test.js | 2 +- .../browser-host-name-resolver.test.js | 2 +- test/internal/buf.test.js | 2 +- test/internal/channel-config.test.js | 2 +- test/internal/chunking.test.js | 2 +- ...ion.test.js => connection-channel.test.js} | 20 +- .../internal/connection-error-handler.test.js | 2 +- test/internal/connection-holder.test.js | 4 +- .../connection-provider-direct.test.js | 25 +- .../connection-provider-routing.test.js | 41 +- test/internal/connectivity-verifier.test.js | 2 +- test/internal/fake-connection.js | 36 +- test/internal/http/http-driver.test.js | 12 +- .../internal/http/http-request-runner.test.js | 2 +- .../http/http-session-tracker.test.js | 2 +- test/internal/http/http-session.test.js | 2 +- ...-connected-load-balancing-strategy.test.js | 2 +- test/internal/logger.test.js | 4 +- .../node/direct.driver.boltkit.test.js | 37 +- .../node/node-host-name-resolver.test.js | 2 +- .../node/routing.driver.boltkit.test.js | 6 +- test/internal/node/tls.test.js | 6 +- test/internal/packstream-v1.test.js | 2 +- test/internal/pool-config.test.js | 2 +- test/internal/pool.test.js | 2 +- test/internal/protocol-handshaker.test.js | 2 +- test/internal/rediscovery.test.js | 2 +- test/internal/request-message.test.js | 2 +- test/internal/round-robin-array-index.test.js | 2 +- test/internal/routing-table.test.js | 2 +- test/internal/routing-util.test.js | 2 +- test/internal/server-address.test.js | 2 +- test/internal/server-version.test.js | 70 +-- test/internal/stream-observer.test.js | 2 +- test/internal/temporal-util.test.js | 2 +- test/internal/test-utils.js | 5 +- test/internal/transaction-executor.test.js | 2 +- test/internal/tx-config.test.js | 2 +- test/internal/url-util.test.js | 2 +- test/internal/utf8.test.js | 2 +- test/internal/util.test.js | 2 +- test/record.test.js | 2 +- test/result.test.js | 2 +- test/routing-driver.test.js | 11 +- test/session.test.js | 2 +- test/spatial-types.test.js | 2 +- test/stress.test.js | 2 +- test/summary.test.js | 2 +- test/temporal-types.test.js | 2 +- test/transaction.test.js | 2 +- test/types.test.js | 22 +- 78 files changed, 1234 insertions(+), 885 deletions(-) create mode 100644 spec/support/jasmine.json create mode 100644 src/internal/connection-channel.js create mode 100644 src/internal/connection-delegate.js create mode 100644 src/internal/connection-provider-pooled.js rename test/internal/{connection.test.js => connection-channel.test.js} (97%) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index b23ee6f19..81a7492f5 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -38,6 +38,7 @@ const ts = require('gulp-typescript') const JasmineReporter = require('jasmine-spec-reporter').SpecReporter const karma = require('karma') const log = require('fancy-log') +const JasmineExec = require('jasmine') /** * Useful to investigate resource leaks in tests. Enable to see active sockets and file handles after the 'test' task. @@ -112,6 +113,18 @@ gulp.task( }) ) +gulp.task('test-nodejs-unit', () => { + return runJasmineTests('#unit*') +}) + +gulp.task('test-nodejs-stub', () => { + return runJasmineTests('#stub*') +}) + +gulp.task('test-nodejs-integration', () => { + return runJasmineTests('#integration*') +}) + gulp.task('run-browser-test-chrome', function (cb) { runKarma('chrome', cb) }) @@ -248,3 +261,24 @@ function runKarma (browser, cb) { } ).start() } + +function runJasmineTests (filterString) { + return new Promise((resolve, reject) => { + const jasmine = new JasmineExec() + jasmine.loadConfigFile('./spec/support/jasmine.json') + jasmine.loadHelpers() + jasmine.loadSpecs() + jasmine.configureDefaultReporter({ + print: () => {} + }) + jasmine.addReporter(newJasmineConsoleReporter()) + jasmine.onComplete(passed => { + if (passed) { + resolve() + } else { + reject(new Error('tests failed')) + } + }) + jasmine.execute(null, filterString) + }) +} diff --git a/package-lock.json b/package-lock.json index 2920ae739..8c431c827 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1485,26 +1485,10 @@ }, "dependencies": { "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz", + "integrity": "sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==", "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", - "dev": true - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha1-tPOxDVGFelrwE4086AA7IBYT1Zk=", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } } } }, diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json new file mode 100644 index 000000000..2e054b235 --- /dev/null +++ b/spec/support/jasmine.json @@ -0,0 +1,7 @@ +{ + "spec_dir": "test", + "spec_files": ["**/*.test.js", "!**/browser/*.js"], + "helpers": ["../node_modules/@babel/register/lib/node.js"], + "stopSpecOnExpectationFailure": false, + "random": true +} diff --git a/src/driver.js b/src/driver.js index 11fe99de6..9b555b891 100644 --- a/src/driver.js +++ b/src/driver.js @@ -19,7 +19,7 @@ import Session from './session' import Pool from './internal/pool' -import Connection from './internal/connection' +import ChannelConnection from './internal/connection-channel' import { newError, SERVICE_UNAVAILABLE } from './error' import DirectConnectionProvider from './internal/connection-provider-direct' import Bookmark from './internal/bookmark' @@ -76,19 +76,9 @@ class Driver { this._id = idGenerator++ this._address = address this._userAgent = userAgent - this._openConnections = {} this._authToken = authToken this._config = config this._log = Logger.create(config) - this._pool = new Pool({ - create: this._createConnection.bind(this), - destroy: this._destroyConnection.bind(this), - validate: this._validateConnection.bind(this), - installIdleObserver: this._installIdleObserverOnConnection.bind(this), - removeIdleObserver: this._removeIdleObserverOnConnection.bind(this), - config: PoolConfig.fromDriverConfig(config), - log: this._log - }) /** * Reference to the connection provider. Initialized lazily by {@link _getOrCreateConnectionProvider}. @@ -120,66 +110,6 @@ class Driver { return connectivityVerifier.verify({ database }) } - /** - * Create a new connection and initialize it. - * @return {Promise} promise resolved with a new connection or rejected when failed to connect. - * @access private - */ - _createConnection (address, release) { - const connection = Connection.create( - address, - this._config, - this._createConnectionErrorHandler(), - this._log - ) - connection._release = () => release(address, connection) - this._openConnections[connection.id] = connection - - return connection.connect(this._userAgent, this._authToken).catch(error => { - if (this.onError) { - // notify Driver.onError callback about connection initialization errors - this.onError(error) - } - // let's destroy this connection - this._destroyConnection(connection) - // propagate the error because connection failed to connect / initialize - throw error - }) - } - - /** - * Check that a connection is usable - * @return {boolean} true if the connection is open - * @access private - **/ - _validateConnection (conn) { - if (!conn.isOpen()) { - return false - } - - const maxConnectionLifetime = this._config.maxConnectionLifetime - const lifetime = Date.now() - conn.creationTimestamp - return lifetime <= maxConnectionLifetime - } - - _installIdleObserverOnConnection (conn, observer) { - conn._queueObserver(observer) - } - - _removeIdleObserverOnConnection (conn) { - conn._updateCurrentObserver() - } - - /** - * Dispose of a connection. - * @return {Connection} the connection to dispose. - * @access private - */ - _destroyConnection (conn) { - delete this._openConnections[conn.id] - conn.close() - } - /** * Acquire a session to communicate with the database. The session will * borrow connections from the underlying connection pool as required and @@ -225,38 +155,27 @@ class Driver { } // Extension point - _createConnectionProvider (address, connectionPool, driverOnErrorCallback) { - return new DirectConnectionProvider( - address, - connectionPool, - driverOnErrorCallback - ) - } - - // Extension point - _createConnectionErrorHandler () { - return new ConnectionErrorHandler(SERVICE_UNAVAILABLE) + _createConnectionProvider (address, userAgent, authToken) { + return new DirectConnectionProvider({ + id: this._id, + config: this._config, + log: this._log, + address: address, + userAgent: userAgent, + authToken: authToken + }) } _getOrCreateConnectionProvider () { if (!this._connectionProvider) { - const driverOnErrorCallback = this._driverOnErrorCallback.bind(this) this._connectionProvider = this._createConnectionProvider( this._address, - this._pool, - driverOnErrorCallback + this._userAgent, + this._authToken ) } - return this._connectionProvider - } - _driverOnErrorCallback (error) { - const userDefinedOnErrorCallback = this.onError - if (userDefinedOnErrorCallback && error.code === SERVICE_UNAVAILABLE) { - userDefinedOnErrorCallback(error) - } else { - // we don't need to tell the driver about this error - } + return this._connectionProvider } /** @@ -266,18 +185,8 @@ class Driver { */ close () { this._log.info(`Driver ${this._id} closing`) - - try { - // purge all idle connections in the connection pool - this._pool.purgeAll() - } finally { - // then close all connections driver has ever created - // it is needed to close connections that are active right now and are acquired from the pool - for (let connectionId in this._openConnections) { - if (this._openConnections.hasOwnProperty(connectionId)) { - this._openConnections[connectionId].close() - } - } + if (this._connectionProvider) { + this._connectionProvider.close() } } } diff --git a/src/internal/connection-channel.js b/src/internal/connection-channel.js new file mode 100644 index 000000000..4a6b0454f --- /dev/null +++ b/src/internal/connection-channel.js @@ -0,0 +1,520 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Channel } from './node' +import { Chunker, Dechunker } from './chunking' +import { newError, PROTOCOL_ERROR } from '../error' +import ChannelConfig from './channel-config' +import ProtocolHandshaker from './protocol-handshaker' +import Connection from './connection' + +// Signature bytes for each response message type +const SUCCESS = 0x70 // 0111 0000 // SUCCESS +const RECORD = 0x71 // 0111 0001 // RECORD +const IGNORED = 0x7e // 0111 1110 // IGNORED +const FAILURE = 0x7f // 0111 1111 // FAILURE + +function NO_OP () {} + +const NO_OP_OBSERVER = { + onNext: NO_OP, + onCompleted: NO_OP, + onError: NO_OP +} + +let idGenerator = 0 + +export default class ChannelConnection extends Connection { + /** + * @constructor + * @param {Channel} channel - channel with a 'write' function and a 'onmessage' callback property. + * @param {ConnectionErrorHandler} errorHandler the error handler. + * @param {ServerAddress} address - the server address to connect to. + * @param {Logger} log - the configured logger. + * @param {boolean} disableLosslessIntegers if this connection should convert all received integers to native JS numbers. + */ + constructor ( + channel, + errorHandler, + address, + log, + disableLosslessIntegers = false + ) { + super(errorHandler) + + this._id = idGenerator++ + this._address = address + this._server = { address: address.asHostPort() } + this.creationTimestamp = Date.now() + this._disableLosslessIntegers = disableLosslessIntegers + this._pendingObservers = [] + this._currentObserver = undefined + this._ch = channel + this._dechunker = new Dechunker() + this._chunker = new Chunker(channel) + this._log = log + + // connection from the database, returned in response for HELLO message and might not be available + this._dbConnectionId = null + + // bolt protocol is initially not initialized + this._protocol = null + + // error extracted from a FAILURE message + this._currentFailure = null + + // Set to true on fatal errors, to get this out of connection pool. + this._isBroken = false + + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} created towards ${address}`) + } + } + + /** + * Crete new connection to the provided address. Returned connection is not connected. + * @param {ServerAddress} address - the Bolt endpoint to connect to. + * @param {object} config - the driver configuration. + * @param {ConnectionErrorHandler} errorHandler - the error handler for connection errors. + * @param {Logger} log - configured logger. + * @return {Connection} - new connection. + */ + static create (address, config, errorHandler, log) { + const channelConfig = new ChannelConfig( + address, + config, + errorHandler.errorCode() + ) + return new ChannelConnection( + new Channel(channelConfig), + errorHandler, + address, + log, + config.disableLosslessIntegers + ) + } + + get id () { + return this._id + } + + get databaseId () { + return this._dbConnectionId + } + + set databaseId (value) { + this._dbConnectionId = value + } + + /** + * Connect to the target address, negotiate Bolt protocol and send initialization message. + * @param {string} userAgent the user agent for this driver. + * @param {object} authToken the object containing auth information. + * @return {Promise} promise resolved with the current connection if connection is successful. Rejected promise otherwise. + */ + connect (userAgent, authToken) { + return this._negotiateProtocol().then(() => + this._initialize(userAgent, authToken) + ) + } + + /** + * Execute Bolt protocol handshake to initialize the protocol version. + * @return {Promise} promise resolved with the current connection if handshake is successful. Rejected promise otherwise. + */ + _negotiateProtocol () { + const protocolHandshaker = new ProtocolHandshaker( + this, + this._ch, + this._chunker, + this._disableLosslessIntegers, + this._log + ) + + return new Promise((resolve, reject) => { + const handshakeErrorHandler = error => { + this._handleFatalError(error) + reject(error) + } + + this._ch.onerror = handshakeErrorHandler.bind(this) + if (this._ch._error) { + // channel is already broken + handshakeErrorHandler(this._ch._error) + } + + this._ch.onmessage = buffer => { + try { + // read the response buffer and initialize the protocol + this._protocol = protocolHandshaker.createNegotiatedProtocol(buffer) + + // reset the error handler to just handle errors and forget about the handshake promise + this._ch.onerror = this._handleFatalError.bind(this) + + // Ok, protocol running. Simply forward all messages to the dechunker + this._ch.onmessage = buf => this._dechunker.write(buf) + + // setup dechunker to dechunk messages and forward them to the message handler + this._dechunker.onmessage = buf => { + this._handleMessage(this._protocol.unpacker().unpack(buf)) + } + // forward all pending bytes to the dechunker + if (buffer.hasRemaining()) { + this._dechunker.write(buffer.readSlice(buffer.remaining())) + } + + resolve(this) + } catch (e) { + this._handleFatalError(e) + reject(e) + } + } + + protocolHandshaker.writeHandshakeRequest() + }) + } + + /** + * Perform protocol-specific initialization which includes authentication. + * @param {string} userAgent the user agent for this driver. + * @param {object} authToken the object containing auth information. + * @return {Promise} promise resolved with the current connection if initialization is successful. Rejected promise otherwise. + */ + _initialize (userAgent, authToken) { + return new Promise((resolve, reject) => { + const observer = new InitializationObserver(this, resolve, reject) + this._protocol.initialize(userAgent, authToken, observer) + }) + } + + /** + * Get the Bolt protocol for the connection. + * @return {BoltProtocol} the protocol. + */ + protocol () { + return this._protocol + } + + get address () { + return this._address + } + + /** + * Get the version of the connected server. + * Available only after initialization + * + * @returns {ServerVersion} version + */ + get version () { + return this._server.version + } + + set version (value) { + this._server.version = value + } + + get server () { + return this._server + } + + /** + * Write a message to the network channel. + * @param {RequestMessage} message the message to write. + * @param {StreamObserver} observer the response observer. + * @param {boolean} flush `true` if flush should happen after the message is written to the buffer. + */ + write (message, observer, flush) { + const queued = this._queueObserver(observer) + + if (queued) { + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} C: ${message}`) + } + + this._protocol + .packer() + .packStruct( + message.signature, + message.fields.map(field => this._packable(field)), + err => this._handleFatalError(err) + ) + + this._chunker.messageBoundary() + + if (flush) { + this._chunker.flush() + } + } + } + + /** + * "Fatal" means the connection is dead. Only call this if something + * happens that cannot be recovered from. This will lead to all subscribers + * failing, and the connection getting ejected from the session pool. + * + * @param error an error object, forwarded to all current and future subscribers + */ + _handleFatalError (error) { + this._isBroken = true + this._error = this.handleAndTransformError(error, this._address) + + if (this._log.isErrorEnabled()) { + this._log.error( + `${this} experienced a fatal error ${JSON.stringify(this._error)}` + ) + } + + if (this._currentObserver && this._currentObserver.onError) { + this._currentObserver.onError(this._error) + } + while (this._pendingObservers.length > 0) { + let observer = this._pendingObservers.shift() + if (observer && observer.onError) { + observer.onError(this._error) + } + } + } + + _handleMessage (msg) { + if (this._isBroken) { + // ignore all incoming messages when this connection is broken. all previously pending observers failed + // with the fatal error. all future observers will fail with same fatal error. + return + } + + const payload = msg.fields[0] + + switch (msg.signature) { + case RECORD: + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} S: RECORD ${JSON.stringify(msg)}`) + } + this._currentObserver.onNext(payload) + break + case SUCCESS: + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} S: SUCCESS ${JSON.stringify(msg)}`) + } + try { + const metadata = this._protocol.transformMetadata(payload) + this._currentObserver.onCompleted(metadata) + } finally { + this._updateCurrentObserver() + } + break + case FAILURE: + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} S: FAILURE ${JSON.stringify(msg)}`) + } + try { + const error = newError(payload.message, payload.code) + this._currentFailure = this.handleAndTransformError( + error, + this._address + ) + this._currentObserver.onError(this._currentFailure) + } finally { + this._updateCurrentObserver() + // Things are now broken. Pending observers will get FAILURE messages routed until we are done handling this failure. + this._resetOnFailure() + } + break + case IGNORED: + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} S: IGNORED ${JSON.stringify(msg)}`) + } + try { + if (this._currentFailure && this._currentObserver.onError) { + this._currentObserver.onError(this._currentFailure) + } else if (this._currentObserver.onError) { + this._currentObserver.onError( + newError('Ignored either because of an error or RESET') + ) + } + } finally { + this._updateCurrentObserver() + } + break + default: + this._handleFatalError( + newError('Unknown Bolt protocol message: ' + msg) + ) + } + } + + /** + * Send a RESET-message to the database. Message is immediately flushed to the network. + * @return {Promise} promise resolved when SUCCESS-message response arrives, or failed when other response messages arrives. + */ + resetAndFlush () { + return new Promise((resolve, reject) => { + this._protocol.reset({ + onNext: record => { + const neo4jError = this._handleProtocolError( + 'Received RECORD as a response for RESET: ' + JSON.stringify(record) + ) + reject(neo4jError) + }, + onError: error => { + if (this._isBroken) { + // handling a fatal error, no need to raise a protocol violation + reject(error) + } else { + const neo4jError = this._handleProtocolError( + 'Received FAILURE as a response for RESET: ' + error + ) + reject(neo4jError) + } + }, + onCompleted: () => { + resolve() + } + }) + }) + } + + _resetOnFailure () { + this._protocol.reset({ + onNext: record => { + this._handleProtocolError( + 'Received RECORD as a response for RESET: ' + JSON.stringify(record) + ) + }, + // clear the current failure when response for RESET is received + onError: () => { + this._currentFailure = null + }, + onCompleted: () => { + this._currentFailure = null + } + }) + } + + _queueObserver (observer) { + if (this._isBroken) { + if (observer && observer.onError) { + observer.onError(this._error) + } + return false + } + observer = observer || NO_OP_OBSERVER + observer.onCompleted = observer.onCompleted || NO_OP + observer.onError = observer.onError || NO_OP + observer.onNext = observer.onNext || NO_OP + if (this._currentObserver === undefined) { + this._currentObserver = observer + } else { + this._pendingObservers.push(observer) + } + return true + } + + /* + * Pop next pending observer form the list of observers and make it current observer. + * @protected + */ + _updateCurrentObserver () { + this._currentObserver = this._pendingObservers.shift() + } + + /** Check if this connection is in working condition */ + isOpen () { + return !this._isBroken && this._ch._open + } + + /** + * Call close on the channel. + * @param {function} cb - Function to call on close. + */ + close (cb = () => null) { + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} closing`) + } + + if (this._protocol && this.isOpen()) { + // protocol has been initialized and this connection is healthy + // notify the database about the upcoming close of the connection + this._protocol.prepareToClose(NO_OP_OBSERVER) + } + + this._ch.close(() => { + if (this._log.isDebugEnabled()) { + this._log.debug(`${this} closed`) + } + cb() + }) + } + + toString () { + return `Connection [${this.id}][${this.databaseId || ''}]` + } + + _packable (value) { + return this._protocol + .packer() + .packable(value, err => this._handleFatalError(err)) + } + + _handleProtocolError (message) { + this._currentFailure = null + this._updateCurrentObserver() + const error = newError(message, PROTOCOL_ERROR) + this._handleFatalError(error) + return error + } +} + +class InitializationObserver { + constructor (connection, onSuccess, onError) { + this._connection = connection + this._onSuccess = onSuccess + this._onError = onError + } + + onNext (record) { + this.onError( + newError('Received RECORD when initializing ' + JSON.stringify(record)) + ) + } + + onError (error) { + this._connection._updateCurrentObserver() // make sure this exact observer will not be called again + this._connection._handleFatalError(error) // initialization errors are fatal + + this._onError(error) + } + + onCompleted (metadata) { + if (metadata) { + // read server version from the response metadata, if it is available + const serverVersion = metadata.server + if (!this._connection.version) { + this._connection.version = serverVersion + } + + // read database connection id from the response metadata, if it is available + const dbConnectionId = metadata.connection_id + if (!this._connection.databaseId) { + this._connection.databaseId = dbConnectionId + } + } + + this._onSuccess(this._connection) + } +} diff --git a/src/internal/connection-delegate.js b/src/internal/connection-delegate.js new file mode 100644 index 000000000..510582d60 --- /dev/null +++ b/src/internal/connection-delegate.js @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Connection from './connection' + +export default class DelegateConnection extends Connection { + /** + * @param delegate {Connection} the delegated connection + * @param errorHandler {ConnectionErrorHandler} the error handler + */ + constructor (delegate, errorHandler) { + super(errorHandler) + + this._originalErrorHandler = delegate._errorHandler + delegate._errorHandler = this._errorHandler + + this._delegate = delegate + } + + get id () { + return this._delegate.id + } + + get databaseId () { + return this._delegate.databaseId + } + + set databaseId (value) { + this._delegate.databaseId = value + } + + isOpen () { + return this._delegate.isOpen() + } + + protocol () { + return this._delegate.protocol() + } + + get address () { + return this._delegate.address + } + + get version () { + return this._delegate.version + } + + set version (value) { + this._delegate.version = value + } + + get server () { + return this._delegate.server + } + + connect (userAgent, authToken) { + return this._delegate.connect(userAgent, authToken) + } + + write (message, observer, flush) { + return this._delegate.write(message, observer, flush) + } + + resetAndFlush () { + return this._delegate.resetAndFlush() + } + + close (cb = () => null) { + return this._delegate.close(cb) + } + + _release () { + this._delegate._errorHandler = this._originalErrorHandler + this._delegate._release() + } +} diff --git a/src/internal/connection-holder.js b/src/internal/connection-holder.js index bd6cbba6b..6a17596fa 100644 --- a/src/internal/connection-holder.js +++ b/src/internal/connection-holder.js @@ -116,7 +116,7 @@ export default class ConnectionHolder { /** * Return the current pooled connection instance to the connection pool. * We don't pool Session instances, to avoid users using the Session after they've called close. - * The `Session` object is just a thin wrapper around Connection anyway, so it makes little difference. + * The `Session` object is just a thin wrapper around ChannelConnection anyway, so it makes little difference. * @return {Promise} - promise resolved then connection is returned to the pool. * @private */ @@ -162,7 +162,7 @@ class EmptyConnectionHolder extends ConnectionHolder { function ignoreError (error) {} /** - * Connection holder that does not manage any connections. + * ChannelConnection holder that does not manage any connections. * @type {ConnectionHolder} */ export const EMPTY_CONNECTION_HOLDER = new EmptyConnectionHolder() diff --git a/src/internal/connection-provider-direct.js b/src/internal/connection-provider-direct.js index 9a465dfed..219018f7a 100644 --- a/src/internal/connection-provider-direct.js +++ b/src/internal/connection-provider-direct.js @@ -17,21 +17,16 @@ * limitations under the License. */ -import ConnectionProvider from './connection-provider' +import PooledConnectionProvider from './connection-provider-pooled' + +export default class DirectConnectionProvider extends PooledConnectionProvider { + constructor ({ id, config, log, address, userAgent, authToken }) { + super({ id, config, log, userAgent, authToken }) -export default class DirectConnectionProvider extends ConnectionProvider { - constructor (address, connectionPool, driverOnErrorCallback) { - super() this._address = address - this._connectionPool = connectionPool - this._driverOnErrorCallback = driverOnErrorCallback } acquireConnection (accessMode, database) { - const connectionPromise = this._connectionPool.acquire(this._address) - return this._withAdditionalOnErrorCallback( - connectionPromise, - this._driverOnErrorCallback - ) + return this._connectionPool.acquire(this._address) } } diff --git a/src/internal/connection-provider-pooled.js b/src/internal/connection-provider-pooled.js new file mode 100644 index 000000000..9a0987070 --- /dev/null +++ b/src/internal/connection-provider-pooled.js @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ChannelConnection from './connection-channel' +import Pool from './pool' +import PoolConfig from './pool-config' +import ConnectionErrorHandler from './connection-error-handler' +import { SERVICE_UNAVAILABLE } from '../error' +import ConnectionProvider from './connection-provider' + +export default class PooledConnectionProvider extends ConnectionProvider { + constructor ({ id, config, log, userAgent, authToken }) { + super() + + this._id = id + this._config = config + this._log = log + this._userAgent = userAgent + this._authToken = authToken + this._connectionPool = new Pool({ + create: this._createConnection.bind(this), + destroy: this._destroyConnection.bind(this), + validate: this._validateConnection.bind(this), + installIdleObserver: PooledConnectionProvider._installIdleObserverOnConnection.bind( + this + ), + removeIdleObserver: PooledConnectionProvider._removeIdleObserverOnConnection.bind( + this + ), + config: PoolConfig.fromDriverConfig(config), + log: this._log + }) + this._openConnections = {} + } + + _createConnectionErrorHandler () { + return new ConnectionErrorHandler(SERVICE_UNAVAILABLE) + } + + /** + * Create a new connection and initialize it. + * @return {Promise} promise resolved with a new connection or rejected when failed to connect. + * @access private + */ + _createConnection (address, release) { + const connection = ChannelConnection.create( + address, + this._config, + this._createConnectionErrorHandler(), + this._log + ) + connection._release = () => release(address, connection) + this._openConnections[connection.id] = connection + + return connection.connect(this._userAgent, this._authToken).catch(error => { + // let's destroy this connection + this._destroyConnection(connection) + // propagate the error because connection failed to connect / initialize + throw error + }) + } + + /** + * Check that a connection is usable + * @return {boolean} true if the connection is open + * @access private + **/ + _validateConnection (conn) { + if (!conn.isOpen()) { + return false + } + + const maxConnectionLifetime = this._config.maxConnectionLifetime + const lifetime = Date.now() - conn.creationTimestamp + return lifetime <= maxConnectionLifetime + } + + /** + * Dispose of a connection. + * @return {Connection} the connection to dispose. + * @access private + */ + _destroyConnection (conn) { + delete this._openConnections[conn.id] + conn.close() + } + + close () { + try { + // purge all idle connections in the connection pool + this._connectionPool.purgeAll() + } finally { + // then close all connections driver has ever created + // it is needed to close connections that are active right now and are acquired from the pool + for (let connectionId in this._openConnections) { + if (this._openConnections.hasOwnProperty(connectionId)) { + this._openConnections[connectionId].close() + } + } + } + } + + static _installIdleObserverOnConnection (conn, observer) { + conn._queueObserver(observer) + } + + static _removeIdleObserverOnConnection (conn) { + conn._updateCurrentObserver() + } +} diff --git a/src/internal/connection-provider-routing.js b/src/internal/connection-provider-routing.js index d02c9cd30..dec06b51f 100644 --- a/src/internal/connection-provider-routing.js +++ b/src/internal/connection-provider-routing.js @@ -24,9 +24,12 @@ import RoutingTable from './routing-table' import Rediscovery from './rediscovery' import RoutingUtil from './routing-util' import { HostNameResolver } from './node' -import ConnectionProvider from './connection-provider' import SingleConnectionProvider from './connection-provider-single' -import { VERSION_4_0_0 } from './server-version' +import { ServerVersion, VERSION_4_0_0 } from './server-version' +import PooledConnectionProvider from './connection-provider-pooled' +import ConnectionErrorHandler from './connection-error-handler' +import DelegateConnection from './connection-delegate' +import LeastConnectedLoadBalancingStrategy from './least-connected-load-balancing-strategy' const UNAUTHORIZED_ERROR_CODE = 'Neo.ClientError.Security.Unauthorized' const DATABASE_NOT_FOUND_ERROR_CODE = @@ -34,76 +37,138 @@ const DATABASE_NOT_FOUND_ERROR_CODE = const SYSTEM_DB_NAME = 'system' const DEFAULT_DB_NAME = '' -export default class RoutingConnectionProvider extends ConnectionProvider { - constructor ( +export default class RoutingConnectionProvider extends PooledConnectionProvider { + constructor ({ + id, address, routingContext, - connectionPool, - loadBalancingStrategy, hostNameResolver, - driverOnErrorCallback, - log - ) { - super() + config, + log, + userAgent, + authToken + }) { + super({ id, config, log, userAgent, authToken }) + this._seedRouter = address this._routingTables = {} this._rediscovery = new Rediscovery(new RoutingUtil(routingContext)) - this._connectionPool = connectionPool - this._driverOnErrorCallback = driverOnErrorCallback - this._loadBalancingStrategy = loadBalancingStrategy + this._loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy( + this._connectionPool + ) this._hostNameResolver = hostNameResolver this._dnsResolver = new HostNameResolver() this._log = log this._useSeedRouter = true } - acquireConnection (accessMode, database) { - const connectionPromise = this._freshRoutingTable( - accessMode, - database || DEFAULT_DB_NAME - ).then(routingTable => { - if (accessMode === READ) { - const address = this._loadBalancingStrategy.selectReader( - routingTable.readers - ) - return this._acquireConnectionToServer(address, 'read', routingTable) - } else if (accessMode === WRITE) { - const address = this._loadBalancingStrategy.selectWriter( - routingTable.writers - ) - return this._acquireConnectionToServer(address, 'write', routingTable) - } else { - throw newError('Illegal mode ' + accessMode) - } - }) - return this._withAdditionalOnErrorCallback( - connectionPromise, - this._driverOnErrorCallback + _createConnectionErrorHandler () { + // connection errors mean SERVICE_UNAVAILABLE for direct driver but for routing driver they should only + // result in SESSION_EXPIRED because there might still exist other servers capable of serving the request + return new ConnectionErrorHandler(SESSION_EXPIRED) + } + + _handleUnavailability (error, address, database) { + this._log.warn( + `Routing driver ${ + this._id + } will forget ${address} for database '${database}' because of an error ${ + error.code + } '${error.message}'` ) + this.forget(address, database || '') + return error } - forget (address) { - Object.values(this._routingTables).forEach(routingTable => - routingTable.forget(address) + _handleWriteFailure (error, address, database) { + this._log.warn( + `Routing driver ${ + this._id + } will forget writer ${address} for database '${database}' because of an error ${ + error.code + } '${error.message}'` + ) + this.forgetWriter(address, database || '') + return newError( + 'No longer possible to write to server at ' + address, + SESSION_EXPIRED ) - this._connectionPool.purge(address) } - forgetWriter (address) { - Object.values(this._routingTables).forEach(routingTable => - routingTable.forgetWriter(address) + acquireConnection (accessMode, database) { + const databaseSpecificErrorHandler = new ConnectionErrorHandler( + SESSION_EXPIRED, + (error, address) => this._handleUnavailability(error, address, database), + (error, address) => this._handleWriteFailure(error, address, database) ) + + return this._freshRoutingTable(accessMode, database || DEFAULT_DB_NAME) + .then(routingTable => { + let name + let address + + if (accessMode === READ) { + address = this._loadBalancingStrategy.selectReader( + routingTable.readers + ) + name = 'read' + } else if (accessMode === WRITE) { + address = this._loadBalancingStrategy.selectWriter( + routingTable.writers + ) + name = 'write' + } else { + throw newError('Illegal mode ' + accessMode) + } + + if (!address) { + throw newError( + `Failed to obtain connection towards ${name} server. Known routing table is: ${routingTable}`, + SESSION_EXPIRED + ) + } + + return this._acquireConnectionToServer( + address, + name, + routingTable + ).catch(error => { + const transformed = databaseSpecificErrorHandler.handleAndTransformError( + error, + address + ) + throw transformed + }) + }) + .then( + connection => + new DelegateConnection(connection, databaseSpecificErrorHandler) + ) } - _acquireConnectionToServer (address, serverName, routingTable) { - if (!address) { - return Promise.reject( - newError( - `Failed to obtain connection towards ${serverName} server. Known routing table is: ${routingTable}`, - SESSION_EXPIRED - ) + forget (address, database) { + if (database || database === '') { + this._routingTables[database].forget(address) + } else { + Object.values(this._routingTables).forEach(routingTable => + routingTable.forget(address) ) } + + this._connectionPool.purge(address) + } + + forgetWriter (address, database) { + if (database || database === '') { + this._routingTables[database].forgetWriter(address) + } else { + Object.values(this._routingTables).forEach(routingTable => + routingTable.forgetWriter(address) + ) + } + } + + _acquireConnectionToServer (address, serverName, routingTable) { return this._connectionPool.acquire(address) } @@ -294,7 +359,8 @@ export default class RoutingConnectionProvider extends ConnectionProvider { .then(connection => { const connectionProvider = new SingleConnectionProvider(connection) - if (connection.version().compareTo(VERSION_4_0_0) < 0) { + const version = ServerVersion.fromString(connection.version) + if (version.compareTo(VERSION_4_0_0) < 0) { return new Session({ mode: WRITE, connectionProvider }) } diff --git a/src/internal/connection-provider.js b/src/internal/connection-provider.js index cad587e67..515390647 100644 --- a/src/internal/connection-provider.js +++ b/src/internal/connection-provider.js @@ -19,16 +19,10 @@ export default class ConnectionProvider { acquireConnection (accessMode, database) { - throw new Error('Abstract function') + throw new Error('not implemented') } - _withAdditionalOnErrorCallback (connectionPromise, driverOnErrorCallback) { - // install error handler from the driver on the connection promise; this callback is installed separately - // so that it does not handle errors, instead it is just an additional error reporting facility. - connectionPromise.catch(error => { - driverOnErrorCallback(error) - }) - // return the original connection promise - return connectionPromise + close () { + throw new Error('not implemented') } } diff --git a/src/internal/connection.js b/src/internal/connection.js index 9cbf832cc..5383beb76 100644 --- a/src/internal/connection.js +++ b/src/internal/connection.js @@ -17,195 +17,70 @@ * limitations under the License. */ -import { Channel } from './node' -import { Chunker, Dechunker } from './chunking' -import { newError, PROTOCOL_ERROR } from '../error' -import ChannelConfig from './channel-config' -import { ServerVersion, VERSION_3_2_0 } from './server-version' -import ProtocolHandshaker from './protocol-handshaker' - -// Signature bytes for each response message type -const SUCCESS = 0x70 // 0111 0000 // SUCCESS -const RECORD = 0x71 // 0111 0001 // RECORD -const IGNORED = 0x7e // 0111 1110 // IGNORED -const FAILURE = 0x7f // 0111 1111 // FAILURE - -function NO_OP () {} - -const NO_OP_OBSERVER = { - onNext: NO_OP, - onCompleted: NO_OP, - onError: NO_OP -} - -let idGenerator = 0 - export default class Connection { /** - * @constructor - * @param {Channel} channel - channel with a 'write' function and a 'onmessage' callback property. - * @param {ConnectionErrorHandler} errorHandler the error handler. - * @param {ServerAddress} address - the server address to connect to. - * @param {Logger} log - the configured logger. - * @param {boolean} disableLosslessIntegers if this connection should convert all received integers to native JS numbers. + * @param {ConnectionErrorHandler} errorHandler the error handler */ - constructor ( - channel, - errorHandler, - address, - log, - disableLosslessIntegers = false - ) { - this.id = idGenerator++ - this.address = address - this.server = { address: address.asHostPort() } - this.creationTimestamp = Date.now() + constructor (errorHandler) { this._errorHandler = errorHandler - this._disableLosslessIntegers = disableLosslessIntegers - this._pendingObservers = [] - this._currentObserver = undefined - this._ch = channel - this._dechunker = new Dechunker() - this._chunker = new Chunker(channel) - this._log = log - - // connection from the database, returned in response for HELLO message and might not be available - this._dbConnectionId = null - - // bolt protocol is initially not initialized - this._protocol = null + } - // error extracted from a FAILURE message - this._currentFailure = null + get id () { + throw new Error('not implemented') + } - // Set to true on fatal errors, to get this out of connection pool. - this._isBroken = false + get databaseId () { + throw new Error('not implemented') + } - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} created towards ${address}`) - } + set databaseId (value) { + throw new Error('not implemented') } /** - * Crete new connection to the provided address. Returned connection is not connected. - * @param {ServerAddress} address - the Bolt endpoint to connect to. - * @param {object} config - this driver configuration. - * @param {ConnectionErrorHandler} errorHandler - the error handler for connection errors. - * @param {Logger} log - configured logger. - * @return {Connection} - new connection. + * @returns {boolean} whether this connection is in a working condition */ - static create (address, config, errorHandler, log) { - const channelConfig = new ChannelConfig( - address, - config, - errorHandler.errorCode() - ) - return new Connection( - new Channel(channelConfig), - errorHandler, - address, - log, - config.disableLosslessIntegers - ) + isOpen () { + throw new Error('not implemented') } /** - * Connect to the target address, negotiate Bolt protocol and send initialization message. - * @param {string} userAgent the user agent for this driver. - * @param {object} authToken the object containing auth information. - * @return {Promise} promise resolved with the current connection if connection is successful. Rejected promise otherwise. + * @returns {BoltProtocol} the underlying bolt protocol assigned to this connection */ - connect (userAgent, authToken) { - return this._negotiateProtocol().then(() => - this._initialize(userAgent, authToken) - ) + protocol () { + throw new Error('not implemented') } /** - * Execute Bolt protocol handshake to initialize the protocol version. - * @return {Promise} promise resolved with the current connection if handshake is successful. Rejected promise otherwise. + * @returns {ServerAddress} the server address this connection is opened against */ - _negotiateProtocol () { - const protocolHandshaker = new ProtocolHandshaker( - this, - this._ch, - this._chunker, - this._disableLosslessIntegers, - this._log - ) - - return new Promise((resolve, reject) => { - const handshakeErrorHandler = error => { - this._handleFatalError(error) - reject(error) - } - - this._ch.onerror = handshakeErrorHandler.bind(this) - if (this._ch._error) { - // channel is already broken - handshakeErrorHandler(this._ch._error) - } - - this._ch.onmessage = buffer => { - try { - // read the response buffer and initialize the protocol - this._protocol = protocolHandshaker.createNegotiatedProtocol(buffer) - - // reset the error handler to just handle errors and forget about the handshake promise - this._ch.onerror = this._handleFatalError.bind(this) - - // Ok, protocol running. Simply forward all messages to the dechunker - this._ch.onmessage = buf => this._dechunker.write(buf) - - // setup dechunker to dechunk messages and forward them to the message handler - this._dechunker.onmessage = buf => { - this._handleMessage(this._protocol.unpacker().unpack(buf)) - } - // forward all pending bytes to the dechunker - if (buffer.hasRemaining()) { - this._dechunker.write(buffer.readSlice(buffer.remaining())) - } - - resolve(this) - } catch (e) { - this._handleFatalError(e) - reject(e) - } - } - - protocolHandshaker.writeHandshakeRequest() - }) + get address () { + throw new Error('not implemented') } /** - * Perform protocol-specific initialization which includes authentication. - * @param {string} userAgent the user agent for this driver. - * @param {object} authToken the object containing auth information. - * @return {Promise} promise resolved with the current connection if initialization is successful. Rejected promise otherwise. + * @returns {ServerVersion} the version of the server this connection is connected to */ - _initialize (userAgent, authToken) { - return new Promise((resolve, reject) => { - const observer = new InitializationObserver(this, resolve, reject) - this._protocol.initialize(userAgent, authToken, observer) - }) + get version () { + throw new Error('not implemented') } - /** - * Get the Bolt protocol for the connection. - * @return {BoltProtocol} the protocol. - */ - protocol () { - return this._protocol + set version (value) { + throw new Error('not implemented') + } + + get server () { + throw new Error('not implemented') } /** - * Get the version of the connected server. - * Available only after initialization - * - * @returns {ServerVersion} version + * Connect to the target address, negotiate Bolt protocol and send initialization message. + * @param {string} userAgent the user agent for this driver. + * @param {object} authToken the object containing auth information. + * @return {Promise} promise resolved with the current connection if connection is successful. Rejected promise otherwise. */ - version () { - return ServerVersion.fromString(this.server.version) + connect (userAgent, authToken) { + throw new Error('not implemented') } /** @@ -215,125 +90,7 @@ export default class Connection { * @param {boolean} flush `true` if flush should happen after the message is written to the buffer. */ write (message, observer, flush) { - const queued = this._queueObserver(observer) - - if (queued) { - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} C: ${message}`) - } - - this._protocol - .packer() - .packStruct( - message.signature, - message.fields.map(field => this._packable(field)), - err => this._handleFatalError(err) - ) - - this._chunker.messageBoundary() - - if (flush) { - this._chunker.flush() - } - } - } - - /** - * "Fatal" means the connection is dead. Only call this if something - * happens that cannot be recovered from. This will lead to all subscribers - * failing, and the connection getting ejected from the session pool. - * - * @param error an error object, forwarded to all current and future subscribers - */ - _handleFatalError (error) { - this._isBroken = true - this._error = this._errorHandler.handleAndTransformError( - error, - this.address - ) - - if (this._log.isErrorEnabled()) { - this._log.error( - `${this} experienced a fatal error ${JSON.stringify(this._error)}` - ) - } - - if (this._currentObserver && this._currentObserver.onError) { - this._currentObserver.onError(this._error) - } - while (this._pendingObservers.length > 0) { - let observer = this._pendingObservers.shift() - if (observer && observer.onError) { - observer.onError(this._error) - } - } - } - - _handleMessage (msg) { - if (this._isBroken) { - // ignore all incoming messages when this connection is broken. all previously pending observers failed - // with the fatal error. all future observers will fail with same fatal error. - return - } - - const payload = msg.fields[0] - - switch (msg.signature) { - case RECORD: - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} S: RECORD ${JSON.stringify(msg)}`) - } - this._currentObserver.onNext(payload) - break - case SUCCESS: - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} S: SUCCESS ${JSON.stringify(msg)}`) - } - try { - const metadata = this._protocol.transformMetadata(payload) - this._currentObserver.onCompleted(metadata) - } finally { - this._updateCurrentObserver() - } - break - case FAILURE: - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} S: FAILURE ${JSON.stringify(msg)}`) - } - try { - const error = newError(payload.message, payload.code) - this._currentFailure = this._errorHandler.handleAndTransformError( - error, - this.address - ) - this._currentObserver.onError(this._currentFailure) - } finally { - this._updateCurrentObserver() - // Things are now broken. Pending observers will get FAILURE messages routed until we are done handling this failure. - this._resetOnFailure() - } - break - case IGNORED: - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} S: IGNORED ${JSON.stringify(msg)}`) - } - try { - if (this._currentFailure && this._currentObserver.onError) { - this._currentObserver.onError(this._currentFailure) - } else if (this._currentObserver.onError) { - this._currentObserver.onError( - newError('Ignored either because of an error or RESET') - ) - } - } finally { - this._updateCurrentObserver() - } - break - default: - this._handleFatalError( - newError('Unknown Bolt protocol message: ' + msg) - ) - } + throw new Error('not implemented') } /** @@ -341,79 +98,7 @@ export default class Connection { * @return {Promise} promise resolved when SUCCESS-message response arrives, or failed when other response messages arrives. */ resetAndFlush () { - return new Promise((resolve, reject) => { - this._protocol.reset({ - onNext: record => { - const neo4jError = this._handleProtocolError( - 'Received RECORD as a response for RESET: ' + JSON.stringify(record) - ) - reject(neo4jError) - }, - onError: error => { - if (this._isBroken) { - // handling a fatal error, no need to raise a protocol violation - reject(error) - } else { - const neo4jError = this._handleProtocolError( - 'Received FAILURE as a response for RESET: ' + error - ) - reject(neo4jError) - } - }, - onCompleted: () => { - resolve() - } - }) - }) - } - - _resetOnFailure () { - this._protocol.reset({ - onNext: record => { - this._handleProtocolError( - 'Received RECORD as a response for RESET: ' + JSON.stringify(record) - ) - }, - // clear the current failure when response for RESET is received - onError: () => { - this._currentFailure = null - }, - onCompleted: () => { - this._currentFailure = null - } - }) - } - - _queueObserver (observer) { - if (this._isBroken) { - if (observer && observer.onError) { - observer.onError(this._error) - } - return false - } - observer = observer || NO_OP_OBSERVER - observer.onCompleted = observer.onCompleted || NO_OP - observer.onError = observer.onError || NO_OP - observer.onNext = observer.onNext || NO_OP - if (this._currentObserver === undefined) { - this._currentObserver = observer - } else { - this._pendingObservers.push(observer) - } - return true - } - - /* - * Pop next pending observer form the list of observers and make it current observer. - * @protected - */ - _updateCurrentObserver () { - this._currentObserver = this._pendingObservers.shift() - } - - /** Check if this connection is in working condition */ - isOpen () { - return !this._isBroken && this._ch._open + throw new Error('not implemented') } /** @@ -421,86 +106,20 @@ export default class Connection { * @param {function} cb - Function to call on close. */ close (cb = () => null) { - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} closing`) - } - - if (this._protocol && this.isOpen()) { - // protocol has been initialized and this connection is healthy - // notify the database about the upcoming close of the connection - this._protocol.prepareToClose(NO_OP_OBSERVER) - } - - this._ch.close(() => { - if (this._log.isDebugEnabled()) { - this._log.debug(`${this} closed`) - } - cb() - }) - } - - toString () { - const dbConnectionId = this._dbConnectionId || '' - return `Connection [${this.id}][${dbConnectionId}]` - } - - _packable (value) { - return this._protocol - .packer() - .packable(value, err => this._handleFatalError(err)) - } - - _handleProtocolError (message) { - this._currentFailure = null - this._updateCurrentObserver() - const error = newError(message, PROTOCOL_ERROR) - this._handleFatalError(error) - return error - } -} - -class InitializationObserver { - constructor (connection, onSuccess, onError) { - this._connection = connection - this._onSuccess = onSuccess - this._onError = onError - } - - onNext (record) { - this.onError( - newError('Received RECORD when initializing ' + JSON.stringify(record)) - ) - } - - onError (error) { - this._connection._updateCurrentObserver() // make sure this exact observer will not be called again - this._connection._handleFatalError(error) // initialization errors are fatal - - this._onError(error) + throw new Error('not implemented') } - onCompleted (metadata) { - if (metadata) { - // read server version from the response metadata, if it is available - const serverVersion = metadata.server - if (!this._connection.server.version) { - this._connection.server.version = serverVersion - const version = ServerVersion.fromString(serverVersion) - if (version.compareTo(VERSION_3_2_0) < 0) { - this._connection - .protocol() - .packer() - .disableByteArrays() - } - } - - // read database connection id from the response metadata, if it is available - const dbConnectionId = metadata.connection_id - if (!this._connection._dbConnectionId) { - this._connection._dbConnectionId = dbConnectionId - } + /** + * + * @param error + * @param address + * @returns {Neo4jError|*} + */ + handleAndTransformError (error, address) { + if (this._errorHandler) { + return this._errorHandler.handleAndTransformError(error, address) } - this._onSuccess(this._connection) + return error } } diff --git a/src/internal/routing-util.js b/src/internal/routing-util.js index 821dd1a44..8ab0ec835 100644 --- a/src/internal/routing-util.js +++ b/src/internal/routing-util.js @@ -19,10 +19,9 @@ import { newError, PROTOCOL_ERROR, SERVICE_UNAVAILABLE } from '../error' import Integer, { int } from '../integer' -import { VERSION_4_0_0 } from './server-version' +import { ServerVersion, VERSION_4_0_0 } from './server-version' import Bookmark from './bookmark' import TxConfig from './tx-config' -import { ACCESS_MODE_READ, ACCESS_MODE_WRITE } from './constants' import ServerAddress from './server-address' const CONTEXT = 'context' @@ -134,12 +133,11 @@ export default class RoutingUtil { _callAvailableRoutingProcedure (session, database) { return session._run(null, null, (connection, streamObserver) => { - const serverVersion = connection.version() - let query let params - if (serverVersion.compareTo(VERSION_4_0_0) >= 0) { + const version = ServerVersion.fromString(connection.version) + if (version.compareTo(VERSION_4_0_0) >= 0) { query = CALL_GET_ROUTING_TABLE_MULTI_DB params = { context: this._routingContext, diff --git a/src/internal/server-version.js b/src/internal/server-version.js index 3508e6df4..1179c31ed 100644 --- a/src/internal/server-version.js +++ b/src/internal/server-version.js @@ -30,11 +30,14 @@ class ServerVersion { * @param {number} major the major version number. * @param {number} minor the minor version number. * @param {number} patch the patch version number. + * @param {string} the original version string */ - constructor (major, minor, patch) { + constructor (major, minor, patch, originalVersionString) { this.major = major this.minor = minor this.patch = patch + + this._originalVersionString = originalVersionString } /** @@ -78,7 +81,7 @@ class ServerVersion { const minor = parseIntStrict(version[3]) const patch = parseIntStrict(version[4] || 0) - return new ServerVersion(major, minor, patch) + return new ServerVersion(major, minor, patch, versionStr) } /** @@ -98,6 +101,14 @@ class ServerVersion { } return result } + + toString () { + if (this._originalVersionString) { + return this._originalVersionString + } + + return `${this.major}.${this.minor}.${this.patch}` + } } function parseIntStrict (str, name) { @@ -112,17 +123,20 @@ function compareInts (x, y) { return x < y ? -1 : x === y ? 0 : 1 } -const VERSION_3_1_0 = new ServerVersion(3, 1, 0) -const VERSION_3_2_0 = new ServerVersion(3, 2, 0) -const VERSION_3_4_0 = new ServerVersion(3, 4, 0) -const VERSION_3_5_0 = new ServerVersion(3, 5, 0) -const VERSION_4_0_0 = new ServerVersion(4, 0, 0) +const VERSION_3_2_0 = ServerVersion.fromString('Neo4j/3.2.0') +const VERSION_3_4_0 = ServerVersion.fromString('Neo4j/3.4.0') +const VERSION_3_5_0 = ServerVersion.fromString('Neo4j/3.5.0') +const VERSION_4_0_0 = ServerVersion.fromString('Neo4j/4.0.0') const maxVer = Number.MAX_SAFE_INTEGER -const VERSION_IN_DEV = new ServerVersion(maxVer, maxVer, maxVer) +const VERSION_IN_DEV = new ServerVersion( + maxVer, + maxVer, + maxVer, + NEO4J_IN_DEV_VERSION_STRING +) export { ServerVersion, - VERSION_3_1_0, VERSION_3_2_0, VERSION_3_4_0, VERSION_3_5_0, diff --git a/src/routing-driver.js b/src/routing-driver.js index 514013a48..a822637e8 100644 --- a/src/routing-driver.js +++ b/src/routing-driver.js @@ -40,67 +40,17 @@ class RoutingDriver extends Driver { ) } - _createConnectionProvider (address, connectionPool, driverOnErrorCallback) { - const loadBalancingStrategy = RoutingDriver._createLoadBalancingStrategy( - this._config, - connectionPool - ) - const resolver = createHostNameResolver(this._config) - return new RoutingConnectionProvider( - address, - this._routingContext, - connectionPool, - loadBalancingStrategy, - resolver, - driverOnErrorCallback, - this._log - ) - } - - _createConnectionErrorHandler () { - // connection errors mean SERVICE_UNAVAILABLE for direct driver but for routing driver they should only - // result in SESSION_EXPIRED because there might still exist other servers capable of serving the request - return new ConnectionErrorHandler( - SESSION_EXPIRED, - (error, address) => this._handleUnavailability(error, address), - (error, address) => this._handleWriteFailure(error, address) - ) - } - - _handleUnavailability (error, address) { - this._log.warn( - `Routing driver ${this._id} will forget ${address} because of an error ${ - error.code - } '${error.message}'` - ) - this._connectionProvider.forget(address) - return error - } - - _handleWriteFailure (error, address) { - this._log.warn( - `Routing driver ${ - this._id - } will forget writer ${address} because of an error ${error.code} '${ - error.message - }'` - ) - this._connectionProvider.forgetWriter(address) - return newError( - 'No longer possible to write to server at ' + address, - SESSION_EXPIRED - ) - } - - /** - * Create new load balancing strategy based on the config. - * @param {object} config the user provided config. - * @param {Pool} connectionPool the connection pool for this driver. - * @return {LoadBalancingStrategy} new strategy. - * @private - */ - static _createLoadBalancingStrategy (config, connectionPool) { - return new LeastConnectedLoadBalancingStrategy(connectionPool) + _createConnectionProvider (address, userAgent, authToken) { + return new RoutingConnectionProvider({ + id: this._id, + address: address, + routingContext: this._routingContext, + hostNameResolver: createHostNameResolver(this._config), + config: this._config, + log: this._log, + userAgent: userAgent, + authToken: authToken + }) } } diff --git a/src/session.js b/src/session.js index 08339508b..94ef91982 100644 --- a/src/session.js +++ b/src/session.js @@ -84,7 +84,7 @@ class Session { /** * Run Cypher statement - * Could be called with a statement object i.e.: `{text: "MATCH ...", parameters: {param: 1}}` + * Could be called with a statement object i.e.: `{text: "MATCH ...", prameters: {param: 1}}` * or with the statement and parameters as separate arguments. * @param {mixed} statement - Cypher statement to execute * @param {Object} parameters - Map with parameters to use in statement diff --git a/test/auth.test.js b/test/auth.test.js index 976b855d0..bca76186e 100644 --- a/test/auth.test.js +++ b/test/auth.test.js @@ -19,7 +19,7 @@ import neo4j from '../src' -describe('auth', () => { +describe('#unit auth', () => { it('should use correct username and password in basic auth', () => { const token = neo4j.auth.basic('cat', 'dog') expect(token).toEqual({ diff --git a/test/bolt-v3.test.js b/test/bolt-v3.test.js index 3518c4fed..6ff546eec 100644 --- a/test/bolt-v3.test.js +++ b/test/bolt-v3.test.js @@ -31,7 +31,7 @@ const INVALID_METADATA_VALUES = [ () => 'hello world' ] -describe('Bolt V3 API', () => { +describe('#integration Bolt V3 API', () => { let driver let session let serverVersion diff --git a/test/bolt-v4.test.js b/test/bolt-v4.test.js index 5a160bfb6..b76e196b7 100644 --- a/test/bolt-v4.test.js +++ b/test/bolt-v4.test.js @@ -21,7 +21,7 @@ import neo4j from '../src' import sharedNeo4j from './internal/shared-neo4j' import { ServerVersion, VERSION_4_0_0 } from '../src/internal/server-version' -describe('Bolt V4 API', () => { +describe('#integration Bolt V4 API', () => { let driver let session let serverVersion diff --git a/test/driver.test.js b/test/driver.test.js index 9cba74cb1..90edee84e 100644 --- a/test/driver.test.js +++ b/test/driver.test.js @@ -25,14 +25,10 @@ import { DEFAULT_ACQUISITION_TIMEOUT, DEFAULT_MAX_SIZE } from '../src/internal/pool-config' -import { - ServerVersion, - VERSION_3_1_0, - VERSION_4_0_0 -} from '../src/internal/server-version' +import { ServerVersion, VERSION_4_0_0 } from '../src/internal/server-version' import testUtils from './internal/test-utils' -describe('driver', () => { +describe('#integration driver', () => { let clock let driver let serverVersion @@ -442,11 +438,6 @@ describe('driver', () => { }) function testIPv6Connection (url, done) { - if (serverVersion.compareTo(VERSION_3_1_0) < 0) { - // IPv6 listen address only supported starting from neo4j 3.1, so let's ignore the rest - done() - } - driver = neo4j.driver(url, sharedNeo4j.authToken) const session = driver.session() diff --git a/test/examples.test.js b/test/examples.test.js index 91e375d17..92b08f27a 100644 --- a/test/examples.test.js +++ b/test/examples.test.js @@ -27,7 +27,7 @@ import sharedNeo4j from './internal/shared-neo4j' * DO NOT add tests to this file that are not for that exact purpose. * DO NOT modify these tests without ensuring they remain consistent with the equivalent examples in other drivers */ -describe('examples', () => { +describe('#integration examples', () => { let driverGlobal let console let originalTimeout diff --git a/test/integer.test.js b/test/integer.test.js index 71458a41e..5d4f5cf41 100644 --- a/test/integer.test.js +++ b/test/integer.test.js @@ -23,7 +23,7 @@ import Integer from '../src/integer' const int = neo4j.int const integer = neo4j.integer -describe('Integer', () => { +describe('#unit Integer', () => { it('exposes inSafeRange function', () => { expect(integer.inSafeRange(int('9007199254740991'))).toBeTruthy() expect(integer.inSafeRange(int('9007199254740992'))).toBeFalsy() diff --git a/test/internal/bolt-protocol-v1.test.js b/test/internal/bolt-protocol-v1.test.js index d17b5ce14..8d1e9c73f 100644 --- a/test/internal/bolt-protocol-v1.test.js +++ b/test/internal/bolt-protocol-v1.test.js @@ -24,7 +24,7 @@ import TxConfig from '../../src/internal/tx-config' import { WRITE } from '../../src/driver' import utils from './test-utils' -describe('BoltProtocolV1', () => { +describe('#unit BoltProtocolV1', () => { beforeEach(() => { jasmine.addMatchers(utils.matchers) }) diff --git a/test/internal/bolt-protocol-v3.test.js b/test/internal/bolt-protocol-v3.test.js index dc4d2b6ad..d26e13610 100644 --- a/test/internal/bolt-protocol-v3.test.js +++ b/test/internal/bolt-protocol-v3.test.js @@ -24,7 +24,7 @@ import Bookmark from '../../src/internal/bookmark' import TxConfig from '../../src/internal/tx-config' import { WRITE } from '../../src/driver' -describe('BoltProtocolV3', () => { +describe('#unit BoltProtocolV3', () => { beforeEach(() => { jasmine.addMatchers(utils.matchers) }) diff --git a/test/internal/bolt-protocol-v4.test.js b/test/internal/bolt-protocol-v4.test.js index c0d0980ff..6868e59b9 100644 --- a/test/internal/bolt-protocol-v4.test.js +++ b/test/internal/bolt-protocol-v4.test.js @@ -24,7 +24,7 @@ import Bookmark from '../../src/internal/bookmark' import TxConfig from '../../src/internal/tx-config' import { WRITE } from '../../src/driver' -describe('BoltProtocolV4', () => { +describe('#unit BoltProtocolV4', () => { beforeEach(() => { jasmine.addMatchers(utils.matchers) }) diff --git a/test/internal/bolt-stub.js b/test/internal/bolt-stub.js index fd8acb2c2..be20ac4ee 100644 --- a/test/internal/bolt-stub.js +++ b/test/internal/bolt-stub.js @@ -36,7 +36,8 @@ class UnsupportedBoltStub { } } -const verbose = false // for debugging purposes +const verbose = + (process.env['NEOLOGLEVEL'] || 'error').toLowerCase() === 'debug' // for debugging purposes class SupportedBoltStub extends UnsupportedBoltStub { constructor () { diff --git a/test/internal/bookmark.test.js b/test/internal/bookmark.test.js index 1b2bdd98d..1bd097a1a 100644 --- a/test/internal/bookmark.test.js +++ b/test/internal/bookmark.test.js @@ -18,7 +18,7 @@ */ import Bookmark from '../../src/internal/bookmark' -describe('Bookmark', () => { +describe('#unit Bookmark', () => { it('should be possible to construct bookmark from string', () => { const bookmark = new Bookmark('neo4j:bookmark:v1:tx412') diff --git a/test/internal/browser/browser-channel.test.js b/test/internal/browser/browser-channel.test.js index 1a0a632d7..0ad05d3bb 100644 --- a/test/internal/browser/browser-channel.test.js +++ b/test/internal/browser/browser-channel.test.js @@ -25,7 +25,7 @@ import { ENCRYPTION_OFF, ENCRYPTION_ON } from '../../../src/internal/util' import ServerAddress from '../../../src/internal/server-address' /* eslint-disable no-global-assign */ -describe('WebSocketChannel', () => { +describe('#unit WebSocketChannel', () => { let OriginalWebSocket let webSocketChannel let originalConsoleWarn diff --git a/test/internal/browser/browser-host-name-resolver.test.js b/test/internal/browser/browser-host-name-resolver.test.js index ecfb2439b..817a595ff 100644 --- a/test/internal/browser/browser-host-name-resolver.test.js +++ b/test/internal/browser/browser-host-name-resolver.test.js @@ -19,7 +19,7 @@ import BrowserHostNameResolver from '../../../src/internal/browser/browser-host-name-resolver' -describe('BrowserHostNameResolver', () => { +describe('#unit BrowserHostNameResolver', () => { it('should resolve given address to itself', done => { const seedRouter = 'localhost' const resolver = new BrowserHostNameResolver() diff --git a/test/internal/buf.test.js b/test/internal/buf.test.js index 56277e9ee..89014f8d9 100644 --- a/test/internal/buf.test.js +++ b/test/internal/buf.test.js @@ -21,7 +21,7 @@ import { Unpacker } from '../../src/internal/packstream-v1' import CombinedBuffer from '../../src/internal/buf/combined-buf' import { alloc, utf8 } from '../../src/internal/node' -describe('buffers', () => { +describe('#unit Buffers', () => { it('should have helpful toString', () => { // Given const b = alloc(4) diff --git a/test/internal/channel-config.test.js b/test/internal/channel-config.test.js index 8a28ff6d9..e80164061 100644 --- a/test/internal/channel-config.test.js +++ b/test/internal/channel-config.test.js @@ -22,7 +22,7 @@ import { SERVICE_UNAVAILABLE } from '../../src/error' import { ENCRYPTION_OFF, ENCRYPTION_ON } from '../../src/internal/util' import ServerAddress from '../../src/internal/server-address' -describe('ChannelConfig', () => { +describe('#unit ChannelConfig', () => { it('should respect given Url', () => { const address = ServerAddress.fromUrl('bolt://neo4j.com:4242') diff --git a/test/internal/chunking.test.js b/test/internal/chunking.test.js index 2c807ecb5..b45b4e8ce 100644 --- a/test/internal/chunking.test.js +++ b/test/internal/chunking.test.js @@ -21,7 +21,7 @@ import { Chunker, Dechunker } from '../../src/internal/chunking' import { alloc } from '../../src/internal/node' import DummyChannel from './dummy-channel' -describe('Chunker', () => { +describe('#unit Chunker', () => { it('should chunk simple data', () => { // Given const ch = new DummyChannel() diff --git a/test/internal/connection.test.js b/test/internal/connection-channel.test.js similarity index 97% rename from test/internal/connection.test.js rename to test/internal/connection-channel.test.js index 1db852ac6..9b5493cb4 100644 --- a/test/internal/connection.test.js +++ b/test/internal/connection-channel.test.js @@ -18,7 +18,7 @@ */ import DummyChannel from './dummy-channel' -import Connection from '../../src/internal/connection' +import ChannelConnection from '../../src/internal/connection-channel' import { Packer } from '../../src/internal/packstream-v1' import { Chunker } from '../../src/internal/chunking' import { alloc } from '../../src/internal/node' @@ -40,7 +40,7 @@ const SUCCESS_MESSAGE = { signature: 0x70, fields: [{}] } const FAILURE_MESSAGE = { signature: 0x7f, fields: [newError('Hello')] } const RECORD_MESSAGE = { signature: 0x71, fields: [{ value: 'Hello' }] } -describe('Connection', () => { +describe('#integration ChannelConnection', () => { let clock let connection @@ -108,7 +108,7 @@ describe('Connection', () => { it('should write protocol handshake', () => { const channel = new DummyChannel() - connection = new Connection( + connection = new ChannelConnection( channel, new ConnectionErrorHandler(SERVICE_UNAVAILABLE), ServerAddress.fromUrl('localhost:7687'), @@ -148,7 +148,7 @@ describe('Connection', () => { it('should convert failure messages to errors', done => { const channel = new DummyChannel() - connection = new Connection( + connection = new ChannelConnection( channel, new ConnectionErrorHandler(SERVICE_UNAVAILABLE), ServerAddress.fromUrl('localhost:7687'), @@ -202,9 +202,7 @@ describe('Connection', () => { .connect('mydriver/0.0.0', basicAuthToken()) .then(initializedConnection => { expect(initializedConnection).toBe(connection) - const serverVersion = ServerVersion.fromString( - connection.server.version - ) + const serverVersion = ServerVersion.fromString(connection.version) expect(serverVersion).toBeDefined() done() }) @@ -373,7 +371,7 @@ describe('Connection', () => { } ) - connection = Connection.create( + connection = ChannelConnection.create( ServerAddress.fromUrl('bolt://localhost'), {}, errorHandler, @@ -406,9 +404,7 @@ describe('Connection', () => { expect(messages.length).toBeGreaterThan(0) expect(messages[0].signature).toEqual(0x01) // first message is either INIT or HELLO - const serverVersion = ServerVersion.fromString( - connection.server.version - ) + const serverVersion = ServerVersion.fromString(connection.version) if (serverVersion.compareTo(VERSION_3_5_0) >= 0) { expect(messages[messages.length - 1].signature).toEqual(0x02) // last message is GOODBYE in V3 } @@ -520,7 +516,7 @@ describe('Connection', () => { * @return {Connection} */ function createConnection (url, config, errorCode = null) { - return Connection.create( + return ChannelConnection.create( ServerAddress.fromUrl(url), config || {}, new ConnectionErrorHandler(errorCode || SERVICE_UNAVAILABLE), diff --git a/test/internal/connection-error-handler.test.js b/test/internal/connection-error-handler.test.js index 2f0732664..9265086ac 100644 --- a/test/internal/connection-error-handler.test.js +++ b/test/internal/connection-error-handler.test.js @@ -21,7 +21,7 @@ import ConnectionErrorHandler from '../../src/internal/connection-error-handler' import { newError, SERVICE_UNAVAILABLE, SESSION_EXPIRED } from '../../src/error' import ServerAddress from '../../src/internal/server-address' -describe('ConnectionErrorHandler', () => { +describe('#unit ConnectionErrorHandler', () => { it('should return error code', () => { const code = 'Neo4j.Error.Hello' const handler = new ConnectionErrorHandler(code) diff --git a/test/internal/connection-holder.test.js b/test/internal/connection-holder.test.js index 5ddfe8418..7c04a7b9e 100644 --- a/test/internal/connection-holder.test.js +++ b/test/internal/connection-holder.test.js @@ -25,7 +25,7 @@ import { READ, WRITE } from '../../src/driver' import FakeConnection from './fake-connection' import StreamObserver from '../../src/internal/stream-observer' -describe('EmptyConnectionHolder', () => { +describe('#unit EmptyConnectionHolder', () => { it('should return rejected promise instead of connection', done => { EMPTY_CONNECTION_HOLDER.getConnection(new StreamObserver()).catch(() => { done() @@ -45,7 +45,7 @@ describe('EmptyConnectionHolder', () => { }) }) -describe('ConnectionHolder', () => { +describe('#unit ConnectionHolder', () => { it('should acquire new connection during initialization', () => { const connectionProvider = new RecordingConnectionProvider([ new FakeConnection() diff --git a/test/internal/connection-provider-direct.test.js b/test/internal/connection-provider-direct.test.js index 11a734786..9c9af1344 100644 --- a/test/internal/connection-provider-direct.test.js +++ b/test/internal/connection-provider-direct.test.js @@ -21,10 +21,10 @@ import { READ } from '../../src/driver' import DirectConnectionProvider from '../../src/internal/connection-provider-direct' import Pool from '../../src/internal/pool' import ServerAddress from '../../src/internal/server-address' +import Connection from '../../src/internal/connection' +import Logger from '../../src/internal/logger' -const NO_OP_DRIVER_CALLBACK = () => {} - -describe('DirectConnectionProvider', () => { +describe('#unit DirectConnectionProvider', () => { it('acquires connection from the pool', done => { const address = ServerAddress.fromUrl('localhost:123') const pool = newPool() @@ -42,7 +42,14 @@ describe('DirectConnectionProvider', () => { }) function newDirectConnectionProvider (address, pool) { - return new DirectConnectionProvider(address, pool, NO_OP_DRIVER_CALLBACK) + const connectionProvider = new DirectConnectionProvider({ + id: 0, + config: {}, + logger: Logger.noOp(), + address: address + }) + connectionProvider._connectionPool = pool + return connectionProvider } function newPool () { @@ -52,9 +59,15 @@ function newPool () { }) } -class FakeConnection { +class FakeConnection extends Connection { constructor (address, release) { - this.address = address + super(null) + + this._address = address this.release = release } + + get address () { + return this._address + } } diff --git a/test/internal/connection-provider-routing.test.js b/test/internal/connection-provider-routing.test.js index 4af4e688f..4f5e3c016 100644 --- a/test/internal/connection-provider-routing.test.js +++ b/test/internal/connection-provider-routing.test.js @@ -22,16 +22,14 @@ import Integer, { int } from '../../src/integer' import { SERVICE_UNAVAILABLE, SESSION_EXPIRED } from '../../src/error' import RoutingTable from '../../src/internal/routing-table' import Pool from '../../src/internal/pool' -import LeastConnectedLoadBalancingStrategy from '../../src/internal/least-connected-load-balancing-strategy' import Logger from '../../src/internal/logger' import SimpleHostNameResolver from '../../src/internal/browser/browser-host-name-resolver' import ServerAddress from '../../src/internal/server-address' import RoutingConnectionProvider from '../../src/internal/connection-provider-routing' import { VERSION_IN_DEV } from '../../src/internal/server-version' +import Connection from '../../src/internal/connection' -const NO_OP_DRIVER_CALLBACK = () => {} - -describe('RoutingConnectionProvider', () => { +describe('#unit RoutingConnectionProvider', () => { let originalTimeout beforeEach(function () { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL @@ -1225,16 +1223,15 @@ function newRoutingConnectionProviderWithSeedRouter ( connectionPool = null ) { const pool = connectionPool || newPool() - const loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy(pool) - const connectionProvider = new RoutingConnectionProvider( - seedRouter, - {}, - pool, - loadBalancingStrategy, - new SimpleHostNameResolver(), - NO_OP_DRIVER_CALLBACK, - Logger.noOp() - ) + const connectionProvider = new RoutingConnectionProvider({ + id: 0, + address: seedRouter, + routingContext: {}, + hostNameResolver: new SimpleHostNameResolver(), + config: {}, + log: Logger.noOp() + }) + connectionProvider._connectionPool = pool connectionProvider._routingTables[database] = new RoutingTable({ database, routers, @@ -1314,11 +1311,21 @@ function expectPoolToNotContain (pool, addresses) { }) } -class FakeConnection { +class FakeConnection extends Connection { constructor (address, release, version) { - this.address = address + super(null) + + this._address = address + this._version = version || VERSION_IN_DEV.toString() this.release = release - this.version = () => VERSION_IN_DEV + } + + get address () { + return this._address + } + + get version () { + return this._version } } diff --git a/test/internal/connectivity-verifier.test.js b/test/internal/connectivity-verifier.test.js index 050ab82c4..f7b0b32e3 100644 --- a/test/internal/connectivity-verifier.test.js +++ b/test/internal/connectivity-verifier.test.js @@ -21,7 +21,7 @@ import ConnectivityVerifier from '../../src/internal/connectivity-verifier' import SingleConnectionProvider from '../../src/internal/connection-provider-single' import FakeConnection from './fake-connection' -describe('ConnectivityVerifier', () => { +describe('#unit ConnectivityVerifier', () => { it('should call success callback when able to acquire and release a connection', done => { const connectionPromise = Promise.resolve(new FakeConnection()) const connectionProvider = new SingleConnectionProvider(connectionPromise) diff --git a/test/internal/fake-connection.js b/test/internal/fake-connection.js index 68712d791..e0ab6ade6 100644 --- a/test/internal/fake-connection.js +++ b/test/internal/fake-connection.js @@ -17,7 +17,7 @@ * limitations under the License. */ -import { ServerVersion } from '../../src/internal/server-version' +import Connection from '../../src/internal/connection' /** * This class is like a mock of {@link Connection} that tracks invocations count. @@ -26,20 +26,44 @@ import { ServerVersion } from '../../src/internal/server-version' * At the time of writing such libraries require {@link Proxy} support but browser tests execute in * PhantomJS which does not support proxies. */ -export default class FakeConnection { +export default class FakeConnection extends Connection { constructor () { + super(null) + this._open = true + this._id = 0 + this._databaseId = null this.creationTimestamp = Date.now() this.resetInvoked = 0 this.releaseInvoked = 0 this.seenStatements = [] this.seenParameters = [] - this.server = {} + this._server = {} + } + + get id () { + return this._id + } + + get databaseId () { + return this._databaseId + } + + set databaseId (value) { + this._databaseId = value + } + + get server () { + return this._server + } + + get version () { + return this._server.version } - version () { - return ServerVersion.fromString(this.server.version) + set version (value) { + this._server.version = value } protocol () { @@ -78,7 +102,7 @@ export default class FakeConnection { } withServerVersion (version) { - this.server.version = version + this.version = version return this } diff --git a/test/internal/http/http-driver.test.js b/test/internal/http/http-driver.test.js index b5ab80bbf..f91379111 100644 --- a/test/internal/http/http-driver.test.js +++ b/test/internal/http/http-driver.test.js @@ -22,11 +22,10 @@ import sharedNeo4j from '../../internal/shared-neo4j' import testUtils from '.././test-utils' import { ServerVersion, - VERSION_3_1_0, VERSION_3_4_0 } from '../../../src/internal/server-version' -describe('http driver', () => { +describe('#integration http driver', () => { let originalTimeout let boltDriver let httpDriver @@ -298,10 +297,7 @@ describe('http driver', () => { }) it('should terminate query waiting on a lock when session is closed', async () => { - if ( - testUtils.isServer() || - !databaseSupportsTransactionTerminationInLocks() - ) { + if (testUtils.isServer()) { return } @@ -700,10 +696,6 @@ describe('http driver', () => { } } - function databaseSupportsTransactionTerminationInLocks () { - return serverVersion.compareTo(VERSION_3_1_0) >= 0 - } - function databaseSupportsSpatialAndTemporalTypes () { return serverVersion.compareTo(VERSION_3_4_0) >= 0 } diff --git a/test/internal/http/http-request-runner.test.js b/test/internal/http/http-request-runner.test.js index ecc90a448..bbab85f44 100644 --- a/test/internal/http/http-request-runner.test.js +++ b/test/internal/http/http-request-runner.test.js @@ -27,7 +27,7 @@ import _ from 'lodash' const VALID_URI = 'http://localhost' const INVALID_URI = 'http://not-localhost' -describe('http request runner', () => { +describe('#unit http request runner', () => { let originalTimeout beforeEach(function () { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL diff --git a/test/internal/http/http-session-tracker.test.js b/test/internal/http/http-session-tracker.test.js index 5a44b911e..a74874672 100644 --- a/test/internal/http/http-session-tracker.test.js +++ b/test/internal/http/http-session-tracker.test.js @@ -21,7 +21,7 @@ import HttpSession from '../../../src/internal/http/http-session' import urlUtil from '../../../src/internal/url-util' import HttpSessionTracker from '../../../src/internal/http/http-session-tracker' -describe('http session tracker', () => { +describe('#unit http session tracker', () => { it('should close open sessions', done => { const tracker = new HttpSessionTracker() diff --git a/test/internal/http/http-session.test.js b/test/internal/http/http-session.test.js index a81c7877d..18563be69 100644 --- a/test/internal/http/http-session.test.js +++ b/test/internal/http/http-session.test.js @@ -22,7 +22,7 @@ import testUtil from '../test-utils' import HttpSession from '../../../src/internal/http/http-session' import HttpSessionTracker from '../../../src/internal/http/http-session-tracker' -describe('http session', () => { +describe('#unit http session', () => { it('should fail for invalid query parameters', done => { if (testUtil.isServer()) { done() diff --git a/test/internal/least-connected-load-balancing-strategy.test.js b/test/internal/least-connected-load-balancing-strategy.test.js index 0afdc97df..c0f86e8a9 100644 --- a/test/internal/least-connected-load-balancing-strategy.test.js +++ b/test/internal/least-connected-load-balancing-strategy.test.js @@ -20,7 +20,7 @@ import LeastConnectedLoadBalancingStrategy from '../../src/internal/least-connected-load-balancing-strategy' import Pool from '../../src/internal/pool' -describe('LeastConnectedLoadBalancingStrategy', () => { +describe('#unit LeastConnectedLoadBalancingStrategy', () => { it('should return null when no readers', () => { const knownReaders = [] const strategy = new LeastConnectedLoadBalancingStrategy(new DummyPool({})) diff --git a/test/internal/logger.test.js b/test/internal/logger.test.js index acfcefc6b..26719d8db 100644 --- a/test/internal/logger.test.js +++ b/test/internal/logger.test.js @@ -21,7 +21,7 @@ import neo4j from '../../src' import sharedNeo4j from '../../test/internal/shared-neo4j' import Logger from '../../src/internal/logger' -describe('Logger', () => { +describe('#unit Logger', () => { let originalConsoleLog beforeEach(() => { @@ -82,7 +82,9 @@ describe('Logger', () => { { level: 'warn', message: 'Warn! Two' } ]) }) +}) +describe('#integration Logger', () => { it('should log when logger configured in the driver', done => { const logged = [] const config = memorizingLoggerConfig(logged) diff --git a/test/internal/node/direct.driver.boltkit.test.js b/test/internal/node/direct.driver.boltkit.test.js index 5a56e70fb..13e08d5ea 100644 --- a/test/internal/node/direct.driver.boltkit.test.js +++ b/test/internal/node/direct.driver.boltkit.test.js @@ -22,7 +22,7 @@ import { READ, WRITE } from '../../../src/driver' import boltStub from '../bolt-stub' import { newError, SERVICE_UNAVAILABLE } from '../../../src/error' -describe('direct driver with stub server', () => { +describe('#stub-direct direct driver with stub server', () => { let originalTimeout beforeAll(() => { @@ -308,7 +308,7 @@ describe('direct driver with stub server', () => { expect(records.length).toEqual(1) expect(records[0].get(0).toNumber()).toEqual(42) session.close(() => { - expect(driver._pool._pools['127.0.0.1:9001'].length).toEqual(0) + expect(connectionPool(driver, '127.0.0.1:9001').length).toEqual(0) driver.close() server.exit(code => { expect(code).toEqual(0) @@ -471,10 +471,10 @@ describe('direct driver with stub server', () => { expect(records[1].get(0)).toBe('Alice') expect(records[2].get(0)).toBe('Tina') - const connectionKey = Object.keys(driver._openConnections)[0] + const connectionKey = Object.keys(openConnections(driver))[0] expect(connectionKey).toBeTruthy() - const connection = driver._openConnections[connectionKey] + const connection = openConnections(driver, connectionKey) session.close(() => { // generate a fake fatal error connection._handleFatalError( @@ -482,12 +482,10 @@ describe('direct driver with stub server', () => { ) // expect that the connection to be removed from the pool - expect(driver._pool._pools['127.0.0.1:9001'].length).toEqual(0) - expect( - driver._pool._activeResourceCounts['127.0.0.1:9001'] - ).toBeFalsy() + expect(connectionPool(driver, '127.0.0.1:9001').length).toEqual(0) + expect(activeResources(driver, '127.0.0.1:9001')).toBeFalsy() // expect that the connection to be unregistered from the open connections registry - expect(driver._openConnections[connectionKey]).toBeFalsy() + expect(openConnections(driver, connectionKey)).toBeFalsy() driver.close() server.exit(code => { expect(code).toEqual(0) @@ -562,4 +560,25 @@ describe('direct driver with stub server', () => { verifyFailureOnCommit('v3', done) }) }) + + function connectionPool (driver, key) { + return driver._connectionProvider._connectionPool._pools[key] + } + + function openConnections (driver, key) { + const connections = driver._connectionProvider._openConnections + if (key) { + return connections[key] + } + return connections + } + + function activeResources (driver, key) { + const resources = + driver._connectionProvider._connectionPool._activeResourceCounts + if (key) { + return resources[key] + } + return resources + } }) diff --git a/test/internal/node/node-host-name-resolver.test.js b/test/internal/node/node-host-name-resolver.test.js index 06101ef97..fbc659b0f 100644 --- a/test/internal/node/node-host-name-resolver.test.js +++ b/test/internal/node/node-host-name-resolver.test.js @@ -20,7 +20,7 @@ import NodeHostNameResolver from '../../../src/internal/node/node-host-name-resolver' import ServerAddress from '../../../src/internal/server-address' -describe('NodeHostNameResolver', () => { +describe('#unit NodeHostNameResolver', () => { let originalTimeout beforeEach(() => { diff --git a/test/internal/node/routing.driver.boltkit.test.js b/test/internal/node/routing.driver.boltkit.test.js index 99101bb44..d53291d32 100644 --- a/test/internal/node/routing.driver.boltkit.test.js +++ b/test/internal/node/routing.driver.boltkit.test.js @@ -25,7 +25,7 @@ import { SERVICE_UNAVAILABLE, SESSION_EXPIRED } from '../../../src/error' import lolex from 'lolex' import ServerAddress from '../../../src/internal/server-address' -describe('routing driver with stub server', () => { +describe('#stub-routing routing driver with stub server', () => { let originalTimeout let clock @@ -2665,7 +2665,7 @@ describe('routing driver with stub server', () => { }) }) - describe('Multi-Database', () => { + describe('multi-Database', () => { function verifyDiscoverAndRead (script, database, done) { if (!boltStub.supported) { done() @@ -3218,7 +3218,7 @@ describe('routing driver with stub server', () => { } function numberOfOpenConnections (driver) { - return Object.keys(driver._openConnections).length + return Object.keys(driver._connectionProvider._openConnections).length } function testResolverFunctionDuringFirstDiscovery (resolutionResult, done) { diff --git a/test/internal/node/tls.test.js b/test/internal/node/tls.test.js index 04540d67d..c938b235f 100644 --- a/test/internal/node/tls.test.js +++ b/test/internal/node/tls.test.js @@ -21,7 +21,7 @@ import neo4j from '../../../src' import path from 'path' import sharedNeo4j from '../shared-neo4j' -describe('trust-all-certificates', () => { +describe(' #integration trust-all-certificates', () => { let driver afterEach(() => { @@ -48,7 +48,7 @@ describe('trust-all-certificates', () => { }) }) -describe('trust-custom-ca-signed-certificates', () => { +describe('#integration trust-custom-ca-signed-certificates', () => { let driver afterEach(() => { @@ -91,7 +91,7 @@ describe('trust-custom-ca-signed-certificates', () => { }) }) -describe('trust-system-ca-signed-certificates', () => { +describe('#integration trust-system-ca-signed-certificates', () => { let driver afterEach(() => { diff --git a/test/internal/packstream-v1.test.js b/test/internal/packstream-v1.test.js index 462e4fb90..15064d55a 100644 --- a/test/internal/packstream-v1.test.js +++ b/test/internal/packstream-v1.test.js @@ -21,7 +21,7 @@ import { alloc } from '../../src/internal/node' import { Packer, Structure, Unpacker } from '../../src/internal/packstream-v1' import { int } from '../../src' -describe('packstream-v1', () => { +describe('#unit PackStreamV1', () => { it('should pack integers', () => { let n, i // test small numbers diff --git a/test/internal/pool-config.test.js b/test/internal/pool-config.test.js index 866008fa3..cb02ae732 100644 --- a/test/internal/pool-config.test.js +++ b/test/internal/pool-config.test.js @@ -22,7 +22,7 @@ import PoolConfig, { DEFAULT_MAX_SIZE } from '../../src/internal/pool-config' -describe('PoolConfig', () => { +describe('#unit PoolConfig', () => { let originalConsoleWarn beforeAll(() => { diff --git a/test/internal/pool.test.js b/test/internal/pool.test.js index b94f134ed..947e69e19 100644 --- a/test/internal/pool.test.js +++ b/test/internal/pool.test.js @@ -22,7 +22,7 @@ import PoolConfig from '../../src/internal/pool-config' import ServerAddress from '../../src/internal/server-address' import { newError, SERVICE_UNAVAILABLE } from '../../src/error' -describe('Pool', () => { +describe('#unit Pool', () => { it('allocates if pool is empty', done => { // Given let counter = 0 diff --git a/test/internal/protocol-handshaker.test.js b/test/internal/protocol-handshaker.test.js index fca9debe3..c835185a6 100644 --- a/test/internal/protocol-handshaker.test.js +++ b/test/internal/protocol-handshaker.test.js @@ -22,7 +22,7 @@ import Logger from '../../src/internal/logger' import BoltProtocol from '../../src/internal/bolt-protocol-v1' import { alloc } from '../../src/internal/node' -describe('ProtocolHandshaker', () => { +describe('#unit ProtocolHandshaker', () => { it('should write handshake request', () => { const writtenBuffers = [] const fakeChannel = { diff --git a/test/internal/rediscovery.test.js b/test/internal/rediscovery.test.js index e72881e7f..807232264 100644 --- a/test/internal/rediscovery.test.js +++ b/test/internal/rediscovery.test.js @@ -26,7 +26,7 @@ import ServerAddress from '../../src/internal/server-address' const ROUTER_ADDRESS = 'neo4j://test.router.com' -describe('rediscovery', () => { +describe('#unit Rediscovery', () => { it('should return null when connection error happens', done => { const util = new FakeRoutingUtil({ callRoutingProcedure: () => null diff --git a/test/internal/request-message.test.js b/test/internal/request-message.test.js index b4016d256..d46ee0410 100644 --- a/test/internal/request-message.test.js +++ b/test/internal/request-message.test.js @@ -23,7 +23,7 @@ import TxConfig from '../../src/internal/tx-config' import { int } from '../../src' import { READ, WRITE } from '../../src/driver' -describe('RequestMessage', () => { +describe('#unit RequestMessage', () => { it('should create INIT message', () => { const userAgent = 'my-driver/1.0.2' const authToken = { username: 'neo4j', password: 'secret' } diff --git a/test/internal/round-robin-array-index.test.js b/test/internal/round-robin-array-index.test.js index 6e85ba685..fe85e963a 100644 --- a/test/internal/round-robin-array-index.test.js +++ b/test/internal/round-robin-array-index.test.js @@ -18,7 +18,7 @@ */ import RoundRobinArrayIndex from '../../src/internal/round-robin-array-index' -describe('RoundRobinArrayIndex', () => { +describe('#unit RoundRobinArrayIndex', () => { it('should return -1 for empty array', () => { const arrayLength = 0 const index = new RoundRobinArrayIndex() diff --git a/test/internal/routing-table.test.js b/test/internal/routing-table.test.js index f880874b0..6ce0ff104 100644 --- a/test/internal/routing-table.test.js +++ b/test/internal/routing-table.test.js @@ -21,7 +21,7 @@ import { int } from '../../src/integer' import { READ, WRITE } from '../../src/driver' import ServerAddress from '../../src/internal/server-address' -describe('RoutingTable', () => { +describe('#unit RoutingTable', () => { const server1 = ServerAddress.fromUrl('server1') const server2 = ServerAddress.fromUrl('server2') const server3 = ServerAddress.fromUrl('server3') diff --git a/test/internal/routing-util.test.js b/test/internal/routing-util.test.js index 1b6181bf4..6cce8a18a 100644 --- a/test/internal/routing-util.test.js +++ b/test/internal/routing-util.test.js @@ -32,7 +32,7 @@ import ServerAddress from '../../src/internal/server-address' const ROUTER_ADDRESS = ServerAddress.fromUrl('test.router.com:4242') -describe('RoutingUtil', () => { +describe('#unit RoutingUtil', () => { let clock afterEach(() => { diff --git a/test/internal/server-address.test.js b/test/internal/server-address.test.js index ceb45ce64..cf832278c 100644 --- a/test/internal/server-address.test.js +++ b/test/internal/server-address.test.js @@ -19,7 +19,7 @@ import ServerAddress from '../../src/internal/server-address' -describe('ServerAddress', () => { +describe('#unit ServerAddress', () => { it('should construct with correct values', () => { verifyAddress(ServerAddress.fromUrl('host.some.domain:8687'), { host: 'host.some.domain', diff --git a/test/internal/server-version.test.js b/test/internal/server-version.test.js index e2019222b..7130d1537 100644 --- a/test/internal/server-version.test.js +++ b/test/internal/server-version.test.js @@ -25,7 +25,7 @@ import { VERSION_IN_DEV } from '../../src/internal/server-version' -describe('ServerVersion', () => { +describe('#unit ServerVersion', () => { it('should construct with correct values', () => { verifyVersion(new ServerVersion(2, 3, 10), 2, 3, 10) verifyVersion(new ServerVersion(3, 2, 0), 3, 2, 0) @@ -85,39 +85,6 @@ describe('ServerVersion', () => { verifyVersion(parse('Neo4j/Dev'), maxVer, maxVer, maxVer) }) - it('should fetch version using driver', done => { - const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) - ServerVersion.fromDriver(driver) - .then(version => { - driver.close() - expect(version).not.toBeNull() - expect(version).toBeDefined() - expect(version instanceof ServerVersion).toBeTruthy() - done() - }) - .catch(error => { - driver.close() - done.fail(error) - }) - }) - - it('should fail to fetch version using incorrect driver', done => { - const driver = neo4j.driver('bolt://localhost:4242', sharedNeo4j.authToken) // use wrong port - ServerVersion.fromDriver(driver) - .then(version => { - driver.close() - done.fail( - 'Should not be able to fetch version: ' + JSON.stringify(version) - ) - }) - .catch(error => { - expect(error).not.toBeNull() - expect(error).toBeDefined() - driver.close() - done() - }) - }) - it('should compare equal versions', () => { expect( new ServerVersion(3, 1, 0).compareTo(new ServerVersion(3, 1, 0)) @@ -184,6 +151,41 @@ describe('ServerVersion', () => { }) }) +describe('#integration ServerVersion', () => { + it('should fetch version using driver', done => { + const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) + ServerVersion.fromDriver(driver) + .then(version => { + driver.close() + expect(version).not.toBeNull() + expect(version).toBeDefined() + expect(version instanceof ServerVersion).toBeTruthy() + done() + }) + .catch(error => { + driver.close() + done.fail(error) + }) + }) + + it('should fail to fetch version using incorrect driver', done => { + const driver = neo4j.driver('bolt://localhost:4242', sharedNeo4j.authToken) // use wrong port + ServerVersion.fromDriver(driver) + .then(version => { + driver.close() + done.fail( + 'Should not be able to fetch version: ' + JSON.stringify(version) + ) + }) + .catch(error => { + expect(error).not.toBeNull() + expect(error).toBeDefined() + driver.close() + done() + }) + }) +}) + function verifyVersion ( serverVersion, expectedMajor, diff --git a/test/internal/stream-observer.test.js b/test/internal/stream-observer.test.js index e95af07bb..432605fad 100644 --- a/test/internal/stream-observer.test.js +++ b/test/internal/stream-observer.test.js @@ -22,7 +22,7 @@ import FakeConnection from './fake-connection' const NO_OP = () => {} -describe('StreamObserver', () => { +describe('#unit StreamObserver', () => { it('remembers resolved connection', () => { const streamObserver = newStreamObserver() const connection = new FakeConnection() diff --git a/test/internal/temporal-util.test.js b/test/internal/temporal-util.test.js index 0ce8e613f..931bc8eb3 100644 --- a/test/internal/temporal-util.test.js +++ b/test/internal/temporal-util.test.js @@ -22,7 +22,7 @@ import * as util from '../../src/internal/temporal-util' import { types } from '../../src' import testUtils from './test-utils' -describe('temporal-util', () => { +describe('#unit temporal-util', () => { it('should normalize seconds for duration', () => { expect(util.normalizeSecondsForDuration(1, 0)).toEqual(int(1)) expect(util.normalizeSecondsForDuration(3, 0)).toEqual(int(3)) diff --git a/test/internal/test-utils.js b/test/internal/test-utils.js index 1037f7b98..f137f7432 100644 --- a/test/internal/test-utils.js +++ b/test/internal/test-utils.js @@ -16,6 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import Connection from '../../src/internal/connection' function isClient () { return typeof window !== 'undefined' && window.document @@ -87,8 +88,10 @@ const matchers = { } } -class MessageRecordingConnection { +class MessageRecordingConnection extends Connection { constructor () { + super(null) + this.messages = [] this.observers = [] this.flushes = [] diff --git a/test/internal/transaction-executor.test.js b/test/internal/transaction-executor.test.js index 3e444753a..c31324b57 100644 --- a/test/internal/transaction-executor.test.js +++ b/test/internal/transaction-executor.test.js @@ -30,7 +30,7 @@ const LOCKS_TERMINATED_ERROR = 'Neo.TransientError.Transaction.LockClientStopped' const OOM_ERROR = 'Neo.DatabaseError.General.OutOfMemoryError' -describe('TransactionExecutor', () => { +describe('#unit TransactionExecutor', () => { let clock let fakeSetTimeout diff --git a/test/internal/tx-config.test.js b/test/internal/tx-config.test.js index a0b78dfa3..d0826efb0 100644 --- a/test/internal/tx-config.test.js +++ b/test/internal/tx-config.test.js @@ -19,7 +19,7 @@ import TxConfig from '../../src/internal/tx-config' import { int } from '../../src' -describe('TxConfig', () => { +describe('#unit TxConfig', () => { it('should be possible to construct from null', () => { testEmptyConfigCreation(null) }) diff --git a/test/internal/url-util.test.js b/test/internal/url-util.test.js index cc8db0c7a..d0e25a41a 100644 --- a/test/internal/url-util.test.js +++ b/test/internal/url-util.test.js @@ -19,7 +19,7 @@ import urlUtil from '../../src/internal/url-util' -describe('url-util', () => { +describe('#unit url-util', () => { it('should parse URL with just host name', () => { verifyUrl('localhost', { host: 'localhost' diff --git a/test/internal/utf8.test.js b/test/internal/utf8.test.js index 1d10e8159..205c7fadd 100644 --- a/test/internal/utf8.test.js +++ b/test/internal/utf8.test.js @@ -20,7 +20,7 @@ import CombinedBuffer from '../../src/internal/buf/combined-buf' import { alloc, utf8 } from '../../src/internal/node' -describe('utf8', () => { +describe('#unit UTF8Encoding', () => { it('should have a nice clean buffer position after serializing', () => { // When const buffer = utf8.encode('hello, world!') diff --git a/test/internal/util.test.js b/test/internal/util.test.js index aa59ecf5b..5a2e6e140 100644 --- a/test/internal/util.test.js +++ b/test/internal/util.test.js @@ -21,7 +21,7 @@ import * as util from '../../src/internal/util' import { int } from '../../src' /* eslint-disable no-new-wrappers */ -describe('util', () => { +describe('#unit Utils', () => { it('should check empty objects', () => { expect(util.isEmptyObjectOrNull(null)).toBeTruthy() expect(util.isEmptyObjectOrNull({})).toBeTruthy() diff --git a/test/record.test.js b/test/record.test.js index f3bf45198..3070f182d 100644 --- a/test/record.test.js +++ b/test/record.test.js @@ -20,7 +20,7 @@ import Record from '../src/record' import { Neo4jError } from '../src/error' -describe('Record', () => { +describe('#unit Record', () => { it('should allow getting fields by name', () => { // Given const record = new Record(['name'], ['Bob']) diff --git a/test/result.test.js b/test/result.test.js index 57fceb69f..a04dcf4a1 100644 --- a/test/result.test.js +++ b/test/result.test.js @@ -21,7 +21,7 @@ import neo4j from '../src' import sharedNeo4j from './internal/shared-neo4j' import utils from './internal/test-utils' -describe('result stream', () => { +describe('#integration result stream', () => { let driver, session beforeEach(done => { diff --git a/test/routing-driver.test.js b/test/routing-driver.test.js index 1f1a9835a..f249a300d 100644 --- a/test/routing-driver.test.js +++ b/test/routing-driver.test.js @@ -22,12 +22,7 @@ import RoutingDriver from '../src/routing-driver' import Pool from '../src/internal/pool' import neo4j from '../src' -describe('RoutingDriver', () => { - it('should create least connected', () => { - const strategy = createStrategy({}) - expect(strategy instanceof LeastConnectedLoadBalancingStrategy).toBeTruthy() - }) - +describe('#unit RoutingDriver', () => { it('should fail when configured resolver is of illegal type', () => { expect(() => neo4j.driver( @@ -44,7 +39,3 @@ describe('RoutingDriver', () => { ).toThrowError(TypeError) }) }) - -function createStrategy (config) { - return RoutingDriver._createLoadBalancingStrategy(config, new Pool()) -} diff --git a/test/session.test.js b/test/session.test.js index e5663e1f7..17e5207c8 100644 --- a/test/session.test.js +++ b/test/session.test.js @@ -31,7 +31,7 @@ import testUtils from './internal/test-utils' import { newError, PROTOCOL_ERROR, SESSION_EXPIRED } from '../src/error' import ServerAddress from '../src/internal/server-address' -describe('session', () => { +describe('#integration session', () => { let driver let session // eslint-disable-next-line no-unused-vars diff --git a/test/spatial-types.test.js b/test/spatial-types.test.js index b054dec98..76899a661 100644 --- a/test/spatial-types.test.js +++ b/test/spatial-types.test.js @@ -29,7 +29,7 @@ const CARTESIAN_2D_CRS_CODE = neo4j.int(7203) const WGS_84_3D_CRS_CODE = neo4j.int(4979) const CARTESIAN_3D_CRS_CODE = neo4j.int(9157) -describe('spatial-types', () => { +describe('#integration spatial-types', () => { let driver let driverWithNativeNumbers let session diff --git a/test/stress.test.js b/test/stress.test.js index 04b95a226..fca065cbf 100644 --- a/test/stress.test.js +++ b/test/stress.test.js @@ -24,7 +24,7 @@ import _ from 'lodash' import { ServerVersion, VERSION_3_2_0 } from '../src/internal/server-version' import sharedNeo4j from './internal/shared-neo4j' -describe('stress tests', () => { +describe('#integration stress tests', () => { const TEST_MODES = { fast: { commandsCount: 5000, diff --git a/test/summary.test.js b/test/summary.test.js index 190eb812a..8a0963947 100644 --- a/test/summary.test.js +++ b/test/summary.test.js @@ -20,7 +20,7 @@ import neo4j from '../src' import sharedNeo4j from './internal/shared-neo4j' -describe('result summary', () => { +describe('#integration result summary', () => { let driver, session beforeEach(done => { diff --git a/test/temporal-types.test.js b/test/temporal-types.test.js index b10e1225f..994d08467 100644 --- a/test/temporal-types.test.js +++ b/test/temporal-types.test.js @@ -48,7 +48,7 @@ const MIN_ZONE_ID = 'Etc/GMT+12' const MAX_ZONE_ID = 'Etc/GMT-14' const ZONE_IDS = ['Europe/Zaporozhye', 'Europe/London', 'UTC', 'Africa/Cairo'] -describe('temporal-types', () => { +describe('#integration temporal-types', () => { let originalTimeout let driver let driverWithNativeNumbers diff --git a/test/transaction.test.js b/test/transaction.test.js index d7cc79eac..49d4e4649 100644 --- a/test/transaction.test.js +++ b/test/transaction.test.js @@ -20,7 +20,7 @@ import neo4j from '../src' import sharedNeo4j from './internal/shared-neo4j' import { ServerVersion } from '../src/internal/server-version' -describe('transaction', () => { +describe('#integration transaction', () => { let driver let session // eslint-disable-next-line no-unused-vars diff --git a/test/types.test.js b/test/types.test.js index 1f3b42e8d..dcefd9628 100644 --- a/test/types.test.js +++ b/test/types.test.js @@ -22,11 +22,11 @@ import sharedNeo4j from './internal/shared-neo4j' import _ from 'lodash' import { ServerVersion, VERSION_3_2_0 } from '../src/internal/server-version' -describe('null value', () => { +describe('#integration null value', () => { it('should support null', testValue(null)) }) -describe('floating point values', () => { +describe('#integration floating point values', () => { it('should support float 1.0 ', testValue(1)) it('should support float 0.0 ', testValue(0.0)) it('should support pretty big float ', testValue(3.4028235e38)) // Max 32-bit @@ -35,7 +35,7 @@ describe('floating point values', () => { it('should support really small float ', testValue(4.9e-324)) // Min 64-bit }) -describe('integer values', () => { +describe('#integration integer values', () => { it('should support integer 1 ', testValue(neo4j.int(1))) it('should support integer 0 ', testValue(neo4j.int(0))) it('should support integer -1 ', testValue(neo4j.int(-1))) @@ -49,12 +49,12 @@ describe('integer values', () => { ) }) -describe('boolean values', () => { +describe('#integration boolean values', () => { it('should support true ', testValue(true)) it('should support false ', testValue(false)) }) -describe('string values', () => { +describe('#integration string values', () => { it('should support empty string ', testValue('')) it('should support simple string ', testValue('abcdefghijklmnopqrstuvwxyz')) it( @@ -64,7 +64,7 @@ describe('string values', () => { it('should support long string', testValue('*'.repeat(10000))) }) -describe('list values', () => { +describe('#integration list values', () => { it('should support empty lists ', testValue([])) it('should support sparse lists ', testValue([undefined, 4], [null, 4])) it('should support float lists ', testValue([1, 2, 3])) @@ -78,7 +78,7 @@ describe('list values', () => { ) }) -describe('map values', () => { +describe('#integration map values', () => { it('should support empty maps ', testValue({})) it( 'should support basic maps ', @@ -100,7 +100,7 @@ describe('map values', () => { it('should support long maps', testValue(longMap())) }) -describe('node values', () => { +describe('#integration node values', () => { it('should support returning nodes ', done => { // Given const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) @@ -121,7 +121,7 @@ describe('node values', () => { }) }) -describe('relationship values', () => { +describe('#integration relationship values', () => { it('should support returning relationships', done => { // Given const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) @@ -142,7 +142,7 @@ describe('relationship values', () => { }) }) -describe('path values', () => { +describe('#integration path values', () => { it('should support returning paths', done => { // Given const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) @@ -178,7 +178,7 @@ describe('path values', () => { }) }) -describe('byte arrays', () => { +describe('#integration byte arrays', () => { let originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL let serverSupportsByteArrays = false From 50f80c5cda30528de652fba5c89b3fb52a6569e5 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Wed, 10 Jul 2019 14:59:22 +0100 Subject: [PATCH 07/13] Removed driver.onError callbacks --- test/driver.test.js | 99 ++++++------------- test/examples.test.js | 30 +++--- .../connection-provider-pooled.test.js | 77 +++++++++++++++ test/session.test.js | 2 +- test/types/driver.test.ts | 6 -- types/driver.d.ts | 2 - 6 files changed, 128 insertions(+), 88 deletions(-) create mode 100644 test/internal/connection-provider-pooled.test.js diff --git a/test/driver.test.js b/test/driver.test.js index 90edee84e..3925ace07 100644 --- a/test/driver.test.js +++ b/test/driver.test.js @@ -19,7 +19,6 @@ import neo4j from '../src' import sharedNeo4j from './internal/shared-neo4j' -import FakeConnection from './internal/fake-connection' import lolex from 'lolex' import { DEFAULT_ACQUISITION_TIMEOUT, @@ -65,20 +64,20 @@ describe('#integration driver', () => { driver.close() }) - it('should handle connection errors', done => { + it('should handle connection errors', async () => { // Given driver = neo4j.driver('bolt://local-host', sharedNeo4j.authToken) - - // Expect - driver.onError = error => { - // the error message is different whether in browser or node + const session = driver.session() + const txc = session.beginTransaction() + try { + await txc.run('RETURN 1') + expect(true).toBeFalsy('exception expected') + } catch (error) { expect(error.message).not.toBeNull() expect(error.code).toEqual(neo4j.error.SERVICE_UNAVAILABLE) - done() + } finally { + session.close() } - - // When - startNewTransaction(driver) }, 10000) it('should fail with correct error message when connecting to port 80', done => { @@ -131,19 +130,20 @@ describe('#integration driver', () => { }).toBeDefined() }) - it('should fail early on wrong credentials', done => { + it('should fail early on wrong credentials', async () => { // Given driver = neo4j.driver('bolt://localhost', wrongCredentials()) - - // Expect - driver.onError = err => { - // the error message is different whether in browser or node - expect(err.code).toEqual('Neo.ClientError.Security.Unauthorized') - done() + const session = driver.session() + const txc = session.beginTransaction() + try { + await txc.run('RETURN 1') + expect(true).toBeFalsy('exception expected') + } catch (error) { + expect(error.message).not.toBeNull() + expect(error.code).toEqual('Neo.ClientError.Security.Unauthorized') + } finally { + session.close() } - - // When - startNewTransaction(driver) }) it('should fail queries on wrong credentials', done => { @@ -220,26 +220,25 @@ describe('#integration driver', () => { }) }) - it('should fail nicely when connecting with routing to standalone server', done => { + it('should fail nicely when connecting with routing to standalone server', async () => { if (!routingProcedureOnlyAvailableOnCores()) { - done() - return + return Promise.resolve(null) } // Given driver = neo4j.driver('neo4j://localhost', sharedNeo4j.authToken) - - // Expect - driver.onError = error => { + const session = driver.session() + try { + await session.run('RETURN 1') + expect(true).toBeFalsy('exception expected') + } catch (error) { expect(error.message).toContain( 'Could not perform discovery. No routing servers available.' ) expect(error.code).toEqual(neo4j.error.SERVICE_UNAVAILABLE) - done() + } finally { + session.close() } - - // When - startNewTransaction(driver) }) it('should have correct user agent', () => { @@ -267,42 +266,6 @@ describe('#integration driver', () => { ) }) - it('should treat closed connections as invalid', () => { - driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) - - const connectionValid = driver._validateConnection( - new FakeConnection().closed() - ) - - expect(connectionValid).toBeFalsy() - }) - - it('should treat not old open connections as valid', () => { - driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken, { - maxConnectionLifetime: 10 - }) - - const connection = new FakeConnection().withCreationTimestamp(12) - clock = lolex.install() - clock.setSystemTime(20) - const connectionValid = driver._validateConnection(connection) - - expect(connectionValid).toBeTruthy() - }) - - it('should treat old open connections as invalid', () => { - driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken, { - maxConnectionLifetime: 10 - }) - - const connection = new FakeConnection().withCreationTimestamp(5) - clock = lolex.install() - clock.setSystemTime(20) - const connectionValid = driver._validateConnection(connection) - - expect(connectionValid).toBeFalsy() - }) - it('should discard closed connections', done => { driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken) @@ -514,7 +477,9 @@ describe('#integration driver', () => { } function openConnectionFrom (driver) { - return Array.from(Object.values(driver._openConnections)) + return Array.from( + Object.values(driver._connectionProvider._openConnections) + ) } function routingProcedureOnlyAvailableOnCores () { diff --git a/test/examples.test.js b/test/examples.test.js index 92b08f27a..370484c21 100644 --- a/test/examples.test.js +++ b/test/examples.test.js @@ -271,21 +271,27 @@ describe('#integration examples', () => { // tag::driver-lifecycle[] const driver = neo4j.driver(uri, neo4j.auth.basic(user, password)) - driver.verifyConnectivity().then(() => { - console.log('Driver created') - }) - - driver.onError = error => { - console.log(error) - } + driver + .verifyConnectivity() + .then(() => { + console.log('Driver created') + }) + .catch(error => { + console.log(`connectivity verification failed. ${error}`) + }) const session = driver.session() - session.run('CREATE (i:Item)').then(() => { - session.close() + session + .run('CREATE (i:Item)') + .then(() => { + session.close() - // ... on application exit: - driver.close() - }) + // ... on application exit: + driver.close() + }) + .catch(error => { + console.log(`unable to execute statement. ${error}`) + }) // end::driver-lifecycle[] testResultPromise.then(loggedMsg => { diff --git a/test/internal/connection-provider-pooled.test.js b/test/internal/connection-provider-pooled.test.js new file mode 100644 index 000000000..ced576a5c --- /dev/null +++ b/test/internal/connection-provider-pooled.test.js @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import PooledConnectionProvider from '../../src/internal/connection-provider-pooled' +import FakeConnection from './fake-connection' +import lolex from 'lolex' + +describe('#unit PooledConnectionProvider', () => { + let clock + + beforeEach(() => { + if (clock) { + clock.uninstall() + clock = null + } + }) + + it('should treat closed connections as invalid', () => { + const provider = new PooledConnectionProvider({ + id: 0, + config: {} + }) + + const connectionValid = provider._validateConnection( + new FakeConnection().closed() + ) + + expect(connectionValid).toBeFalsy() + }) + + it('should treat not old open connections as valid', () => { + const provider = new PooledConnectionProvider({ + id: 0, + config: { + maxConnectionLifetime: 10 + } + }) + + const connection = new FakeConnection().withCreationTimestamp(12) + clock = lolex.install() + clock.setSystemTime(20) + const connectionValid = provider._validateConnection(connection) + + expect(connectionValid).toBeTruthy() + }) + + it('should treat old open connections as invalid', () => { + const provider = new PooledConnectionProvider({ + id: 0, + config: { + maxConnectionLifetime: 10 + } + }) + + const connection = new FakeConnection().withCreationTimestamp(5) + clock = lolex.install() + clock.setSystemTime(20) + const connectionValid = provider._validateConnection(connection) + + expect(connectionValid).toBeFalsy() + }) +}) diff --git a/test/session.test.js b/test/session.test.js index 17e5207c8..9716311b5 100644 --- a/test/session.test.js +++ b/test/session.test.js @@ -1274,7 +1274,7 @@ describe('#integration session', () => { } function numberOfAcquiredConnectionsFromPool () { - const pool = driver._pool + const pool = driver._connectionProvider._connectionPool return pool.activeResourceCount(ServerAddress.fromUrl('localhost:7687')) } diff --git a/test/types/driver.test.ts b/test/types/driver.test.ts index afdb904bc..cf1e98d55 100644 --- a/test/types/driver.test.ts +++ b/test/types/driver.test.ts @@ -101,9 +101,3 @@ driver.verifyConnectivity().then((serverInfo: ServerInfo) => { console.log(serverInfo.version) console.log(serverInfo.address) }) - -driver.onError = (error: Neo4jError) => { - console.log(error) -} - -driver.onError(new Neo4jError('message', 'code')) diff --git a/types/driver.d.ts b/types/driver.d.ts index 34060ef77..d087753be 100644 --- a/types/driver.d.ts +++ b/types/driver.d.ts @@ -75,8 +75,6 @@ declare interface Driver { close(): void verifyConnectivity(): Promise - - onError?: (error: Neo4jError) => void } export { From 5a262fabbfd3afde3b4c2407c53042abc7ec40ed Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Wed, 10 Jul 2019 21:14:16 +0100 Subject: [PATCH 08/13] Add a couple of tests --- src/internal/connection-delegate.js | 27 ++- src/internal/connection-provider-direct.js | 5 +- test/internal/connection-delegate.test.js | 189 ++++++++++++++++++ .../connection-provider-direct.test.js | 13 +- .../connection-provider-routing.test.js | 18 ++ test/internal/logger.test.js | 112 +++++------ 6 files changed, 286 insertions(+), 78 deletions(-) create mode 100644 test/internal/connection-delegate.test.js diff --git a/src/internal/connection-delegate.js b/src/internal/connection-delegate.js index 510582d60..97a9e2665 100644 --- a/src/internal/connection-delegate.js +++ b/src/internal/connection-delegate.js @@ -27,8 +27,10 @@ export default class DelegateConnection extends Connection { constructor (delegate, errorHandler) { super(errorHandler) - this._originalErrorHandler = delegate._errorHandler - delegate._errorHandler = this._errorHandler + if (errorHandler) { + this._originalErrorHandler = delegate._errorHandler + delegate._errorHandler = this._errorHandler + } this._delegate = delegate } @@ -45,12 +47,8 @@ export default class DelegateConnection extends Connection { this._delegate.databaseId = value } - isOpen () { - return this._delegate.isOpen() - } - - protocol () { - return this._delegate.protocol() + get server () { + return this._delegate.server } get address () { @@ -65,8 +63,12 @@ export default class DelegateConnection extends Connection { this._delegate.version = value } - get server () { - return this._delegate.server + isOpen () { + return this._delegate.isOpen() + } + + protocol () { + return this._delegate.protocol() } connect (userAgent, authToken) { @@ -86,7 +88,10 @@ export default class DelegateConnection extends Connection { } _release () { - this._delegate._errorHandler = this._originalErrorHandler + if (this._originalErrorHandler) { + this._delegate._errorHandler = this._originalErrorHandler + } + this._delegate._release() } } diff --git a/src/internal/connection-provider-direct.js b/src/internal/connection-provider-direct.js index 219018f7a..b791ce543 100644 --- a/src/internal/connection-provider-direct.js +++ b/src/internal/connection-provider-direct.js @@ -18,6 +18,7 @@ */ import PooledConnectionProvider from './connection-provider-pooled' +import DelegateConnection from './connection-delegate' export default class DirectConnectionProvider extends PooledConnectionProvider { constructor ({ id, config, log, address, userAgent, authToken }) { @@ -27,6 +28,8 @@ export default class DirectConnectionProvider extends PooledConnectionProvider { } acquireConnection (accessMode, database) { - return this._connectionPool.acquire(this._address) + return this._connectionPool + .acquire(this._address) + .then(connection => new DelegateConnection(connection, null)) } } diff --git a/test/internal/connection-delegate.test.js b/test/internal/connection-delegate.test.js new file mode 100644 index 000000000..3c0fdea4a --- /dev/null +++ b/test/internal/connection-delegate.test.js @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2002-2019 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import DelegateConnection from '../../src/internal/connection-delegate' +import Connection from '../../src/internal/connection' +import BoltProtocol from '../../src/internal/bolt-protocol-v1' +import BoltAddress from '../../src/internal/server-address' +import ConnectionErrorHandler from '../../src/internal/connection-error-handler' + +describe('#unit DelegateConnection', () => { + it('should delegate get id', () => { + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'id', 'get').and.returnValue(5) + const connection = new DelegateConnection(delegate, null) + + expect(connection.id).toBe(5) + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate get databaseId', () => { + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'databaseId', 'get').and.returnValue( + '123-456' + ) + const connection = new DelegateConnection(delegate, null) + + expect(connection.databaseId).toBe('123-456') + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate set databaseId', () => { + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'databaseId', 'set') + const connection = new DelegateConnection(delegate, null) + + connection.databaseId = '345-678' + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate get server', () => { + const server = { + address: BoltAddress.fromUrl('bolt://127.0.0.1:8798'), + version: 'Neo4j/3.5.6' + } + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'server', 'get').and.returnValue(server) + const connection = new DelegateConnection(delegate, null) + + expect(connection.server).toBe(server) + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate get address', () => { + const address = BoltAddress.fromUrl('bolt://127.0.0.1:8080') + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'address', 'get').and.returnValue( + address + ) + const connection = new DelegateConnection(delegate, null) + + expect(connection.address).toBe(address) + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate get version', () => { + const version = 'Neo4j/3.5.6' + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'version', 'get').and.returnValue( + version + ) + const connection = new DelegateConnection(delegate, null) + + expect(connection.version).toBe(version) + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate set version', () => { + const delegate = new Connection(null) + const spy = spyOnProperty(delegate, 'version', 'set') + const connection = new DelegateConnection(delegate, null) + + connection.version = 'Neo4j/3.4.9' + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate isOpen', () => { + const delegate = new Connection(null) + const spy = spyOn(delegate, 'isOpen').and.returnValue(true) + const connection = new DelegateConnection(delegate, null) + + expect(connection.isOpen()).toBeTruthy() + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate protocol', () => { + const protocol = new BoltProtocol() + const delegate = new Connection(null) + const spy = spyOn(delegate, 'protocol').and.returnValue(protocol) + const connection = new DelegateConnection(delegate, null) + + expect(connection.protocol()).toBe(protocol) + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate connect', () => { + const delegate = new Connection(null) + const spy = spyOn(delegate, 'connect') + const connection = new DelegateConnection(delegate, null) + + connection.connect('neo4j/js-driver', {}) + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate write', () => { + const delegate = new Connection(null) + const spy = spyOn(delegate, 'write') + const connection = new DelegateConnection(delegate, null) + + connection.write({}, null, true) + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate resetAndFlush', () => { + const delegate = new Connection(null) + const spy = spyOn(delegate, 'resetAndFlush') + const connection = new DelegateConnection(delegate, null) + + connection.resetAndFlush() + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate close', () => { + const delegate = new Connection(null) + const spy = spyOn(delegate, 'close') + const connection = new DelegateConnection(delegate, null) + + connection.close() + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should delegate _release', () => { + const delegate = new Connection(null) + delegate._release = () => {} + const spy = spyOn(delegate, '_release') + const connection = new DelegateConnection(delegate, null) + + connection._release() + + expect(spy).toHaveBeenCalledTimes(1) + }) + + it('should override errorHandler on create and restore on release', () => { + const errorHandlerOriginal = new ConnectionErrorHandler('code1') + const delegate = new Connection(errorHandlerOriginal) + delegate._release = () => {} + + expect(delegate._errorHandler).toBe(errorHandlerOriginal) + + const errorHandlerNew = new ConnectionErrorHandler('code2') + const connection = new DelegateConnection(delegate, errorHandlerNew) + + expect(delegate._errorHandler).toBe(errorHandlerNew) + + connection._release() + + expect(delegate._errorHandler).toBe(errorHandlerOriginal) + }) +}) diff --git a/test/internal/connection-provider-direct.test.js b/test/internal/connection-provider-direct.test.js index 9c9af1344..15d549992 100644 --- a/test/internal/connection-provider-direct.test.js +++ b/test/internal/connection-provider-direct.test.js @@ -23,6 +23,7 @@ import Pool from '../../src/internal/pool' import ServerAddress from '../../src/internal/server-address' import Connection from '../../src/internal/connection' import Logger from '../../src/internal/logger' +import DelegateConnection from '../../src/internal/connection-delegate' describe('#unit DirectConnectionProvider', () => { it('acquires connection from the pool', done => { @@ -30,15 +31,23 @@ describe('#unit DirectConnectionProvider', () => { const pool = newPool() const connectionProvider = newDirectConnectionProvider(address, pool) - connectionProvider.acquireConnection(READ).then(connection => { + connectionProvider.acquireConnection(READ, '').then(connection => { expect(connection).toBeDefined() expect(connection.address).toEqual(address) - expect(connection.release).toBeDefined() expect(pool.has(address)).toBeTruthy() done() }) }) + + it('acquires connection and returns a DelegateConnection', async () => { + const address = ServerAddress.fromUrl('localhost:123') + const pool = newPool() + const connectionProvider = newDirectConnectionProvider(address, pool) + + const conn = await connectionProvider.acquireConnection(READ, '') + expect(conn instanceof DelegateConnection).toBeTruthy() + }) }) function newDirectConnectionProvider (address, pool) { diff --git a/test/internal/connection-provider-routing.test.js b/test/internal/connection-provider-routing.test.js index 4f5e3c016..9347ecb6f 100644 --- a/test/internal/connection-provider-routing.test.js +++ b/test/internal/connection-provider-routing.test.js @@ -28,6 +28,7 @@ import ServerAddress from '../../src/internal/server-address' import RoutingConnectionProvider from '../../src/internal/connection-provider-routing' import { VERSION_IN_DEV } from '../../src/internal/server-version' import Connection from '../../src/internal/connection' +import DelegateConnection from '../../src/internal/connection-delegate' describe('#unit RoutingConnectionProvider', () => { let originalTimeout @@ -169,6 +170,23 @@ describe('#unit RoutingConnectionProvider', () => { ) }) + it('acquires connection and returns a DelegateConnection', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + '', + [server1, server2], + [server3, server4], + [server5, server6], + pool + ) + + const conn1 = await connectionProvider.acquireConnection(READ, '') + expect(conn1 instanceof DelegateConnection).toBeTruthy() + + const conn2 = await connectionProvider.acquireConnection(WRITE, '') + expect(conn2 instanceof DelegateConnection).toBeTruthy() + }) + it('acquires read connection with up-to-date routing table', done => { const pool = newPool() const connectionProvider = newRoutingConnectionProvider( diff --git a/test/internal/logger.test.js b/test/internal/logger.test.js index 26719d8db..4a99997ff 100644 --- a/test/internal/logger.test.js +++ b/test/internal/logger.test.js @@ -22,16 +22,6 @@ import sharedNeo4j from '../../test/internal/shared-neo4j' import Logger from '../../src/internal/logger' describe('#unit Logger', () => { - let originalConsoleLog - - beforeEach(() => { - originalConsoleLog = console.log - }) - - afterEach(() => { - console.log = originalConsoleLog - }) - it('should create no-op logger when not configured', () => { const log = Logger.create({ logging: null }) @@ -122,74 +112,68 @@ describe('#integration Logger', () => { }) }) - it('should log debug to console when configured in the driver', done => { + it('should log debug to console when configured in the driver', async () => { + const originalConsoleLog = console.log const logged = [] console.log = message => logged.push(message) + const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken, { logging: neo4j.logging.console('debug') }) - const session = driver.session() - session - .run('RETURN 123456789') - .then(() => { - expect(logged.length).toBeGreaterThan(0) - - // the executed statement should've been logged - const statementLogged = logged.find( - log => - log.indexOf('DEBUG') !== -1 && - log.indexOf('RETURN 123456789') !== -1 - ) - expect(statementLogged).toBeTruthy() - - // driver creation should've been logged because it is on info level - const driverCreationLogged = logged.find( - log => log.indexOf('driver') !== -1 && log.indexOf('created') !== -1 - ) - expect(driverCreationLogged).toBeTruthy() - }) - .catch(error => { - done.fail(error) - }) - .then(() => { - driver.close() - done() - }) + try { + const session = driver.session() + await session.run('RETURN 123456789') + + expect(logged.length).toBeGreaterThan(0) + + // the executed statement should've been logged + const statementLogged = logged.find( + log => + log.indexOf('DEBUG') !== -1 && log.indexOf('RETURN 123456789') !== -1 + ) + expect(statementLogged).toBeTruthy() + + // driver creation should've been logged because it is on info level + const driverCreationLogged = logged.find( + log => log.indexOf('driver') !== -1 && log.indexOf('created') !== -1 + ) + expect(driverCreationLogged).toBeTruthy() + } finally { + console.log = originalConsoleLog + driver.close() + } }) - it('should log info to console when configured in the driver', done => { + it('should log info to console when configured in the driver', async () => { + const originalConsoleLog = console.log const logged = [] console.log = message => logged.push(message) + const driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken, { logging: neo4j.logging.console() }) // info is the default level - const session = driver.session() - session - .run('RETURN 123456789') - .then(() => { - expect(logged.length).toBeGreaterThan(0) - - // the executed statement should not be logged because it is in debug level - const statementLogged = logged.find( - log => log.indexOf('RETURN 123456789') !== -1 - ) - expect(statementLogged).toBeFalsy() - - // driver creation should've been logged because it is on info level - const driverCreationLogged = logged.find( - log => log.indexOf('driver') !== -1 && log.indexOf('created') !== -1 - ) - expect(driverCreationLogged).toBeTruthy() - }) - .catch(error => { - done.fail(error) - }) - .then(() => { - driver.close() - done() - }) + try { + const session = driver.session() + await session.run('RETURN 123456789') + expect(logged.length).toBeGreaterThan(0) + + // the executed statement should not be logged because it is in debug level + const statementLogged = logged.find( + log => log.indexOf('RETURN 123456789') !== -1 + ) + expect(statementLogged).toBeFalsy() + + // driver creation should've been logged because it is on info level + const driverCreationLogged = logged.find( + log => log.indexOf('driver') !== -1 && log.indexOf('created') !== -1 + ) + expect(driverCreationLogged).toBeTruthy() + } finally { + console.log = originalConsoleLog + driver.close() + } }) }) From 71985353aa56e5ce7b00a0c80264e92cd7dc8029 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Thu, 11 Jul 2019 16:46:28 +0100 Subject: [PATCH 09/13] Pull setTimeout mock into tests --- test/internal/transaction-executor.test.js | 470 +++++++++++---------- 1 file changed, 238 insertions(+), 232 deletions(-) diff --git a/test/internal/transaction-executor.test.js b/test/internal/transaction-executor.test.js index c31324b57..84d26d7a6 100644 --- a/test/internal/transaction-executor.test.js +++ b/test/internal/transaction-executor.test.js @@ -31,164 +31,150 @@ const LOCKS_TERMINATED_ERROR = const OOM_ERROR = 'Neo.DatabaseError.General.OutOfMemoryError' describe('#unit TransactionExecutor', () => { - let clock - let fakeSetTimeout + let originalTimeout beforeEach(() => { - fakeSetTimeout = setTimeoutMock.install() + originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL + jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000 }) afterEach(() => { - if (clock) { - clock.uninstall() - clock = null - } - fakeSetTimeout.uninstall() + jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout }) - it('should retry when transaction work returns promise rejected with SERVICE_UNAVAILABLE', done => { - testRetryWhenTransactionWorkReturnsRejectedPromise( - [SERVICE_UNAVAILABLE], - done - ) + it('should retry when transaction work returns promise rejected with SERVICE_UNAVAILABLE', async () => { + await testRetryWhenTransactionWorkReturnsRejectedPromise([ + SERVICE_UNAVAILABLE + ]) }) - it('should retry when transaction work returns promise rejected with SESSION_EXPIRED', done => { - testRetryWhenTransactionWorkReturnsRejectedPromise([SESSION_EXPIRED], done) + it('should retry when transaction work returns promise rejected with SESSION_EXPIRED', async () => { + await testRetryWhenTransactionWorkReturnsRejectedPromise([SESSION_EXPIRED]) }) - it('should retry when transaction work returns promise rejected with deadlock error', done => { - testRetryWhenTransactionWorkReturnsRejectedPromise( - [TRANSIENT_ERROR_1], - done - ) + it('should retry when transaction work returns promise rejected with deadlock error', async () => { + await testRetryWhenTransactionWorkReturnsRejectedPromise([ + TRANSIENT_ERROR_1 + ]) }) - it('should retry when transaction work returns promise rejected with communication error', done => { - testRetryWhenTransactionWorkReturnsRejectedPromise( - [TRANSIENT_ERROR_2], - done - ) + it('should retry when transaction work returns promise rejected with communication error', async () => { + await testRetryWhenTransactionWorkReturnsRejectedPromise([ + TRANSIENT_ERROR_2 + ]) }) - it('should not retry when transaction work returns promise rejected with OOM error', done => { - testNoRetryOnUnknownError([OOM_ERROR], 1, done) + it('should not retry when transaction work returns promise rejected with OOM error', async () => { + await testNoRetryOnUnknownError([OOM_ERROR], 1) }) - it('should not retry when transaction work returns promise rejected with unknown error', done => { - testNoRetryOnUnknownError([UNKNOWN_ERROR], 1, done) + it('should not retry when transaction work returns promise rejected with unknown error', async () => { + await testNoRetryOnUnknownError([UNKNOWN_ERROR], 1) }) - it('should not retry when transaction work returns promise rejected with transaction termination error', done => { - testNoRetryOnUnknownError([TX_TERMINATED_ERROR], 1, done) + it('should not retry when transaction work returns promise rejected with transaction termination error', async () => { + await testNoRetryOnUnknownError([TX_TERMINATED_ERROR], 1) }) - it('should not retry when transaction work returns promise rejected with locks termination error', done => { - testNoRetryOnUnknownError([LOCKS_TERMINATED_ERROR], 1, done) + it('should not retry when transaction work returns promise rejected with locks termination error', async () => { + await testNoRetryOnUnknownError([LOCKS_TERMINATED_ERROR], 1) }) - it('should stop retrying when time expires', done => { - const executor = new TransactionExecutor() + it('should stop retrying when time expires', async () => { + let clock const usedTransactions = [] - const realWork = transactionWork( - [ - SERVICE_UNAVAILABLE, - SESSION_EXPIRED, - TRANSIENT_ERROR_1, - TRANSIENT_ERROR_2 - ], - 42 - ) - - const result = executor.execute(transactionCreator(), tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - if (usedTransactions.length === 3) { - const currentTime = Date.now() - clock = lolex.install() - clock.setSystemTime(currentTime + 30001) // move `Date.now()` call forward by 30 seconds - } - return realWork() - }) + try { + const executor = new TransactionExecutor() + const realWork = transactionWork( + [ + SERVICE_UNAVAILABLE, + SESSION_EXPIRED, + TRANSIENT_ERROR_1, + TRANSIENT_ERROR_2 + ], + 42 + ) + + await executor.execute(transactionCreator(), tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + if (usedTransactions.length === 3) { + const currentTime = Date.now() + clock = lolex.install() + clock.setSystemTime(currentTime + 30001) // move `Date.now()` call forward by 30 seconds + } + return realWork() + }) - result.catch(error => { + expect(false).toBeTruthy('should have thrown an exception') + } catch (error) { expect(usedTransactions.length).toEqual(3) expectAllTransactionsToBeClosed(usedTransactions) expect(error.code).toEqual(TRANSIENT_ERROR_1) - done() - }) + } finally { + if (clock) { + clock.uninstall() + } + } }) - it('should retry when given transaction creator throws once', done => { - testRetryWhenTransactionCreatorFails([SERVICE_UNAVAILABLE], done) + it('should retry when given transaction creator throws once', async () => { + await testRetryWhenTransactionCreatorFails([SERVICE_UNAVAILABLE]) }) - it('should retry when given transaction creator throws many times', done => { - testRetryWhenTransactionCreatorFails( - [ - SERVICE_UNAVAILABLE, - SESSION_EXPIRED, - TRANSIENT_ERROR_2, - SESSION_EXPIRED, - SERVICE_UNAVAILABLE, - TRANSIENT_ERROR_1 - ], - done - ) + it('should retry when given transaction creator throws many times', async () => { + await testRetryWhenTransactionCreatorFails([ + SERVICE_UNAVAILABLE, + SESSION_EXPIRED, + TRANSIENT_ERROR_2, + SESSION_EXPIRED, + SERVICE_UNAVAILABLE, + TRANSIENT_ERROR_1 + ]) }) - it('should retry when given transaction work throws once', done => { - testRetryWhenTransactionWorkThrows([SERVICE_UNAVAILABLE], done) + it('should retry when given transaction work throws once', async () => { + await testRetryWhenTransactionWorkThrows([SERVICE_UNAVAILABLE]) }) - it('should retry when given transaction work throws many times', done => { - testRetryWhenTransactionWorkThrows( - [ - SERVICE_UNAVAILABLE, - TRANSIENT_ERROR_2, - TRANSIENT_ERROR_2, - SESSION_EXPIRED - ], - done - ) + it('should retry when given transaction work throws many times', async () => { + await testRetryWhenTransactionWorkThrows([ + SERVICE_UNAVAILABLE, + TRANSIENT_ERROR_2, + TRANSIENT_ERROR_2, + SESSION_EXPIRED + ]) }) - it('should retry when given transaction work returns rejected promise many times', done => { - testRetryWhenTransactionWorkReturnsRejectedPromise( - [ - SERVICE_UNAVAILABLE, - SERVICE_UNAVAILABLE, - TRANSIENT_ERROR_2, - SESSION_EXPIRED, - TRANSIENT_ERROR_1, - SESSION_EXPIRED - ], - done - ) + it('should retry when given transaction work returns rejected promise many times', async () => { + await testRetryWhenTransactionWorkReturnsRejectedPromise([ + SERVICE_UNAVAILABLE, + SERVICE_UNAVAILABLE, + TRANSIENT_ERROR_2, + SESSION_EXPIRED, + TRANSIENT_ERROR_1, + SESSION_EXPIRED + ]) }) - it('should retry when transaction commit returns rejected promise once', done => { - testRetryWhenTransactionCommitReturnsRejectedPromise( - [TRANSIENT_ERROR_1], - done - ) + it('should retry when transaction commit returns rejected promise once', async () => { + await testRetryWhenTransactionCommitReturnsRejectedPromise([ + TRANSIENT_ERROR_1 + ]) }) - it('should retry when transaction commit returns rejected promise multiple times', done => { - testRetryWhenTransactionCommitReturnsRejectedPromise( - [ - TRANSIENT_ERROR_1, - TRANSIENT_ERROR_1, - SESSION_EXPIRED, - SERVICE_UNAVAILABLE, - TRANSIENT_ERROR_2 - ], - done - ) + it('should retry when transaction commit returns rejected promise multiple times', async () => { + await testRetryWhenTransactionCommitReturnsRejectedPromise([ + TRANSIENT_ERROR_1, + TRANSIENT_ERROR_1, + SESSION_EXPIRED, + SERVICE_UNAVAILABLE, + TRANSIENT_ERROR_2 + ]) }) - it('should retry until database error happens', done => { - testNoRetryOnUnknownError( + it('should retry until database error happens', async () => { + await testNoRetryOnUnknownError( [ SERVICE_UNAVAILABLE, SERVICE_UNAVAILABLE, @@ -197,44 +183,53 @@ describe('#unit TransactionExecutor', () => { UNKNOWN_ERROR, SESSION_EXPIRED ], - 5, - done + 5 ) }) - it('should retry when transaction work throws and rollback fails', done => { - testRetryWhenTransactionWorkThrowsAndRollbackFails( + it('should retry when transaction work throws and rollback fails', async () => { + await testRetryWhenTransactionWorkThrowsAndRollbackFails( [ SERVICE_UNAVAILABLE, TRANSIENT_ERROR_2, SESSION_EXPIRED, SESSION_EXPIRED ], - [SESSION_EXPIRED, TRANSIENT_ERROR_1], - done + [SESSION_EXPIRED, TRANSIENT_ERROR_1] ) }) - it('should cancel in-flight timeouts when closed', done => { - const executor = new TransactionExecutor() - // do not execute setTimeout callbacks - fakeSetTimeout.pause() - - executor.execute(transactionCreator([SERVICE_UNAVAILABLE]), () => - Promise.resolve(42) - ) - executor.execute(transactionCreator([TRANSIENT_ERROR_1]), () => - Promise.resolve(4242) - ) - executor.execute(transactionCreator([SESSION_EXPIRED]), () => - Promise.resolve(424242) - ) - - fakeSetTimeout.setTimeoutOriginal(() => { - executor.close() - expect(fakeSetTimeout.clearedTimeouts.length).toEqual(3) - done() - }, 1000) + it('should cancel in-flight timeouts when closed', async () => { + const fakeSetTimeout = setTimeoutMock.install() + try { + const executor = new TransactionExecutor() + // do not execute setTimeout callbacks + fakeSetTimeout.pause() + + executor.execute(transactionCreator([SERVICE_UNAVAILABLE]), () => + Promise.resolve(42) + ) + executor.execute(transactionCreator([TRANSIENT_ERROR_1]), () => + Promise.resolve(4242) + ) + executor.execute(transactionCreator([SESSION_EXPIRED]), () => + Promise.resolve(424242) + ) + + await new Promise((resolve, reject) => { + fakeSetTimeout.setTimeoutOriginal(() => { + try { + executor.close() + expect(fakeSetTimeout.clearedTimeouts.length).toEqual(3) + resolve() + } catch (error) { + reject(error) + } + }, 1000) + }) + } finally { + fakeSetTimeout.uninstall() + } }) it('should allow zero max retry time', () => { @@ -256,141 +251,150 @@ describe('#unit TransactionExecutor', () => { expect(executor._jitterFactor).toEqual(0) }) - function testRetryWhenTransactionCreatorFails (errorCodes, done) { - const executor = new TransactionExecutor() - const transactionCreator = throwingTransactionCreator( - errorCodes, - new FakeTransaction() - ) - const usedTransactions = [] - - const result = executor.execute(transactionCreator, tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - return Promise.resolve(42) - }) + async function testRetryWhenTransactionCreatorFails (errorCodes) { + const fakeSetTimeout = setTimeoutMock.install() + try { + const executor = new TransactionExecutor() + const transactionCreator = throwingTransactionCreator( + errorCodes, + new FakeTransaction() + ) + const usedTransactions = [] + + const result = await executor.execute(transactionCreator, tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + return Promise.resolve(42) + }) - result.then(value => { expect(usedTransactions.length).toEqual(1) - expect(value).toEqual(42) + expect(result).toEqual(42) verifyRetryDelays(fakeSetTimeout, errorCodes.length) - done() - }) + } finally { + fakeSetTimeout.uninstall() + } } - function testRetryWhenTransactionWorkReturnsRejectedPromise ( - errorCodes, - done + async function testRetryWhenTransactionWorkReturnsRejectedPromise ( + errorCodes ) { - const executor = new TransactionExecutor() - const usedTransactions = [] - const realWork = transactionWork(errorCodes, 42) + const fakeSetTimeout = setTimeoutMock.install() + try { + const executor = new TransactionExecutor() + const usedTransactions = [] + const realWork = transactionWork(errorCodes, 42) - const result = executor.execute(transactionCreator(), tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - return realWork() - }) + const result = await executor.execute(transactionCreator(), tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + return realWork() + }) - result.then(value => { // work should have failed 'failures.length' times and succeeded 1 time expect(usedTransactions.length).toEqual(errorCodes.length + 1) expectAllTransactionsToBeClosed(usedTransactions) - expect(value).toEqual(42) + expect(result).toEqual(42) verifyRetryDelays(fakeSetTimeout, errorCodes.length) - done() - }) + } finally { + fakeSetTimeout.uninstall() + } } - function testRetryWhenTransactionCommitReturnsRejectedPromise ( - errorCodes, - done + async function testRetryWhenTransactionCommitReturnsRejectedPromise ( + errorCodes ) { - const executor = new TransactionExecutor() - const usedTransactions = [] - const realWork = () => Promise.resolve(4242) + const fakeSetTimeout = setTimeoutMock.install() + try { + const executor = new TransactionExecutor() + const usedTransactions = [] + const realWork = () => Promise.resolve(4242) + + const result = await executor.execute( + transactionCreator(errorCodes), + tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + return realWork() + } + ) - const result = executor.execute(transactionCreator(errorCodes), tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - return realWork() - }) - - result.then(value => { // work should have failed 'failures.length' times and succeeded 1 time expect(usedTransactions.length).toEqual(errorCodes.length + 1) expectAllTransactionsToBeClosed(usedTransactions) - expect(value).toEqual(4242) + expect(result).toEqual(4242) verifyRetryDelays(fakeSetTimeout, errorCodes.length) - done() - }) + } finally { + fakeSetTimeout.uninstall() + } } - function testRetryWhenTransactionWorkThrows (errorCodes, done) { - const executor = new TransactionExecutor() - const usedTransactions = [] - const realWork = throwingTransactionWork(errorCodes, 42) + async function testRetryWhenTransactionWorkThrows (errorCodes) { + const fakeSetTimeout = setTimeoutMock.install() + try { + const executor = new TransactionExecutor() + const usedTransactions = [] + const realWork = throwingTransactionWork(errorCodes, 42) - const result = executor.execute(transactionCreator(), tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - return realWork() - }) + const result = await executor.execute(transactionCreator(), tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + return realWork() + }) - result.then(value => { // work should have failed 'failures.length' times and succeeded 1 time expect(usedTransactions.length).toEqual(errorCodes.length + 1) expectAllTransactionsToBeClosed(usedTransactions) - expect(value).toEqual(42) + expect(result).toEqual(42) verifyRetryDelays(fakeSetTimeout, errorCodes.length) - done() - }) + } finally { + fakeSetTimeout.uninstall() + } } - function testRetryWhenTransactionWorkThrowsAndRollbackFails ( + async function testRetryWhenTransactionWorkThrowsAndRollbackFails ( txWorkErrorCodes, - rollbackErrorCodes, - done + rollbackErrorCodes ) { - const executor = new TransactionExecutor() - const usedTransactions = [] - const realWork = throwingTransactionWork(txWorkErrorCodes, 424242) + const fakeSetTimeout = setTimeoutMock.install() + try { + const executor = new TransactionExecutor() + const usedTransactions = [] + const realWork = throwingTransactionWork(txWorkErrorCodes, 424242) + + const result = await executor.execute( + transactionCreator([], rollbackErrorCodes), + tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + return realWork() + } + ) - const result = executor.execute( - transactionCreator([], rollbackErrorCodes), - tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - return realWork() - } - ) - - result.then(value => { // work should have failed 'failures.length' times and succeeded 1 time expect(usedTransactions.length).toEqual(txWorkErrorCodes.length + 1) expectAllTransactionsToBeClosed(usedTransactions) - expect(value).toEqual(424242) + expect(result).toEqual(424242) verifyRetryDelays(fakeSetTimeout, txWorkErrorCodes.length) - done() - }) + } finally { + fakeSetTimeout.uninstall() + } } - function testNoRetryOnUnknownError ( + async function testNoRetryOnUnknownError ( errorCodes, - expectedWorkInvocationCount, - done + expectedWorkInvocationCount ) { const executor = new TransactionExecutor() const usedTransactions = [] const realWork = transactionWork(errorCodes, 42) - const result = executor.execute(transactionCreator(), tx => { - expect(tx).toBeDefined() - usedTransactions.push(tx) - return realWork() - }) - - result.catch(error => { + try { + await executor.execute(transactionCreator(), tx => { + expect(tx).toBeDefined() + usedTransactions.push(tx) + return realWork() + }) + } catch (error) { expect(usedTransactions.length).toEqual(expectedWorkInvocationCount) expectAllTransactionsToBeClosed(usedTransactions) if (errorCodes.length === 1) { @@ -398,8 +402,10 @@ describe('#unit TransactionExecutor', () => { } else { expect(error.code).toEqual(errorCodes[expectedWorkInvocationCount - 1]) } - done() - }) + return + } + + expect(false).toBeTruthy('exception expected') } }) From ca8739d46c406d251c62c6944c06ad1d4222be25 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Thu, 11 Jul 2019 17:14:17 +0100 Subject: [PATCH 10/13] Add exit statement to the script --- test/resources/boltstub/v3/acquire_endpoints_no_writers.script | 1 + 1 file changed, 1 insertion(+) diff --git a/test/resources/boltstub/v3/acquire_endpoints_no_writers.script b/test/resources/boltstub/v3/acquire_endpoints_no_writers.script index 7deb5bbe9..43124515b 100644 --- a/test/resources/boltstub/v3/acquire_endpoints_no_writers.script +++ b/test/resources/boltstub/v3/acquire_endpoints_no_writers.script @@ -8,3 +8,4 @@ C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {}} {} S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": [],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] SUCCESS {} + From bf647e758b49982d93e402f6f2592e721f6749e4 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Fri, 12 Jul 2019 12:19:51 +0100 Subject: [PATCH 11/13] Localize all global clock and timer mocks --- test/driver.test.js | 43 +++++----- test/internal/connection-channel.test.js | 78 ++++++++++--------- .../connection-provider-pooled.test.js | 33 ++++---- .../node/routing.driver.boltkit.test.js | 17 ++-- test/internal/routing-util.test.js | 56 ++++++------- 5 files changed, 115 insertions(+), 112 deletions(-) diff --git a/test/driver.test.js b/test/driver.test.js index 3925ace07..35595d0ad 100644 --- a/test/driver.test.js +++ b/test/driver.test.js @@ -28,7 +28,6 @@ import { ServerVersion, VERSION_4_0_0 } from '../src/internal/server-version' import testUtils from './internal/test-utils' describe('#integration driver', () => { - let clock let driver let serverVersion @@ -42,10 +41,6 @@ describe('#integration driver', () => { }) afterEach(() => { - if (clock) { - clock.uninstall() - clock = null - } if (driver) { driver.close() driver = null @@ -295,38 +290,38 @@ describe('#integration driver', () => { }) }) - it('should discard old connections', done => { + it('should discard old connections', async () => { const maxLifetime = 100000 driver = neo4j.driver('bolt://localhost', sharedNeo4j.authToken, { maxConnectionLifetime: maxLifetime }) const session1 = driver.session() - session1.run('CREATE () RETURN 42').then(() => { - session1.close() + await session1.run('CREATE () RETURN 42') + session1.close() - // one connection should be established - const connections1 = openConnectionFrom(driver) - expect(connections1.length).toEqual(1) + // one connection should be established + const connections1 = openConnectionFrom(driver) + expect(connections1.length).toEqual(1) - // make existing connection look very old by advancing the `Date.now()` value - const currentTime = Date.now() - clock = lolex.install() + // make existing connection look very old by advancing the `Date.now()` value + const currentTime = Date.now() + const clock = lolex.install() + try { clock.setSystemTime(currentTime + maxLifetime * 2) const session2 = driver.session() - session2.run('RETURN 1').then(() => { - session2.close() + await session2.run('RETURN 1') + session2.close() - // old connection should be disposed and new one should be created - const connections2 = openConnectionFrom(driver) - expect(connections2.length).toEqual(1) + // old connection should be disposed and new one should be created + const connections2 = openConnectionFrom(driver) + expect(connections2.length).toEqual(1) - expect(connections1[0]).not.toEqual(connections2[0]) - - done() - }) - }) + expect(connections1[0]).not.toEqual(connections2[0]) + } finally { + clock.uninstall() + } }) const exposedTypes = [ diff --git a/test/internal/connection-channel.test.js b/test/internal/connection-channel.test.js index 9b5493cb4..1eca98b16 100644 --- a/test/internal/connection-channel.test.js +++ b/test/internal/connection-channel.test.js @@ -41,15 +41,9 @@ const FAILURE_MESSAGE = { signature: 0x7f, fields: [newError('Hello')] } const RECORD_MESSAGE = { signature: 0x71, fields: [{ value: 'Hello' }] } describe('#integration ChannelConnection', () => { - let clock let connection afterEach(done => { - if (clock) { - clock.uninstall() - clock = null - } - const usedConnection = connection connection = null if (usedConnection) { @@ -59,12 +53,16 @@ describe('#integration ChannelConnection', () => { }) it('should have correct creation timestamp', () => { - clock = lolex.install() - clock.setSystemTime(424242) + const clock = lolex.install() + try { + clock.setSystemTime(424242) - connection = createConnection('bolt://localhost') + connection = createConnection('bolt://localhost') - expect(connection.creationTimestamp).toEqual(424242) + expect(connection.creationTimestamp).toEqual(424242) + } finally { + clock.uninstall() + } }) it('should read/write basic messages', done => { @@ -231,12 +229,12 @@ describe('#integration ChannelConnection', () => { }) }) - it('should respect connection timeout', done => { - testConnectionTimeout(false, done) + it('should respect connection timeout', async () => { + await testConnectionTimeout(false) }) - it('should respect encrypted connection timeout', done => { - testConnectionTimeout(true, done) + it('should respect encrypted connection timeout', async () => { + await testConnectionTimeout(true) }) it('should not queue INIT observer when broken', done => { @@ -471,30 +469,38 @@ describe('#integration ChannelConnection', () => { } } - function testConnectionTimeout (encrypted, done) { - const boltUri = 'bolt://10.0.0.0' // use non-routable IP address which never responds - connection = createConnection( - boltUri, - { encrypted: encrypted, connectionTimeout: 1000 }, - 'TestErrorCode' - ) - - connection - .connect('mydriver/0.0.0', basicAuthToken()) - .then(() => done.fail('Should not be able to connect')) - .catch(error => { - expect(error.code).toEqual('TestErrorCode') + async function testConnectionTimeout (encrypted) { + const clock = jasmine.clock() + clock.install() + + try { + const boltUri = 'bolt://10.0.0.0' // use non-routable IP address which never responds + connection = createConnection( + boltUri, + { encrypted: encrypted, connectionTimeout: 1000 }, + 'TestErrorCode' + ) + + clock.tick(1001) + + await connection.connect('mydriver/0.0.0', basicAuthToken()) + } catch (error) { + expect(error.code).toEqual('TestErrorCode') + + // in some environments non-routable address results in immediate 'connection refused' error and connect + // timeout is not fired; skip message assertion for such cases, it is important for connect attempt to not hang + if (error.message.indexOf('Failed to establish connection') === 0) { + expect(error.message).toEqual( + 'Failed to establish connection in 1000ms' + ) + } - // in some environments non-routable address results in immediate 'connection refused' error and connect - // timeout is not fired; skip message assertion for such cases, it is important for connect attempt to not hang - if (error.message.indexOf('Failed to establish connection') === 0) { - expect(error.message).toEqual( - 'Failed to establish connection in 1000ms' - ) - } + return + } finally { + clock.uninstall() + } - done() - }) + expect(false).toBeTruthy('exception expected') } function testQueueingOfObserversWithBrokenConnection (connectionAction, done) { diff --git a/test/internal/connection-provider-pooled.test.js b/test/internal/connection-provider-pooled.test.js index ced576a5c..a7949e6fb 100644 --- a/test/internal/connection-provider-pooled.test.js +++ b/test/internal/connection-provider-pooled.test.js @@ -21,15 +21,6 @@ import FakeConnection from './fake-connection' import lolex from 'lolex' describe('#unit PooledConnectionProvider', () => { - let clock - - beforeEach(() => { - if (clock) { - clock.uninstall() - clock = null - } - }) - it('should treat closed connections as invalid', () => { const provider = new PooledConnectionProvider({ id: 0, @@ -52,11 +43,15 @@ describe('#unit PooledConnectionProvider', () => { }) const connection = new FakeConnection().withCreationTimestamp(12) - clock = lolex.install() - clock.setSystemTime(20) - const connectionValid = provider._validateConnection(connection) + const clock = lolex.install() + try { + clock.setSystemTime(20) + const connectionValid = provider._validateConnection(connection) - expect(connectionValid).toBeTruthy() + expect(connectionValid).toBeTruthy() + } finally { + clock.uninstall() + } }) it('should treat old open connections as invalid', () => { @@ -68,10 +63,14 @@ describe('#unit PooledConnectionProvider', () => { }) const connection = new FakeConnection().withCreationTimestamp(5) - clock = lolex.install() - clock.setSystemTime(20) - const connectionValid = provider._validateConnection(connection) + const clock = lolex.install() + try { + clock.setSystemTime(20) + const connectionValid = provider._validateConnection(connection) - expect(connectionValid).toBeFalsy() + expect(connectionValid).toBeFalsy() + } finally { + clock.uninstall() + } }) }) diff --git a/test/internal/node/routing.driver.boltkit.test.js b/test/internal/node/routing.driver.boltkit.test.js index d53291d32..52e859a6c 100644 --- a/test/internal/node/routing.driver.boltkit.test.js +++ b/test/internal/node/routing.driver.boltkit.test.js @@ -27,7 +27,6 @@ import ServerAddress from '../../../src/internal/server-address' describe('#stub-routing routing driver with stub server', () => { let originalTimeout - let clock beforeAll(() => { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL @@ -1586,18 +1585,19 @@ describe('#stub-routing routing driver with stub server', () => { const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') const session = driver.session() + let clock let invocations = 0 const resultPromise = session.readTransaction(tx => { invocations++ if (invocations === 2) { // make retries stop after two invocations - moveTime30SecondsForward() + clock = moveTime30SecondsForward() } return tx.run('MATCH (n) RETURN n.name') }) resultPromise.catch(error => { - removeTimeMocking() // uninstall lolex mocking to make test complete, boltkit uses timers + removeTimeMocking(clock) // uninstall lolex mocking to make test complete, boltkit uses timers expect(error.code).toEqual(SESSION_EXPIRED) expect(invocations).toEqual(2) @@ -1642,18 +1642,19 @@ describe('#stub-routing routing driver with stub server', () => { const driver = boltStub.newDriver('neo4j://127.0.0.1:9001') const session = driver.session() + let clock = null let invocations = 0 const resultPromise = session.writeTransaction(tx => { invocations++ if (invocations === 2) { // make retries stop after two invocations - moveTime30SecondsForward() + clock = moveTime30SecondsForward() } return tx.run("CREATE (n {name:'Bob'})") }) resultPromise.catch(error => { - removeTimeMocking() // uninstall lolex mocking to make test complete, boltStub uses timers + removeTimeMocking(clock) // uninstall lolex mocking to make test complete, boltStub uses timers expect(error.code).toEqual(SESSION_EXPIRED) expect(invocations).toEqual(2) @@ -2939,14 +2940,14 @@ describe('#stub-routing routing driver with stub server', () => { function moveTime30SecondsForward () { const currentTime = Date.now() - clock = lolex.install() + const clock = lolex.install() clock.setSystemTime(currentTime + 30 * 1000 + 1) + return clock } - function removeTimeMocking () { + function removeTimeMocking (clock) { if (clock) { clock.uninstall() - clock = null } } diff --git a/test/internal/routing-util.test.js b/test/internal/routing-util.test.js index 6cce8a18a..ad0c0b0de 100644 --- a/test/internal/routing-util.test.js +++ b/test/internal/routing-util.test.js @@ -33,15 +33,6 @@ import ServerAddress from '../../src/internal/server-address' const ROUTER_ADDRESS = ServerAddress.fromUrl('test.router.com:4242') describe('#unit RoutingUtil', () => { - let clock - - afterEach(() => { - if (clock) { - clock.uninstall() - clock = null - } - }) - it('should return retrieved records when query succeeds', done => { const session = FakeSession.successful({ records: ['foo', 'bar', 'baz'] }) @@ -179,35 +170,46 @@ describe('#unit RoutingUtil', () => { }) it('should parse valid ttl', () => { - clock = lolex.install() - - testValidTtlParsing(100, 5) - testValidTtlParsing(Date.now(), 3600) // 1 hour - testValidTtlParsing(Date.now(), 86400) // 24 hours - testValidTtlParsing(Date.now(), 3628800) // 42 days - testValidTtlParsing(0, 1) - testValidTtlParsing(50, 0) - testValidTtlParsing(Date.now(), 0) + const clock = lolex.install() + try { + testValidTtlParsing(clock, 100, 5) + testValidTtlParsing(clock, Date.now(), 3600) // 1 hour + testValidTtlParsing(clock, Date.now(), 86400) // 24 hours + testValidTtlParsing(clock, Date.now(), 3628800) // 42 days + testValidTtlParsing(clock, 0, 1) + testValidTtlParsing(clock, 50, 0) + testValidTtlParsing(clock, Date.now(), 0) + } finally { + clock.uninstall() + } }) it('should not overflow parsing huge ttl', () => { const record = newRecord({ ttl: Integer.MAX_VALUE }) - clock = lolex.install() - clock.setSystemTime(42) + const clock = lolex.install() + try { + clock.setSystemTime(42) - const expirationTime = parseTtl(record) + const expirationTime = parseTtl(record) - expect(expirationTime).toBe(Integer.MAX_VALUE) + expect(expirationTime).toBe(Integer.MAX_VALUE) + } finally { + clock.uninstall() + } }) it('should return valid value parsing negative ttl', () => { const record = newRecord({ ttl: int(-42) }) - clock = lolex.install() - clock.setSystemTime(42) + const clock = lolex.install() + try { + clock.setSystemTime(42) - const expirationTime = parseTtl(record) + const expirationTime = parseTtl(record) - expect(expirationTime).toBe(Integer.MAX_VALUE) + expect(expirationTime).toBe(Integer.MAX_VALUE) + } finally { + clock.uninstall() + } }) it('should throw when record does not have a ttl entry', done => { @@ -323,7 +325,7 @@ describe('#unit RoutingUtil', () => { }) } - function testValidTtlParsing (currentTime, ttlSeconds) { + function testValidTtlParsing (clock, currentTime, ttlSeconds) { clock.setSystemTime(currentTime) const expectedExpirationTime = currentTime + ttlSeconds * 1000 From 846dfad6a2d92bc7bc00febf4d859f7bec23845e Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Fri, 12 Jul 2019 16:06:18 +0100 Subject: [PATCH 12/13] Add more tests --- .../connection-provider-routing.test.js | 953 +++++++++++++----- 1 file changed, 675 insertions(+), 278 deletions(-) diff --git a/test/internal/connection-provider-routing.test.js b/test/internal/connection-provider-routing.test.js index 9347ecb6f..f5a0b849d 100644 --- a/test/internal/connection-provider-routing.test.js +++ b/test/internal/connection-provider-routing.test.js @@ -19,7 +19,7 @@ import { READ, WRITE } from '../../src/driver' import Integer, { int } from '../../src/integer' -import { SERVICE_UNAVAILABLE, SESSION_EXPIRED } from '../../src/error' +import { newError, SERVICE_UNAVAILABLE, SESSION_EXPIRED } from '../../src/error' import RoutingTable from '../../src/internal/routing-table' import Pool from '../../src/internal/pool' import Logger from '../../src/internal/logger' @@ -29,8 +29,9 @@ import RoutingConnectionProvider from '../../src/internal/connection-provider-ro import { VERSION_IN_DEV } from '../../src/internal/server-version' import Connection from '../../src/internal/connection' import DelegateConnection from '../../src/internal/connection-delegate' +import { Neo4jError } from '../../src' -describe('#unit RoutingConnectionProvider', () => { +fdescribe('#unit RoutingConnectionProvider', () => { let originalTimeout beforeEach(function () { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL @@ -72,12 +73,14 @@ describe('#unit RoutingConnectionProvider', () => { const serverABC = ServerAddress.fromUrl('serverABC') it('can forget address', () => { - const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server2], - [server2, server4] - ) + const connectionProvider = newRoutingConnectionProvider([ + newRoutingTable( + '', + [server1, server2], + [server3, server2], + [server2, server4] + ) + ]) connectionProvider.forget(server2) @@ -91,12 +94,14 @@ describe('#unit RoutingConnectionProvider', () => { }) it('can not forget unknown address', () => { - const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6] - ) + const connectionProvider = newRoutingConnectionProvider([ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6] + ) + ]) connectionProvider.forget(server42) @@ -118,10 +123,14 @@ describe('#unit RoutingConnectionProvider', () => { expectPoolToContain(pool, [server1, server3, server5]) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server2], - [server2, server4], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server2], + [server2, server4] + ) + ], pool ) @@ -133,12 +142,14 @@ describe('#unit RoutingConnectionProvider', () => { }) it('can forget writer address', () => { - const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server2], - [server2, server4] - ) + const connectionProvider = newRoutingConnectionProvider([ + newRoutingTable( + '', + [server1, server2], + [server3, server2], + [server2, server4] + ) + ]) connectionProvider.forgetWriter(server2) @@ -152,12 +163,14 @@ describe('#unit RoutingConnectionProvider', () => { }) it('can not forget unknown writer address', () => { - const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6] - ) + const connectionProvider = newRoutingConnectionProvider([ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6] + ) + ]) connectionProvider.forgetWriter(server42) @@ -173,10 +186,14 @@ describe('#unit RoutingConnectionProvider', () => { it('acquires connection and returns a DelegateConnection', async () => { const pool = newPool() const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6] + ) + ], pool ) @@ -190,10 +207,14 @@ describe('#unit RoutingConnectionProvider', () => { it('acquires read connection with up-to-date routing table', done => { const pool = newPool() const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6] + ) + ], pool ) @@ -213,10 +234,14 @@ describe('#unit RoutingConnectionProvider', () => { it('acquires write connection with up-to-date routing table', done => { const pool = newPool() const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6] + ) + ], pool ) @@ -234,12 +259,14 @@ describe('#unit RoutingConnectionProvider', () => { }) it('throws for illegal access mode', done => { - const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6] - ) + const connectionProvider = newRoutingConnectionProvider([ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6] + ) + ]) connectionProvider.acquireConnection('WRONG', '').catch(error => { expect(error.message).toEqual('Illegal mode WRONG') @@ -256,13 +283,17 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table - { 'server1:7687': updatedRoutingTable } + { '': { 'server1:7687': updatedRoutingTable } } ) connectionProvider.acquireConnection(READ, '').then(connection => { @@ -287,13 +318,17 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table - { 'server1:7687': updatedRoutingTable } + { '': { 'server1:7687': updatedRoutingTable } } ) connectionProvider.acquireConnection(WRITE, '').then(connection => { @@ -318,15 +353,21 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table { - 'server1:7687': null, // returns no routing table - 'server2:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': updatedRoutingTable + } } ) @@ -352,15 +393,21 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table { - 'server1:7687': null, // returns no routing table - 'server2:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': updatedRoutingTable + } } ) @@ -386,15 +433,21 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [], // no readers - [server3, server4], + [ + newRoutingTable( + '', + [server1, server2], + [], // no readers + [server3, server4], + Integer.MAX_VALUE + ) + ], pool, - Integer.MAX_VALUE, { - 'server1:7687': null, // returns no routing table - 'server2:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': updatedRoutingTable + } } ) @@ -420,15 +473,21 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [], // no writers + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [], // no writers + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table { - 'server1:7687': null, // returns no routing table - 'server2:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': updatedRoutingTable + } } ) @@ -447,15 +506,21 @@ describe('#unit RoutingConnectionProvider', () => { it('throws when all routers return nothing while getting read connection', done => { const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], newPool(), - int(0), // expired routing table { - 'server1:7687': null, // returns no routing table - 'server2:7687': null // returns no routing table + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null // returns no routing table + } } ) @@ -467,15 +532,21 @@ describe('#unit RoutingConnectionProvider', () => { it('throws when all routers return nothing while getting write connection', done => { const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], newPool(), - int(0), // expired routing table { - 'server1:7687': null, // returns no routing table - 'server2:7687': null // returns no routing table + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null // returns no routing table + } } ) @@ -493,15 +564,21 @@ describe('#unit RoutingConnectionProvider', () => { [serverC, serverD] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], newPool(), - int(0), // expired routing table { - 'server1:7687': updatedRoutingTable, - 'server2:7687': updatedRoutingTable + '': { + 'server1:7687': updatedRoutingTable, + 'server2:7687': updatedRoutingTable + } } ) @@ -519,15 +596,21 @@ describe('#unit RoutingConnectionProvider', () => { [] // no writers - table can't satisfy connection requirement ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], newPool(), - int(0), // expired routing table { - 'server1:7687': updatedRoutingTable, - 'server2:7687': updatedRoutingTable + '': { + 'server1:7687': updatedRoutingTable, + 'server2:7687': updatedRoutingTable + } } ) @@ -539,12 +622,16 @@ describe('#unit RoutingConnectionProvider', () => { it('throws when stale routing table without routers while getting read connection', done => { const connectionProvider = newRoutingConnectionProvider( - '', - [], // no routers - [server3, server4], - [server5, server6], - newPool(), - int(0) // expired routing table + [ + newRoutingTable( + '', + [], // no routers + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], + newPool() ) connectionProvider.acquireConnection(READ, '').catch(error => { @@ -555,12 +642,16 @@ describe('#unit RoutingConnectionProvider', () => { it('throws when stale routing table without routers while getting write connection', done => { const connectionProvider = newRoutingConnectionProvider( - '', - [], // no routers - [server3, server4], - [server5, server6], - newPool(), - int(0) // expired routing table + [ + newRoutingTable( + '', + [], // no routers + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], + newPool() ) connectionProvider.acquireConnection(WRITE, '').catch(error => { @@ -578,14 +669,20 @@ describe('#unit RoutingConnectionProvider', () => { [serverE, serverF] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table { - 'server1:7687': updatedRoutingTable + '': { + 'server1:7687': updatedRoutingTable + } } ) @@ -611,12 +708,16 @@ describe('#unit RoutingConnectionProvider', () => { it('forgets all routers when they fail while acquiring read connection', done => { const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2, server3], - [server4, server5], - [server6, server7], - newPool(), - int(0) // expired routing table + [ + newRoutingTable( + '', + [server1, server2, server3], + [server4, server5], + [server6, server7], + int(0) // expired routing table + ) + ], + newPool() ) connectionProvider.acquireConnection(READ, '').catch(error => { @@ -634,12 +735,16 @@ describe('#unit RoutingConnectionProvider', () => { it('forgets all routers when they fail while acquiring write connection', done => { const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2, server3], - [server4, server5], - [server6, server7], - newPool(), - int(0) // expired routing table + [ + newRoutingTable( + '', + [server1, server2, server3], + [server4, server5], + [server6, server7], + int(0) // expired routing table + ) + ], + newPool() ) connectionProvider.acquireConnection(WRITE, '').catch(error => { @@ -666,16 +771,22 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server0], // seed router address resolves just to itself - '', - [server1, server2, server3], - [server4, server5], - [server6, server7], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1, server2, server3], + [server4, server5], + [server6, server7], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server2:7687': null, // returns no routing table - 'server3:7687': null, // returns no routing table - 'server0:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null, // returns no routing table + 'server3:7687': null, // returns no routing table + 'server0:7687': updatedRoutingTable + } } ) @@ -708,16 +819,22 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01], // seed router address resolves to a different one - '', - [server1, server2, server3], - [server4, server5], - [server6, server7], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1, server2, server3], + [server4, server5], + [server6, server7], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server2:7687': null, // returns no routing table - 'server3:7687': null, // returns no routing table - 'server01:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null, // returns no routing table + 'server3:7687': null, // returns no routing table + 'server01:7687': updatedRoutingTable + } } ) @@ -750,16 +867,22 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01, server02, server03], // seed router address resolves to 3 different addresses - '', - [server1], - [server2], - [server3], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1], + [server2], + [server3], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server01:7687': null, // returns no routing table - 'server02:7687': null, // returns no routing table - 'server03:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server01:7687': null, // returns no routing table + 'server02:7687': null, // returns no routing table + 'server03:7687': updatedRoutingTable + } } ) @@ -785,16 +908,22 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server0], // seed router address resolves just to itself - '', - [server1, server2, server3], - [server4, server5], - [server6], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1, server2, server3], + [server4, server5], + [server6], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server2:7687': null, // returns no routing table - 'server3:7687': null, // returns no routing table - 'server0:7687': null // returns no routing table + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null, // returns no routing table + 'server3:7687': null, // returns no routing table + 'server0:7687': null // returns no routing table + } } ) @@ -829,15 +958,21 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01], // seed router address resolves to a different one - '', - [server1, server2], - [server3], - [server4], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1, server2], + [server3], + [server4], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server2:7687': null, // returns no routing table - 'server01:7687': null // returns no routing table + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null, // returns no routing table + 'server01:7687': null // returns no routing table + } } ) @@ -872,17 +1007,23 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server02, server01], // seed router address resolves to 2 different addresses - '', - [server1, server2, server3], - [server4], - [server5], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1, server2, server3], + [server4], + [server5], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server2:7687': null, // returns no routing table - 'server3:7687': null, // returns no routing table - 'server01:7687': null, // returns no routing table - 'server02:7687': null // returns no routing table + '': { + 'server1:7687': null, // returns no routing table + 'server2:7687': null, // returns no routing table + 'server3:7687': null, // returns no routing table + 'server01:7687': null, // returns no routing table + 'server02:7687': null // returns no routing table + } } ) @@ -924,13 +1065,19 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server0], // seed router address resolves just to itself - '', - [], // no routers in the known routing table - [server1, server2], - [server3], - Integer.MAX_VALUE, // not expired + [ + newRoutingTable( + '', + [], // no routers in the known routing table + [server1, server2], + [server3], + Integer.MAX_VALUE // not expired + ) + ], { - 'server0:7687': updatedRoutingTable + '': { + 'server0:7687': updatedRoutingTable + } } ) @@ -963,13 +1110,19 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server01], // seed router address resolves to a different one - '', - [], // no routers in the known routing table - [server1, server2], - [server3, server4], - Integer.MAX_VALUE, // not expired + [ + newRoutingTable( + '', + [], // no routers in the known routing table + [server1, server2], + [server3, server4], + Integer.MAX_VALUE // not expired + ) + ], { - 'server01:7687': updatedRoutingTable + '': { + 'server01:7687': updatedRoutingTable + } } ) @@ -1002,15 +1155,21 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server02, server01, server03], // seed router address resolves to 3 different addresses - '', - [], // no routers in the known routing table - [server1], - [server2, server3], - Integer.MAX_VALUE, // not expired + [ + newRoutingTable( + '', + [], // no routers in the known routing table + [server1], + [server2, server3], + Integer.MAX_VALUE // not expired + ) + ], { - 'server01:7687': null, // returns no routing table - 'server02:7687': null, // returns no routing table - 'server03:7687': updatedRoutingTable + '': { + 'server01:7687': null, // returns no routing table + 'server02:7687': null, // returns no routing table + 'server03:7687': updatedRoutingTable + } } ) @@ -1043,16 +1202,22 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server1, server01, server2, server02], // seed router address resolves to 4 different addresses - '', - [server1, server2], - [server3, server4], - [server5, server6], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], { - 'server1:7687': null, // returns no routing table - 'server01:7687': null, // returns no routing table - 'server2:7687': null, // returns no routing table - 'server02:7687': updatedRoutingTable + '': { + 'server1:7687': null, // returns no routing table + 'server01:7687': null, // returns no routing table + 'server2:7687': null, // returns no routing table + 'server02:7687': updatedRoutingTable + } } ) // override default use of seed router @@ -1098,14 +1263,20 @@ describe('#unit RoutingConnectionProvider', () => { [serverC, serverD] ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table { - 'server1:7687': updatedRoutingTable + '': { + 'server1:7687': updatedRoutingTable + } } ) @@ -1124,14 +1295,20 @@ describe('#unit RoutingConnectionProvider', () => { [] // no writers ) const connectionProvider = newRoutingConnectionProvider( - '', - [server1, server2], - [server3, server4], - [server5, server6], + [ + newRoutingTable( + '', + [server1, server2], + [server3, server4], + [server5, server6], + int(0) // expired routing table + ) + ], pool, - int(0), // expired routing table { - 'server1:7687': updatedRoutingTable + '': { + 'server1:7687': updatedRoutingTable + } } ) @@ -1158,17 +1335,23 @@ describe('#unit RoutingConnectionProvider', () => { const connectionProvider = newRoutingConnectionProviderWithSeedRouter( server0, [server02, server01], // seed router address resolves to 2 different addresses - '', - [server1], - [server2, server3], - [server4, server5], - int(0), // expired routing table + [ + newRoutingTable( + '', + [server1], + [server2, server3], + [server4, server5], + int(0) // expired routing table + ) + ], { - 'server1:7687': routingTable1, - 'serverA:7687': routingTable1, - 'serverB:7687': routingTable1, - 'server01:7687': null, // returns no routing table - 'server02:7687': routingTable2 + '': { + 'server1:7687': routingTable1, + 'serverA:7687': routingTable1, + 'serverB:7687': routingTable1, + 'server01:7687': null, // returns no routing table + 'server02:7687': routingTable2 + } } ) // override default use of seed router @@ -1204,26 +1387,244 @@ describe('#unit RoutingConnectionProvider', () => { }) }) }) + + fdescribe('multi-database', () => { + it('should acquire read connection from correct routing table', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + [ + newRoutingTable( + 'databaseA', + [server1, server2], + [server1], + [server2] + ), + newRoutingTable('databaseB', [serverA, serverB], [serverA], [serverB]) + ], + pool + ) + + const conn1 = await connectionProvider.acquireConnection( + READ, + 'databaseA' + ) + expect(conn1 instanceof DelegateConnection).toBeTruthy() + expect(conn1.address).toBe(server1) + + const conn2 = await connectionProvider.acquireConnection( + READ, + 'databaseB' + ) + expect(conn2 instanceof DelegateConnection).toBeTruthy() + expect(conn2.address).toBe(serverA) + }) + + it('should acquire write connection from correct routing table', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + [ + newRoutingTable( + 'databaseA', + [server1, server2], + [server1], + [server2] + ), + newRoutingTable('databaseB', [serverA, serverB], [serverA], [serverB]) + ], + pool + ) + + const conn1 = await connectionProvider.acquireConnection( + WRITE, + 'databaseA' + ) + expect(conn1 instanceof DelegateConnection).toBeTruthy() + expect(conn1.address).toBe(server2) + + const conn2 = await connectionProvider.acquireConnection( + WRITE, + 'databaseB' + ) + expect(conn2 instanceof DelegateConnection).toBeTruthy() + expect(conn2.address).toBe(serverB) + }) + + it('should fail connection acquisition if database is not known', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + [ + newRoutingTable('databaseA', [server1, server2], [server1], [server2]) + ], + pool + ) + + try { + await connectionProvider.acquireConnection(WRITE, 'databaseX') + } catch (error) { + expect(error instanceof Neo4jError).toBeTruthy() + expect(error.code).toBe(SERVICE_UNAVAILABLE) + expect(error.message).toContain( + 'Could not perform discovery. No routing servers available.' + ) + return + } + + expect(false).toBeTruthy('exception expected') + }) + + it('should forget read server from correct routing table on availability error', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + [ + newRoutingTable( + 'databaseA', + [server1, server2, server3], + [server1, server2], + [server3] + ), + newRoutingTable( + 'databaseB', + [serverA, serverB, serverC], + [serverA, serverB], + [serverA, serverC] + ) + ], + pool + ) + + const conn1 = await connectionProvider.acquireConnection( + READ, + 'databaseB' + ) + + // when + conn1._errorHandler.handleAndTransformError( + newError('connection error', SERVICE_UNAVAILABLE), + conn1.address + ) + + expectRoutingTable( + connectionProvider, + 'databaseA', + [server1, server2, server3], + [server1, server2], + [server3] + ) + expectRoutingTable( + connectionProvider, + 'databaseB', + [serverA, serverB, serverC], + [serverB], + [serverC] + ) + }) + + it('should forget write server from correct routing table on availability error', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + [ + newRoutingTable( + 'databaseA', + [server1, server2, server3], + [server1, server2], + [server3] + ), + newRoutingTable( + 'databaseB', + [serverA, serverB, serverC], + [serverA, serverB], + [serverA, serverC] + ) + ], + pool + ) + + const conn1 = await connectionProvider.acquireConnection( + WRITE, + 'databaseB' + ) + + // when + conn1._errorHandler.handleAndTransformError( + newError('connection error', SERVICE_UNAVAILABLE), + conn1.address + ) + + expectRoutingTable( + connectionProvider, + 'databaseA', + [server1, server2, server3], + [server1, server2], + [server3] + ) + expectRoutingTable( + connectionProvider, + 'databaseB', + [serverA, serverB, serverC], + [serverB], + [serverC] + ) + }) + + it('should forget write server from correct routing table on write error', async () => { + const pool = newPool() + const connectionProvider = newRoutingConnectionProvider( + [ + newRoutingTable( + 'databaseA', + [server1, server2, server3], + [server1, server2], + [server3] + ), + newRoutingTable( + 'databaseB', + [serverA, serverB, serverC], + [serverA, serverB], + [serverA, serverC] + ) + ], + pool + ) + + const conn1 = await connectionProvider.acquireConnection( + WRITE, + 'databaseB' + ) + + // when + conn1._errorHandler.handleAndTransformError( + newError('connection error', 'Neo.ClientError.Cluster.NotALeader'), + conn1.address + ) + + expectRoutingTable( + connectionProvider, + 'databaseA', + [server1, server2, server3], + [server1, server2], + [server3] + ) + expectRoutingTable( + connectionProvider, + 'databaseB', + [serverA, serverB, serverC], + [serverA, serverB], + [serverC] + ) + }) + }) }) function newRoutingConnectionProvider ( - database, - routers, - readers, - writers, + routingTables, pool = null, - expirationTime = Integer.MAX_VALUE, - routerToRoutingTable = {} + routerToRoutingTable = { '': {} } ) { const seedRouter = ServerAddress.fromUrl('server-non-existing-seed-router') return newRoutingConnectionProviderWithSeedRouter( seedRouter, [seedRouter], - database, - routers, - readers, - writers, - expirationTime, + routingTables, routerToRoutingTable, pool ) @@ -1232,12 +1633,8 @@ function newRoutingConnectionProvider ( function newRoutingConnectionProviderWithSeedRouter ( seedRouter, seedRouterResolved, - database, - routers, - readers, - writers, - expirationTime = Integer.MAX_VALUE, - routerToRoutingTable = {}, + routingTables, + routerToRoutingTable = { '': {} }, connectionPool = null ) { const pool = connectionPool || newPool() @@ -1250,18 +1647,14 @@ function newRoutingConnectionProviderWithSeedRouter ( log: Logger.noOp() }) connectionProvider._connectionPool = pool - connectionProvider._routingTables[database] = new RoutingTable({ - database, - routers, - readers, - writers, - expirationTime + routingTables.forEach(r => { + connectionProvider._routingTables[r.database] = r }) connectionProvider._rediscovery = new FakeRediscovery(routerToRoutingTable) connectionProvider._hostNameResolver = new FakeDnsResolver(seedRouterResolved) - if (expirationTime === Integer.ZERO) { - connectionProvider._useSeedRouter = false - } + connectionProvider._useSeedRouter = routingTables.every( + r => r.expirationTime !== Integer.ZERO + ) return connectionProvider } @@ -1353,7 +1746,11 @@ class FakeRediscovery { } lookupRoutingTableOnRouter (ignored, database, router) { - return Promise.resolve(this._routerToRoutingTable[router.asKey()]) + const table = this._routerToRoutingTable[database || ''] + if (table) { + return Promise.resolve(table[router.asKey()]) + } + return Promise.resolve(null) } } From 5f3f5a25e8c4b46072465725c03ae459f1074579 Mon Sep 17 00:00:00 2001 From: Ali Ince Date: Fri, 12 Jul 2019 16:17:11 +0100 Subject: [PATCH 13/13] Remove test focus --- test/internal/connection-provider-routing.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/internal/connection-provider-routing.test.js b/test/internal/connection-provider-routing.test.js index f5a0b849d..df320d999 100644 --- a/test/internal/connection-provider-routing.test.js +++ b/test/internal/connection-provider-routing.test.js @@ -31,7 +31,7 @@ import Connection from '../../src/internal/connection' import DelegateConnection from '../../src/internal/connection-delegate' import { Neo4jError } from '../../src' -fdescribe('#unit RoutingConnectionProvider', () => { +describe('#unit RoutingConnectionProvider', () => { let originalTimeout beforeEach(function () { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL @@ -1388,7 +1388,7 @@ fdescribe('#unit RoutingConnectionProvider', () => { }) }) - fdescribe('multi-database', () => { + describe('multi-database', () => { it('should acquire read connection from correct routing table', async () => { const pool = newPool() const connectionProvider = newRoutingConnectionProvider(