From 9fc2c0472dde11e49c601efe2288015dd6bae462 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Wed, 5 Feb 2025 09:09:06 -0500 Subject: [PATCH 1/8] Implementation. Needs tests. --- packages/database/src/api/Database.ts | 19 ++++++++++++++----- packages/database/src/core/RepoInfo.ts | 12 +++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 72ae85c08a1..b23d3502ffb 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -27,6 +27,7 @@ import { Provider } from '@firebase/component'; import { getModularInstance, createMockUserToken, + deepEqual, EmulatorMockTokenOptions, getDefaultEmulatorHostnameAndPort } from '@firebase/util'; @@ -85,11 +86,10 @@ let useRestClient = false; function repoManagerApplyEmulatorSettings( repo: Repo, host: string, - port: number, tokenProvider?: AuthTokenProvider ): void { repo.repoInfo_ = new RepoInfo( - `${host}:${port}`, + host, /* secure= */ false, repo.repoInfo_.namespace, repo.repoInfo_.webSocketOnly, @@ -350,13 +350,22 @@ export function connectDatabaseEmulator( ): void { db = getModularInstance(db); db._checkNotDeleted('useEmulator'); + const hostAndPort = `${host}:${port}`; + const repo = db._repoInternal; if (db._instanceStarted) { + // If the instance has already been started, and this function is called again with the same + // parameters, then silently return. If the parameters differ then assert. + if ( + hostAndPort === repo.repoInfo_.host && + deepEqual(options, repo.repoInfo_.emulatorOptions) + ) { + return; + } fatal( - 'Cannot call useEmulator() after instance has already been initialized.' + 'connectDatabaseEmulator() cannot alter the emulator configuration after the database instance has started.' ); } - const repo = db._repoInternal; let tokenProvider: EmulatorTokenProvider | undefined = undefined; if (repo.repoInfo_.nodeAdmin) { if (options.mockUserToken) { @@ -374,7 +383,7 @@ export function connectDatabaseEmulator( } // Modify the repo to apply emulator settings - repoManagerApplyEmulatorSettings(repo, host, port, tokenProvider); + repoManagerApplyEmulatorSettings(repo, host, tokenProvider); } /** diff --git a/packages/database/src/core/RepoInfo.ts b/packages/database/src/core/RepoInfo.ts index 9d4c1abe36b..025b746b951 100644 --- a/packages/database/src/core/RepoInfo.ts +++ b/packages/database/src/core/RepoInfo.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { assert } from '@firebase/util'; +import { assert, EmulatorMockTokenOptions } from '@firebase/util'; import { LONG_POLLING, WEBSOCKET } from '../realtime/Constants'; @@ -28,6 +28,9 @@ import { each } from './util/util'; export class RepoInfo { private _host: string; private _domain: string; + private _emulatorOptions: { + mockUserToken?: EmulatorMockTokenOptions | string; + }; internalHost: string; /** @@ -50,6 +53,7 @@ export class RepoInfo { ) { this._host = host.toLowerCase(); this._domain = this._host.substr(this._host.indexOf('.') + 1); + this._emulatorOptions = {}; this.internalHost = (PersistentStorage.get('host:' + host) as string) || this._host; } @@ -78,6 +82,12 @@ export class RepoInfo { } } + get emulatorOptions(): { + mockUserToken?: EmulatorMockTokenOptions | string; + } { + return this._emulatorOptions; + } + toString(): string { let str = this.toURLString(); if (this.persistenceKey) { From 4c24b18c5d8f518e1f40f459186a1ef291d20577 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Wed, 5 Feb 2025 11:10:18 -0500 Subject: [PATCH 2/8] fix hostAndPort --- packages/database/src/api/Database.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index b23d3502ffb..1b38bac8383 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -383,7 +383,7 @@ export function connectDatabaseEmulator( } // Modify the repo to apply emulator settings - repoManagerApplyEmulatorSettings(repo, host, tokenProvider); + repoManagerApplyEmulatorSettings(repo, hostAndPort, tokenProvider); } /** From fc4f2b9a7ce70dfc9c2ec236193631792596619e Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Wed, 5 Feb 2025 14:56:26 -0500 Subject: [PATCH 3/8] Added integration tests --- .../database/test/exp/integration.test.ts | 39 +++++++++++++++++++ packages/database/test/helpers/util.ts | 4 ++ 2 files changed, 43 insertions(+) diff --git a/packages/database/test/exp/integration.test.ts b/packages/database/test/exp/integration.test.ts index adf5094f222..642543214cc 100644 --- a/packages/database/test/exp/integration.test.ts +++ b/packages/database/test/exp/integration.test.ts @@ -20,6 +20,7 @@ import { Deferred } from '@firebase/util'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; +import { connectDatabaseEmulator } from '../../src/api/Database'; import { child, get, @@ -48,6 +49,7 @@ import { DATABASE_URL, getFreshRepo, getRWRefs, + isEmulatorActive, waitFor, waitUntil, writeAndValidate @@ -138,6 +140,43 @@ describe('Database@exp Tests', () => { unsubscribe(); }); + it('can connected to emulator', async () => { + if (isEmulatorActive()) { + const db = getDatabase(defaultApp); + connectDatabaseEmulator(db, 'localhost', 9000); + await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); + } + }); + + it('can chnage emulator config before network operations', async () => { + if (isEmulatorActive()) { + const db = getDatabase(defaultApp); + connectDatabaseEmulator(db, 'localhost', 9001); + connectDatabaseEmulator(db, 'localhost', 9000); + await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); + } + }); + + it('can connected to emulator after network operations with same parameters', async () => { + if (isEmulatorActive()) { + const db = getDatabase(defaultApp); + connectDatabaseEmulator(db, 'localhost', 9000); + await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); + connectDatabaseEmulator(db, 'localhost', 9000); + } + }); + + it('cannot connect to emulator after network operations with different parameters', async () => { + if (isEmulatorActive()) { + const db = getDatabase(defaultApp); + connectDatabaseEmulator(db, 'localhost', 9000); + await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); + expect(() => { + connectDatabaseEmulator(db, 'localhost', 9001); + }).to.throw(); + } + }); + it('can properly handle unknown deep merges', async () => { // Note: This test requires `testIndex` to be added as an index. // Please run `yarn test:setup` to ensure that this gets added. diff --git a/packages/database/test/helpers/util.ts b/packages/database/test/helpers/util.ts index 73eb04a8c5e..f2712b8a4f9 100644 --- a/packages/database/test/helpers/util.ts +++ b/packages/database/test/helpers/util.ts @@ -143,3 +143,7 @@ export async function waitUntil(cb: () => boolean, maxRetries = 5) { } }); } + +export function isEmulatorActive(): boolean { + return USE_EMULATOR; +} From 35e65451ad9d21e28e1e6cbe46c1824dde841456 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Wed, 5 Feb 2025 15:05:19 -0500 Subject: [PATCH 4/8] update comment in connectDatabaseEmulator --- packages/database/src/api/Database.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 1b38bac8383..2e08f211b68 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -353,8 +353,8 @@ export function connectDatabaseEmulator( const hostAndPort = `${host}:${port}`; const repo = db._repoInternal; if (db._instanceStarted) { - // If the instance has already been started, and this function is called again with the same - // parameters, then silently return. If the parameters differ then assert. + // If the instance has already been started, then silenty fail if this function is called again + // with the same parameters. If the parameters differ then assert. if ( hostAndPort === repo.repoInfo_.host && deepEqual(options, repo.repoInfo_.emulatorOptions) From d80841d7335e874125e9d4c8149189e484819e82 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Wed, 5 Feb 2025 16:05:24 -0500 Subject: [PATCH 5/8] test with dynamic port string --- packages/database/test/exp/integration.test.ts | 16 ++++++++++------ packages/database/test/helpers/util.ts | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/database/test/exp/integration.test.ts b/packages/database/test/exp/integration.test.ts index 642543214cc..4e0a5d4b640 100644 --- a/packages/database/test/exp/integration.test.ts +++ b/packages/database/test/exp/integration.test.ts @@ -47,6 +47,7 @@ import { EventAccumulatorFactory } from '../helpers/EventAccumulator'; import { DATABASE_ADDRESS, DATABASE_URL, + EMULATOR_PORT, getFreshRepo, getRWRefs, isEmulatorActive, @@ -143,7 +144,7 @@ describe('Database@exp Tests', () => { it('can connected to emulator', async () => { if (isEmulatorActive()) { const db = getDatabase(defaultApp); - connectDatabaseEmulator(db, 'localhost', 9000); + connectDatabaseEmulator(db, 'localhost', parseInt(EMULATOR_PORT, 10)); await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); } }); @@ -151,8 +152,9 @@ describe('Database@exp Tests', () => { it('can chnage emulator config before network operations', async () => { if (isEmulatorActive()) { const db = getDatabase(defaultApp); - connectDatabaseEmulator(db, 'localhost', 9001); - connectDatabaseEmulator(db, 'localhost', 9000); + const port = parseInt(EMULATOR_PORT, 10); + connectDatabaseEmulator(db, 'localhost', port + 1); + connectDatabaseEmulator(db, 'localhost', port); await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); } }); @@ -160,16 +162,18 @@ describe('Database@exp Tests', () => { it('can connected to emulator after network operations with same parameters', async () => { if (isEmulatorActive()) { const db = getDatabase(defaultApp); - connectDatabaseEmulator(db, 'localhost', 9000); + const port = parseInt(EMULATOR_PORT, 10); + connectDatabaseEmulator(db, 'localhost', port); await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); - connectDatabaseEmulator(db, 'localhost', 9000); + connectDatabaseEmulator(db, 'localhost', port); } }); it('cannot connect to emulator after network operations with different parameters', async () => { if (isEmulatorActive()) { const db = getDatabase(defaultApp); - connectDatabaseEmulator(db, 'localhost', 9000); + const port = parseInt(EMULATOR_PORT, 10); + connectDatabaseEmulator(db, 'localhost', port); await get(refFromURL(db, `${DATABASE_ADDRESS}/foo/bar`)); expect(() => { connectDatabaseEmulator(db, 'localhost', 9001); diff --git a/packages/database/test/helpers/util.ts b/packages/database/test/helpers/util.ts index f2712b8a4f9..883b6632b38 100644 --- a/packages/database/test/helpers/util.ts +++ b/packages/database/test/helpers/util.ts @@ -33,7 +33,7 @@ import { EventAccumulator } from './EventAccumulator'; // eslint-disable-next-line @typescript-eslint/no-require-imports export const TEST_PROJECT = require('../../../../config/project.json'); -const EMULATOR_PORT = process.env.RTDB_EMULATOR_PORT; +export const EMULATOR_PORT = process.env.RTDB_EMULATOR_PORT; const EMULATOR_NAMESPACE = process.env.RTDB_EMULATOR_NAMESPACE; const USE_EMULATOR = !!EMULATOR_PORT; From dffe5b4272deaa33ade026eda21360b9250a8b52 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Thu, 6 Feb 2025 09:20:58 -0500 Subject: [PATCH 6/8] Disable tests to debug CI errors --- packages/database/test/exp/integration.test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/database/test/exp/integration.test.ts b/packages/database/test/exp/integration.test.ts index 4e0a5d4b640..33ceb5032b0 100644 --- a/packages/database/test/exp/integration.test.ts +++ b/packages/database/test/exp/integration.test.ts @@ -20,7 +20,7 @@ import { Deferred } from '@firebase/util'; import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import { connectDatabaseEmulator } from '../../src/api/Database'; +//import { connectDatabaseEmulator } from '../../src/api/Database'; import { child, get, @@ -47,10 +47,10 @@ import { EventAccumulatorFactory } from '../helpers/EventAccumulator'; import { DATABASE_ADDRESS, DATABASE_URL, - EMULATOR_PORT, + //EMULATOR_PORT, getFreshRepo, getRWRefs, - isEmulatorActive, + //isEmulatorActive, waitFor, waitUntil, writeAndValidate @@ -141,7 +141,7 @@ describe('Database@exp Tests', () => { unsubscribe(); }); - it('can connected to emulator', async () => { + /*it('can connected to emulator', async () => { if (isEmulatorActive()) { const db = getDatabase(defaultApp); connectDatabaseEmulator(db, 'localhost', parseInt(EMULATOR_PORT, 10)); @@ -180,6 +180,7 @@ describe('Database@exp Tests', () => { }).to.throw(); } }); + */ it('can properly handle unknown deep merges', async () => { // Note: This test requires `testIndex` to be added as an index. From 447b94f58652f37bcc0aaedb743f0a996e894464 Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Thu, 6 Feb 2025 09:30:52 -0500 Subject: [PATCH 7/8] Revert more for CI failures --- packages/database/src/api/Database.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 2e08f211b68..17f59e6da26 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -27,7 +27,7 @@ import { Provider } from '@firebase/component'; import { getModularInstance, createMockUserToken, - deepEqual, + //deepEqual, DEDB replace EmulatorMockTokenOptions, getDefaultEmulatorHostnameAndPort } from '@firebase/util'; @@ -86,10 +86,12 @@ let useRestClient = false; function repoManagerApplyEmulatorSettings( repo: Repo, host: string, + port: number, // DEDB remove tokenProvider?: AuthTokenProvider ): void { repo.repoInfo_ = new RepoInfo( - host, + //host, DDB replace + `${host}:${port}`, // DEDB remove /* secure= */ false, repo.repoInfo_.namespace, repo.repoInfo_.webSocketOnly, @@ -352,11 +354,12 @@ export function connectDatabaseEmulator( db._checkNotDeleted('useEmulator'); const hostAndPort = `${host}:${port}`; const repo = db._repoInternal; + /* if (db._instanceStarted) { // If the instance has already been started, then silenty fail if this function is called again // with the same parameters. If the parameters differ then assert. if ( - hostAndPort === repo.repoInfo_.host && + hostAndPort === db._repoInternal.repoInfo_.host && deepEqual(options, repo.repoInfo_.emulatorOptions) ) { return; @@ -365,6 +368,7 @@ export function connectDatabaseEmulator( 'connectDatabaseEmulator() cannot alter the emulator configuration after the database instance has started.' ); } + */ let tokenProvider: EmulatorTokenProvider | undefined = undefined; if (repo.repoInfo_.nodeAdmin) { @@ -383,7 +387,9 @@ export function connectDatabaseEmulator( } // Modify the repo to apply emulator settings - repoManagerApplyEmulatorSettings(repo, hostAndPort, tokenProvider); + //repoManagerApplyEmulatorSettings(repo, hostAndPort, tokenProvider); // DDB Replace + repoManagerApplyEmulatorSettings(repo, host, port, tokenProvider); // DDB Remove + } /** From cf00ae33d4976acfa59772f5067f2a9ea87c9d3c Mon Sep 17 00:00:00 2001 From: DellaBitta Date: Thu, 6 Feb 2025 09:39:31 -0500 Subject: [PATCH 8/8] Revert RepoInfo.ts, too --- packages/database/src/core/RepoInfo.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/database/src/core/RepoInfo.ts b/packages/database/src/core/RepoInfo.ts index 025b746b951..53da592cf49 100644 --- a/packages/database/src/core/RepoInfo.ts +++ b/packages/database/src/core/RepoInfo.ts @@ -15,7 +15,10 @@ * limitations under the License. */ -import { assert, EmulatorMockTokenOptions } from '@firebase/util'; +import { + assert, + //EmulatorMockTokenOptions //DEDB replace +} from '@firebase/util'; import { LONG_POLLING, WEBSOCKET } from '../realtime/Constants'; @@ -28,9 +31,12 @@ import { each } from './util/util'; export class RepoInfo { private _host: string; private _domain: string; + /* + //DEDB replace private _emulatorOptions: { mockUserToken?: EmulatorMockTokenOptions | string; }; + */ internalHost: string; /** @@ -53,7 +59,7 @@ export class RepoInfo { ) { this._host = host.toLowerCase(); this._domain = this._host.substr(this._host.indexOf('.') + 1); - this._emulatorOptions = {}; + // this._emulatorOptions = {}; //DEDB replace this.internalHost = (PersistentStorage.get('host:' + host) as string) || this._host; } @@ -82,11 +88,14 @@ export class RepoInfo { } } + /* + //DEDB replace get emulatorOptions(): { mockUserToken?: EmulatorMockTokenOptions | string; } { return this._emulatorOptions; } + */ toString(): string { let str = this.toURLString();