From a76de344c0c6faa29677d0ab3c96bf598aae99b0 Mon Sep 17 00:00:00 2001 From: Cheng-Chin Chiang Date: Thu, 13 Aug 2026 19:19:13 +0800 Subject: [PATCH 1/6] Cover the session type and platform strings in the default access test --- ICD_test_stages/file_browser.tests | 1 + src/test/ACCESS_CARTA_DEFAULT.test.ts | 56 ++++++++++++++++++++------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/ICD_test_stages/file_browser.tests b/ICD_test_stages/file_browser.tests index be92334..9da8c12 100644 --- a/ICD_test_stages/file_browser.tests +++ b/ICD_test_stages/file_browser.tests @@ -1,4 +1,5 @@ src/test/ACCESS_WEBSOCKET.test.ts +src/test/ACCESS_CARTA_DEFAULT.test.ts src/test/GET_FILELIST_ROOTPATH_CONCURRENT.test.ts src/test/FILEINFO_FITS_MULTIHDU.test.ts src/test/FILEINFO_EXCEPTIONS.test.ts diff --git a/src/test/ACCESS_CARTA_DEFAULT.test.ts b/src/test/ACCESS_CARTA_DEFAULT.test.ts index b025443..f5b62ba 100644 --- a/src/test/ACCESS_CARTA_DEFAULT.test.ts +++ b/src/test/ACCESS_CARTA_DEFAULT.test.ts @@ -5,38 +5,68 @@ import { MessageController } from './MessageController'; let testServerUrl = config.serverURL0; let connectTimeout = config.timeout.connection; +const platformStringKeys = ['release_info', 'deployment', 'architecture', 'platform']; + describe(`ACCESS_CARTA_DEFAULT tests: Testing connections to the backend`, () => { describe(`create a Websocket connection and receive REGISTER_VIEWER_ACK`, () => { let RegisterViewerAckResponse: CARTA.IRegisterViewerAck; const msgController = MessageController.Instance; - test(`Receive REGISTER_VIEWER_ACK`, async () => { - RegisterViewerAckResponse = await msgController.connect(testServerUrl); + test( + `Receive REGISTER_VIEWER_ACK`, + async () => { + RegisterViewerAckResponse = await msgController.connect(testServerUrl); + }, + connectTimeout + ); + + test('REGISTER_VIEWER_ACK.success = True', () => { + expect(RegisterViewerAckResponse.success).toBe(true); }); - test(`REGISTER_VIEWER_ACK.message is not empty`, () => { - expect(RegisterViewerAckResponse.message).toBeDefined(); + test('REGISTER_VIEWER_ACK.session_id is assigned by the backend', () => { + expect(RegisterViewerAckResponse.sessionId).toBeDefined(); + expect(RegisterViewerAckResponse.sessionId).not.toEqual(0); + console.log(`Registered session ID is ${RegisterViewerAckResponse.sessionId} @${new Date()}`); }); - test(`REGISTER_VIEWER_ACK.platformStrings is not empty`, () => { - expect(RegisterViewerAckResponse.platformStrings).toBeDefined(); + test(`REGISTER_VIEWER_ACK.session_type = "CARTA.SessionType.NEW"`, () => { + expect(RegisterViewerAckResponse.sessionType).toBe(CARTA.SessionType.NEW); }); - test('REGISTER_VIEWER_ACK.success = True', () => { - expect(RegisterViewerAckResponse.success).toBe(true); + test(`REGISTER_VIEWER_ACK.message is a non-empty string reporting the assigned session id`, () => { + expect(RegisterViewerAckResponse.message).toBeDefined(); + expect(RegisterViewerAckResponse.message).not.toEqual(''); + expect(RegisterViewerAckResponse.message).toContain(`${RegisterViewerAckResponse.sessionId}`); }); - test('REGISTER_VIEWER_ACK.session_id is not None', () => { - expect(RegisterViewerAckResponse.sessionId).toBeDefined(); - console.log(`Registered session ID is ${RegisterViewerAckResponse.sessionId} @${new Date()}`); + test(`REGISTER_VIEWER_ACK.server_feature_flags does not report READ_ONLY`, () => { + expect(RegisterViewerAckResponse.serverFeatureFlags).toBeDefined(); + expect(RegisterViewerAckResponse.serverFeatureFlags! & CARTA.ServerFeatureFlags.READ_ONLY).toEqual(0); + console.log(`Server feature flags are ${RegisterViewerAckResponse.serverFeatureFlags}`); + }); + + test(`REGISTER_VIEWER_ACK.platform_strings has ${platformStringKeys.join(', ')}`, () => { + const platformStrings = RegisterViewerAckResponse.platformStrings!; + expect(platformStrings).toBeDefined(); + platformStringKeys.forEach((key) => { + expect(platformStrings[key]).toBeDefined(); + expect(platformStrings[key]).not.toEqual(''); + }); + expect(['macOS', 'Linux']).toContain(platformStrings['platform']); + console.log(`Platform strings are ${JSON.stringify(platformStrings)}`); }); test('REGISTER_VIEWER_ACK.user_preferences = None', () => { - expect(RegisterViewerAckResponse.userPreferences).toMatchObject({}); + expect(RegisterViewerAckResponse.serverFeatureFlags! & CARTA.ServerFeatureFlags.USER_PREFERENCES).toEqual( + 0 + ); + expect(RegisterViewerAckResponse.userPreferences).toEqual({}); }); test('REGISTER_VIEWER_ACK.user_layouts = None', () => { - expect(RegisterViewerAckResponse.userLayouts).toMatchObject({}); + expect(RegisterViewerAckResponse.serverFeatureFlags! & CARTA.ServerFeatureFlags.USER_LAYOUTS).toEqual(0); + expect(RegisterViewerAckResponse.userLayouts).toEqual({}); }); afterAll(async () => { From 8f32a54c7487f187da296c66b1555648018aa8f3 Mon Sep 17 00:00:00 2001 From: Cheng-Chin Chiang Date: Thu, 13 Aug 2026 19:22:53 +0800 Subject: [PATCH 2/6] Update the document for the test ACCESS_CARTA_DEFAULT --- docs/source/access_carta.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/source/access_carta.rst b/docs/source/access_carta.rst index ad9440a..72a331b 100644 --- a/docs/source/access_carta.rst +++ b/docs/source/access_carta.rst @@ -46,15 +46,19 @@ This test verifies that a default connection to the backend succeeds and returns - REGISTER_VIEWER_ACK.success = True - - REGISTER_VIEWER_ACK.session_id is not None + - REGISTER_VIEWER_ACK.session_id is assigned by the backend (not 0) - - REGISTER_VIEWER_ACK.message is not empty + - REGISTER_VIEWER_ACK.session_type = CARTA.SessionType.NEW - - REGISTER_VIEWER_ACK.platformStrings is not empty + - REGISTER_VIEWER_ACK.message is a non-empty string reporting the assigned session_id - - REGISTER_VIEWER_ACK.user_preferences = None (empty object) + - REGISTER_VIEWER_ACK.server_feature_flags does not have the READ_ONLY bit set - - REGISTER_VIEWER_ACK.user_layouts = None (empty object) + - REGISTER_VIEWER_ACK.platform_strings has non-empty release_info, deployment, architecture and platform entries, where platform is "macOS" or "Linux" + + - REGISTER_VIEWER_ACK.user_preferences = None (empty object), and server_feature_flags does not have the USER_PREFERENCES bit set + + - REGISTER_VIEWER_ACK.user_layouts = None (empty object), and server_feature_flags does not have the USER_LAYOUTS bit set ACCESS_CARTA_DEFAULT_CONCURRENT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From e7dfcb79923a3973c60975129d81ecc9b3b5e4f3 Mon Sep 17 00:00:00 2001 From: Cheng-Chin Chiang Date: Thu, 13 Aug 2026 19:31:55 +0800 Subject: [PATCH 3/6] Register the clients in parallel in the concurrent access test --- ICD_test_stages/file_browser.tests | 1 + docs/source/access_carta.rst | 10 ++- .../ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts | 80 ++++++++++++------- src/test/MessageControllerConcurrent.ts | 2 +- 4 files changed, 57 insertions(+), 36 deletions(-) diff --git a/ICD_test_stages/file_browser.tests b/ICD_test_stages/file_browser.tests index 9da8c12..c5d9eaf 100644 --- a/ICD_test_stages/file_browser.tests +++ b/ICD_test_stages/file_browser.tests @@ -1,5 +1,6 @@ src/test/ACCESS_WEBSOCKET.test.ts src/test/ACCESS_CARTA_DEFAULT.test.ts +src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts src/test/GET_FILELIST_ROOTPATH_CONCURRENT.test.ts src/test/FILEINFO_FITS_MULTIHDU.test.ts src/test/FILEINFO_EXCEPTIONS.test.ts diff --git a/docs/source/access_carta.rst b/docs/source/access_carta.rst index 72a331b..53789ab 100644 --- a/docs/source/access_carta.rst +++ b/docs/source/access_carta.rst @@ -65,7 +65,7 @@ ACCESS_CARTA_DEFAULT_CONCURRENT See the `source code `__. -This test verifies that multiple concurrent connections (10 clients) to the backend all succeed, each receiving a unique session ID. +This test verifies that multiple concurrent connections (10 clients) to the backend all succeed, each receiving a unique session ID. The 10 clients connect simultaneously, so the backend registers them in parallel rather than one after another. 1. 10 clients each send: **REGISTER_VIEWER** (``RegisterViewer``) @@ -80,15 +80,17 @@ This test verifies that multiple concurrent connections (10 clients) to the back - REGISTER_VIEWER_ACK.success = True - - REGISTER_VIEWER_ACK.session_id is not None + - REGISTER_VIEWER_ACK.session_id is assigned by the backend (not 0) - REGISTER_VIEWER_ACK.session_id is unique across all connections - REGISTER_VIEWER_ACK.session_type = CARTA.SessionType.NEW - - REGISTER_VIEWER_ACK.message is not empty + - REGISTER_VIEWER_ACK.message is a non-empty string reporting its own session_id + + - REGISTER_VIEWER_ACK.platform_strings has non-empty release_info, deployment, architecture and platform entries - - REGISTER_VIEWER_ACK.platformStrings is not empty + - REGISTER_VIEWER_ACK.server_feature_flags and REGISTER_VIEWER_ACK.platform_strings are identical across all connections - REGISTER_VIEWER_ACK.user_preferences = None (empty object) diff --git a/src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts b/src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts index ed926d6..7b1aa9c 100644 --- a/src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts +++ b/src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts @@ -7,73 +7,91 @@ let testServerUrl = config.serverURL0; let connectTimeout = config.timeout.connection; let testNumber = config.repeat.concurrent; -let client: BackendService[] = Array(testNumber); -let RegisterViewerAckResponse: CARTA.RegisterViewerAck[] = new Array(testNumber); +const platformStringKeys = ['release_info', 'deployment', 'architecture', 'platform']; + +let client: BackendService[] = []; +let RegisterViewerAckResponse: CARTA.IRegisterViewerAck[] = []; describe(`ACCESS_CARTA_DEFAULT_CONCURRENT: Testing multiple concurrent connections to the backend.`, () => { test( - `establish ${testNumber} connections to "${testServerUrl}".`, + `establish ${testNumber} concurrent connections to "${testServerUrl}".`, async () => { - for (let i = 0; i < client.length; i++) { - client[i] = new BackendService(); - RegisterViewerAckResponse[i] = await client[i].connect(testServerUrl); - expect(client[i].connection.readyState).toBe(WebSocket.OPEN); - } + client = Array.from({ length: testNumber }, () => new BackendService()); + RegisterViewerAckResponse = await Promise.all(client.map((item) => item.connect(testServerUrl))); + client.forEach((item) => { + expect(item.connection.readyState).toBe(WebSocket.OPEN); + }); }, connectTimeout ); test(`assert every REGISTER_VIEWER_ACK.success is True.`, () => { - RegisterViewerAckResponse.forEach((item, index, array) => { + RegisterViewerAckResponse.forEach((item) => { expect(item.success).toBe(true); }); }); - test(`assert every REGISTER_VIEWER_ACK.session_id is not None.`, () => { - RegisterViewerAckResponse.forEach((item, index, array) => { + test(`assert every REGISTER_VIEWER_ACK.session_id is assigned by the backend.`, () => { + RegisterViewerAckResponse.forEach((item) => { expect(item.sessionId).toBeDefined(); + expect(item.sessionId).not.toEqual(0); }); }); - test(`assert every REGISTER_VIEWER_ACK.message is not empty`, () => { - RegisterViewerAckResponse.forEach((item, index, array) => { - expect(item.message).toBeDefined(); + test(`assert every REGISTER_VIEWER_ACK.session_id is unique.`, () => { + const sessionIds = RegisterViewerAckResponse.map((item) => item.sessionId); + console.log(`Registered session IDs are ${sessionIds}`); + expect(new Set(sessionIds).size).toEqual(testNumber); + }); + + test(`assert every REGISTER_VIEWER_ACK.session_type is "CARTA.SessionType.NEW".`, () => { + RegisterViewerAckResponse.forEach((item) => { + expect(item.sessionType).toEqual(CARTA.SessionType.NEW); }); }); - test(`assert every REGISTER_VIEWER_ACK.platformStrings is not empty`, () => { - RegisterViewerAckResponse.forEach((item, index, array) => { - expect(item.platformStrings).toBeDefined(); + test(`assert every REGISTER_VIEWER_ACK.message reports its own session_id`, () => { + RegisterViewerAckResponse.forEach((item) => { + expect(item.message).toBeDefined(); + expect(item.message).not.toEqual(''); + expect(item.message).toContain(`${item.sessionId}`); }); }); - test(`assert every REGISTER_VIEWER_ACK.session_id is unique.`, () => { - RegisterViewerAckResponse.forEach((item, index, array) => { - expect(array.filter((f) => f.sessionId === item.sessionId).length).toEqual(1); + test(`assert every REGISTER_VIEWER_ACK.platform_strings has ${platformStringKeys.join(', ')}`, () => { + RegisterViewerAckResponse.forEach((item) => { + const platformStrings = item.platformStrings!; + expect(platformStrings).toBeDefined(); + platformStringKeys.forEach((key) => { + expect(platformStrings[key]).toBeDefined(); + expect(platformStrings[key]).not.toEqual(''); + }); }); }); - test(`assert every REGISTER_VIEWER_ACK.session_type is "CARTA.SessionType.NEW".`, () => { - RegisterViewerAckResponse.forEach((item, index, array) => { - expect(item.sessionType).toEqual(CARTA.SessionType.NEW); + test(`assert every REGISTER_VIEWER_ACK reports the same server information`, () => { + const firstResponse = RegisterViewerAckResponse[0]; + RegisterViewerAckResponse.forEach((item) => { + expect(item.serverFeatureFlags).toEqual(firstResponse.serverFeatureFlags); + expect(item.platformStrings).toEqual(firstResponse.platformStrings); }); }); test('assert every REGISTER_VIEWER_ACK.user_preferences = None', () => { - RegisterViewerAckResponse.forEach((item, index, array) => { - expect(item.userPreferences).toMatchObject({}); + RegisterViewerAckResponse.forEach((item) => { + expect(item.userPreferences).toEqual({}); }); }); test('assert every REGISTER_VIEWER_ACK.user_layouts = None', () => { - RegisterViewerAckResponse.forEach((item, index, array) => { - expect(item.userLayouts).toMatchObject({}); + RegisterViewerAckResponse.forEach((item) => { + expect(item.userLayouts).toEqual({}); }); }); - afterAll(async () => { - for (let i = 0; i < client.length; i++) { - await client[i].closeConnection(); - } + afterAll(() => { + client.forEach((item) => { + item.closeConnection(); + }); }); }); diff --git a/src/test/MessageControllerConcurrent.ts b/src/test/MessageControllerConcurrent.ts index ef5c3e3..243705b 100644 --- a/src/test/MessageControllerConcurrent.ts +++ b/src/test/MessageControllerConcurrent.ts @@ -69,7 +69,7 @@ export class BackendService { public serverFeatureFlags: number; public serverUrl: string; - private connection: WebSocket; + public connection: WebSocket; private deferredMap: Map>; private eventCounter: number; From 7ca43246a1fae4c2957572a4484d3dc30e8ce6c0 Mon Sep 17 00:00:00 2001 From: Cheng-Chin Chiang Date: Thu, 13 Aug 2026 19:36:51 +0800 Subject: [PATCH 4/6] Cover the message and platform strings in the known session access test --- ICD_test_stages/file_browser.tests | 1 + docs/source/access_carta.rst | 8 ++++-- src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts | 28 ++++++++++++++++----- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/ICD_test_stages/file_browser.tests b/ICD_test_stages/file_browser.tests index c5d9eaf..b1e57fe 100644 --- a/ICD_test_stages/file_browser.tests +++ b/ICD_test_stages/file_browser.tests @@ -1,6 +1,7 @@ src/test/ACCESS_WEBSOCKET.test.ts src/test/ACCESS_CARTA_DEFAULT.test.ts src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts +src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts src/test/GET_FILELIST_ROOTPATH_CONCURRENT.test.ts src/test/FILEINFO_FITS_MULTIHDU.test.ts src/test/FILEINFO_EXCEPTIONS.test.ts diff --git a/docs/source/access_carta.rst b/docs/source/access_carta.rst index 53789ab..cc27175 100644 --- a/docs/source/access_carta.rst +++ b/docs/source/access_carta.rst @@ -101,7 +101,7 @@ ACCESS_CARTA_KNOWN_SESSION See the `source code `__. -This test verifies that connecting with a known (previously used) session ID results in a resumed session. +This test verifies that connecting with a client-supplied session ID results in a resumed session. Any non-zero session ID is treated as a resume request, and the backend adopts the requested ID and echoes it back. 1. Frontend sends: **REGISTER_VIEWER** (``RegisterViewer``) @@ -120,7 +120,11 @@ This test verifies that connecting with a known (previously used) session ID res - REGISTER_VIEWER_ACK.session_type = CARTA.SessionType.RESUMED - - REGISTER_VIEWER_ACK.message is a non-empty string + - REGISTER_VIEWER_ACK.message is a non-empty string reporting the requested session id + + - REGISTER_VIEWER_ACK.server_feature_flags does not have the READ_ONLY bit set + + - REGISTER_VIEWER_ACK.platform_strings has non-empty release_info, deployment, architecture and platform entries, where platform is "macOS" or "Linux" - REGISTER_VIEWER_ACK.user_preferences = None (empty object) diff --git a/src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts b/src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts index 92d3064..049768c 100644 --- a/src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts +++ b/src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts @@ -16,6 +16,8 @@ let assertItem: AssertItem = { }, }; +const platformStringKeys = ['release_info', 'deployment', 'architecture', 'platform']; + export enum ConnectionStatus { CLOSED = 0, PENDING = 1, @@ -280,19 +282,33 @@ describe(`ACCESS_CARTA_KNOWN_SESSION tests: Testing connections to the backend w }); test('REGISTER_VIEWER_ACK.user_preferences = None', () => { - expect(RegisterViewerAckTemp.userPreferences).toMatchObject({}); + expect(RegisterViewerAckTemp.userPreferences).toEqual({}); }); test('REGISTER_VIEWER_ACK.user_layouts = None', () => { - expect(RegisterViewerAckTemp.userLayouts).toMatchObject({}); + expect(RegisterViewerAckTemp.userLayouts).toEqual({}); }); - test('REGISTER_VIEWER_ACK.message is a non-empty string', () => { + test(`REGISTER_VIEWER_ACK.message is a non-empty string reporting the requested session id`, () => { expect(RegisterViewerAckTemp.message).toBeDefined(); expect(RegisterViewerAckTemp.message).not.toEqual(''); - if (RegisterViewerAckTemp.message !== '') { - console.warn(`"REGISTER_VIEWER_ACK.message" returns: "${RegisterViewerAckTemp.message}" @${new Date()}`); - } + expect(RegisterViewerAckTemp.message).toContain(`${assertItem.register.sessionId}`); + console.log(`"REGISTER_VIEWER_ACK.message" returns: "${RegisterViewerAckTemp.message}" @${new Date()}`); + }); + + test(`REGISTER_VIEWER_ACK.server_feature_flags does not report READ_ONLY`, () => { + expect(RegisterViewerAckTemp.serverFeatureFlags).toBeDefined(); + expect(RegisterViewerAckTemp.serverFeatureFlags! & CARTA.ServerFeatureFlags.READ_ONLY).toEqual(0); + }); + + test(`REGISTER_VIEWER_ACK.platform_strings has ${platformStringKeys.join(', ')}`, () => { + const platformStrings = RegisterViewerAckTemp.platformStrings!; + expect(platformStrings).toBeDefined(); + platformStringKeys.forEach((key) => { + expect(platformStrings[key]).toBeDefined(); + expect(platformStrings[key]).not.toEqual(''); + }); + expect(['macOS', 'Linux']).toContain(platformStrings['platform']); }); afterAll(async () => { From 98c73af86aebd234b8c596534403d726c3c60b30 Mon Sep 17 00:00:00 2001 From: Cheng-Chin Chiang Date: Thu, 13 Aug 2026 19:40:40 +0800 Subject: [PATCH 5/6] Match the default access checks in the no client feature test --- ICD_test_stages/file_browser.tests | 1 + docs/source/access_carta.rst | 10 ++++-- .../ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts | 32 ++++++++++++++++--- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/ICD_test_stages/file_browser.tests b/ICD_test_stages/file_browser.tests index b1e57fe..a6b7a39 100644 --- a/ICD_test_stages/file_browser.tests +++ b/ICD_test_stages/file_browser.tests @@ -2,6 +2,7 @@ src/test/ACCESS_WEBSOCKET.test.ts src/test/ACCESS_CARTA_DEFAULT.test.ts src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts +src/test/ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts src/test/GET_FILELIST_ROOTPATH_CONCURRENT.test.ts src/test/FILEINFO_FITS_MULTIHDU.test.ts src/test/FILEINFO_EXCEPTIONS.test.ts diff --git a/docs/source/access_carta.rst b/docs/source/access_carta.rst index cc27175..b3579c9 100644 --- a/docs/source/access_carta.rst +++ b/docs/source/access_carta.rst @@ -135,7 +135,7 @@ ACCESS_CARTA_NO_CLIENT_FEATURE See the `source code `__. -This test verifies that a connection without any client feature flags still succeeds. +This test verifies that a connection without any client feature flags still succeeds, and that the acknowledgement is the same as for a default connection. The backend does not read ``client_feature_flags``, so no part of the response may depend on it. 1. Frontend sends: **REGISTER_VIEWER** (``RegisterViewer``) @@ -150,10 +150,16 @@ This test verifies that a connection without any client feature flags still succ - REGISTER_VIEWER_ACK.success = True - - REGISTER_VIEWER_ACK.session_id is not None + - REGISTER_VIEWER_ACK.session_id is assigned by the backend (not 0) - REGISTER_VIEWER_ACK.session_type = CARTA.SessionType.NEW + - REGISTER_VIEWER_ACK.message is a non-empty string reporting the assigned session_id + + - REGISTER_VIEWER_ACK.server_feature_flags does not have the READ_ONLY bit set + + - REGISTER_VIEWER_ACK.platform_strings has non-empty release_info, deployment, architecture and platform entries, where platform is "macOS" or "Linux" + - REGISTER_VIEWER_ACK.user_preferences = None (empty object) - REGISTER_VIEWER_ACK.user_layouts = None (empty object) diff --git a/src/test/ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts b/src/test/ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts index 307873f..6c6b29b 100644 --- a/src/test/ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts +++ b/src/test/ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts @@ -17,6 +17,8 @@ let assertItem: AssertItem = { }, }; +const platformStringKeys = ['release_info', 'deployment', 'architecture', 'platform']; + export enum ConnectionStatus { CLOSED = 0, PENDING = 1, @@ -259,7 +261,7 @@ describe(`ACCESS_CARTA_NO_CLIENT_FEATURE tests: Testing backend connection witho let client = new BackendService(); let RegisterViewerAckTemp: CARTA.IRegisterViewerAck; test( - `send "REGISTER_VIEWER" to "${testServerUrl}" with session_id=${assertItem.register.sessionId} and client_feature_flags="${assertItem.register.clientFeatureFlags}, then receive "REGISTER_VIEWER_ACK" `, + `send "REGISTER_VIEWER" to "${testServerUrl}" with session_id=${assertItem.register.sessionId} and client_feature_flags=${assertItem.register.clientFeatureFlags}, then receive "REGISTER_VIEWER_ACK" `, async () => { RegisterViewerAckTemp = await client.connect( testServerUrl, @@ -274,8 +276,9 @@ describe(`ACCESS_CARTA_NO_CLIENT_FEATURE tests: Testing backend connection witho expect(RegisterViewerAckTemp.success).toBe(true); }); - test('REGISTER_VIEWER_ACK.session_id is non-empty string', () => { + test('REGISTER_VIEWER_ACK.session_id is assigned by the backend', () => { expect(RegisterViewerAckTemp.sessionId).toBeDefined(); + expect(RegisterViewerAckTemp.sessionId).not.toEqual(0); console.log(`Registered session ID is ${RegisterViewerAckTemp.sessionId} @${new Date()}`); }); @@ -283,12 +286,33 @@ describe(`ACCESS_CARTA_NO_CLIENT_FEATURE tests: Testing backend connection witho expect(RegisterViewerAckTemp.sessionType).toBe(CARTA.SessionType.NEW); }); + test(`REGISTER_VIEWER_ACK.message is a non-empty string reporting the assigned session id`, () => { + expect(RegisterViewerAckTemp.message).toBeDefined(); + expect(RegisterViewerAckTemp.message).not.toEqual(''); + expect(RegisterViewerAckTemp.message).toContain(`${RegisterViewerAckTemp.sessionId}`); + }); + + test(`REGISTER_VIEWER_ACK.server_feature_flags does not report READ_ONLY`, () => { + expect(RegisterViewerAckTemp.serverFeatureFlags).toBeDefined(); + expect(RegisterViewerAckTemp.serverFeatureFlags! & CARTA.ServerFeatureFlags.READ_ONLY).toEqual(0); + }); + + test(`REGISTER_VIEWER_ACK.platform_strings has ${platformStringKeys.join(', ')}`, () => { + const platformStrings = RegisterViewerAckTemp.platformStrings!; + expect(platformStrings).toBeDefined(); + platformStringKeys.forEach((key) => { + expect(platformStrings[key]).toBeDefined(); + expect(platformStrings[key]).not.toEqual(''); + }); + expect(['macOS', 'Linux']).toContain(platformStrings['platform']); + }); + test('REGISTER_VIEWER_ACK.user_preferences = None', () => { - expect(RegisterViewerAckTemp.userPreferences).toMatchObject({}); + expect(RegisterViewerAckTemp.userPreferences).toEqual({}); }); test('REGISTER_VIEWER_ACK.user_layouts = None', () => { - expect(RegisterViewerAckTemp.userLayouts).toMatchObject({}); + expect(RegisterViewerAckTemp.userLayouts).toEqual({}); }); afterAll(async () => { From 58c9e5dee6380dbe382df9b786ef1f6a297f645e Mon Sep 17 00:00:00 2001 From: Cheng-Chin Chiang Date: Thu, 13 Aug 2026 19:46:57 +0800 Subject: [PATCH 6/6] Cover both acknowledgements in the same id twice access test --- ICD_test_stages/file_browser.tests | 1 + docs/source/access_carta.rst | 18 ++++++++- src/test/ACCESS_CARTA_SAME_ID_TWICE.test.ts | 44 +++++++++++++++++++-- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/ICD_test_stages/file_browser.tests b/ICD_test_stages/file_browser.tests index a6b7a39..dc67fb0 100644 --- a/ICD_test_stages/file_browser.tests +++ b/ICD_test_stages/file_browser.tests @@ -3,6 +3,7 @@ src/test/ACCESS_CARTA_DEFAULT.test.ts src/test/ACCESS_CARTA_DEFAULT_CONCURRENT.test.ts src/test/ACCESS_CARTA_KNOWN_SESSION.test.ts src/test/ACCESS_CARTA_NO_CLIENT_FEATURE.test.ts +src/test/ACCESS_CARTA_SAME_ID_TWICE.test.ts src/test/GET_FILELIST_ROOTPATH_CONCURRENT.test.ts src/test/FILEINFO_FITS_MULTIHDU.test.ts src/test/FILEINFO_EXCEPTIONS.test.ts diff --git a/docs/source/access_carta.rst b/docs/source/access_carta.rst index b3579c9..f107db1 100644 --- a/docs/source/access_carta.rst +++ b/docs/source/access_carta.rst @@ -169,7 +169,7 @@ ACCESS_CARTA_SAME_ID_TWICE See the `source code `__. -This test verifies that sending REGISTER_VIEWER twice on the same connection with the same session ID results in a resumed session on the second attempt. +This test verifies that sending REGISTER_VIEWER twice on the same connection with the same session ID results in a resumed session on both attempts. The two registrations take different branches in the backend: the first adopts the requested session ID, while the second finds the session already holding it, so the two acknowledgements report different messages. 1. Frontend sends: **REGISTER_VIEWER** (``RegisterViewer``) — first registration @@ -180,6 +180,14 @@ This test verifies that sending REGISTER_VIEWER twice on the same connection wit 2. Backend returns: **REGISTER_VIEWER_ACK** (``RegisterViewerAck``) +:red-text:`Check 1:` the first REGISTER_VIEWER_ACK should satisfy: + + - REGISTER_VIEWER_ACK.success = True + + - REGISTER_VIEWER_ACK.session_id = 9999 + + - REGISTER_VIEWER_ACK.session_type = CARTA.SessionType.RESUMED + 3. Frontend sends: **REGISTER_VIEWER** (``RegisterViewer``) — second registration on same connection .. code-block:: text @@ -189,7 +197,7 @@ This test verifies that sending REGISTER_VIEWER twice on the same connection wit 4. Backend returns: **REGISTER_VIEWER_ACK** (``RegisterViewerAck``) -:red-text:`Check 1:` the second REGISTER_VIEWER_ACK should satisfy: +:red-text:`Check 2:` the second REGISTER_VIEWER_ACK should satisfy: - REGISTER_VIEWER_ACK.success = True @@ -197,6 +205,12 @@ This test verifies that sending REGISTER_VIEWER twice on the same connection wit - REGISTER_VIEWER_ACK.session_type = CARTA.SessionType.RESUMED + - REGISTER_VIEWER_ACK.message is a non-empty string reporting the session id, and differs from the message of the first acknowledgement + + - REGISTER_VIEWER_ACK.server_feature_flags does not have the READ_ONLY bit set, and is identical to the first acknowledgement + + - REGISTER_VIEWER_ACK.platform_strings has non-empty release_info, deployment, architecture and platform entries, is identical to the first acknowledgement, and platform is "macOS" or "Linux" + - REGISTER_VIEWER_ACK.user_preferences = None (empty object) - REGISTER_VIEWER_ACK.user_layouts = None (empty object) diff --git a/src/test/ACCESS_CARTA_SAME_ID_TWICE.test.ts b/src/test/ACCESS_CARTA_SAME_ID_TWICE.test.ts index 60888cc..5967f51 100644 --- a/src/test/ACCESS_CARTA_SAME_ID_TWICE.test.ts +++ b/src/test/ACCESS_CARTA_SAME_ID_TWICE.test.ts @@ -17,6 +17,8 @@ let assertItem: AssertItem = { }, }; +const platformStringKeys = ['release_info', 'deployment', 'architecture', 'platform']; + export enum ConnectionStatus { CLOSED = 0, PENDING = 1, @@ -276,18 +278,25 @@ export class BackendService { } } -describe(`ACCESS_CARTA_SAME_ID_TWICE tests: Testing backend connection with default parameters`, () => { +describe(`ACCESS_CARTA_SAME_ID_TWICE tests: Testing REGISTER_VIEWER sent twice on one connection with the same session id`, () => { let client = new BackendService(); + let FirstRegisterViewerAck: CARTA.IRegisterViewerAck; let RegisterViewerAckTemp: CARTA.IRegisterViewerAck; test( `send "REGISTER_VIEWER" to "${testServerUrl}" with session_id=${assertItem.register.sessionId} and receive "REGISTER_VIEWER_ACK"x2 within ${connectTimeout} ms`, async () => { - await client.connect(testServerUrl, assertItem.register.sessionId); + FirstRegisterViewerAck = await client.connect(testServerUrl, assertItem.register.sessionId); RegisterViewerAckTemp = await client.getRegisterViewerAck(assertItem.register.sessionId); }, connectTimeout ); + test(`the first REGISTER_VIEWER_ACK is a resumed session with session_id ${assertItem.register.sessionId}`, () => { + expect(FirstRegisterViewerAck.success).toBe(true); + expect(FirstRegisterViewerAck.sessionId).toEqual(assertItem.register.sessionId); + expect(FirstRegisterViewerAck.sessionType).toBe(CARTA.SessionType.RESUMED); + }); + test('REGISTER_VIEWER_ACK.success = True', () => { expect(RegisterViewerAckTemp.success).toBe(true); }); @@ -300,12 +309,39 @@ describe(`ACCESS_CARTA_SAME_ID_TWICE tests: Testing backend connection with defa expect(RegisterViewerAckTemp.sessionType).toBe(CARTA.SessionType.RESUMED); }); + test(`REGISTER_VIEWER_ACK.message reports the session id and differs from the first acknowledgement`, () => { + expect(RegisterViewerAckTemp.message).toBeDefined(); + expect(RegisterViewerAckTemp.message).not.toEqual(''); + expect(RegisterViewerAckTemp.message).toContain(`${assertItem.register.sessionId}`); + expect(FirstRegisterViewerAck.message).toContain(`${assertItem.register.sessionId}`); + expect(RegisterViewerAckTemp.message).not.toEqual(FirstRegisterViewerAck.message); + console.log(`The first "REGISTER_VIEWER_ACK.message" returns: "${FirstRegisterViewerAck.message}"`); + console.log(`The second "REGISTER_VIEWER_ACK.message" returns: "${RegisterViewerAckTemp.message}"`); + }); + + test(`REGISTER_VIEWER_ACK.server_feature_flags does not report READ_ONLY`, () => { + expect(RegisterViewerAckTemp.serverFeatureFlags).toBeDefined(); + expect(RegisterViewerAckTemp.serverFeatureFlags! & CARTA.ServerFeatureFlags.READ_ONLY).toEqual(0); + expect(RegisterViewerAckTemp.serverFeatureFlags).toEqual(FirstRegisterViewerAck.serverFeatureFlags); + }); + + test(`REGISTER_VIEWER_ACK.platform_strings has ${platformStringKeys.join(', ')}`, () => { + const platformStrings = RegisterViewerAckTemp.platformStrings!; + expect(platformStrings).toBeDefined(); + platformStringKeys.forEach((key) => { + expect(platformStrings[key]).toBeDefined(); + expect(platformStrings[key]).not.toEqual(''); + }); + expect(['macOS', 'Linux']).toContain(platformStrings['platform']); + expect(platformStrings).toEqual(FirstRegisterViewerAck.platformStrings); + }); + test('REGISTER_VIEWER_ACK.user_preferences = None', () => { - expect(RegisterViewerAckTemp.userPreferences).toMatchObject({}); + expect(RegisterViewerAckTemp.userPreferences).toEqual({}); }); test('REGISTER_VIEWER_ACK.user_layouts = None', () => { - expect(RegisterViewerAckTemp.userLayouts).toMatchObject({}); + expect(RegisterViewerAckTemp.userLayouts).toEqual({}); }); afterAll(async () => {