From 9c1513fe23b3fff663fa50feb92cd53360003d48 Mon Sep 17 00:00:00 2001 From: MytsV Date: Thu, 29 Aug 2024 16:04:31 +0300 Subject: [PATCH] Make the list RSEs pipeline element discard results with errors and cover this by a test --- ...peline-element-get-rse-pipeline-element.ts | 10 +- test/api/rse/list-rses.test.ts | 186 ++++++++++++------ 2 files changed, 134 insertions(+), 62 deletions(-) diff --git a/src/lib/core/use-case/list-rses/pipeline-element-get-rse-pipeline-element.ts b/src/lib/core/use-case/list-rses/pipeline-element-get-rse-pipeline-element.ts index 07ac02b5c..a95fbd476 100644 --- a/src/lib/core/use-case/list-rses/pipeline-element-get-rse-pipeline-element.ts +++ b/src/lib/core/use-case/list-rses/pipeline-element-get-rse-pipeline-element.ts @@ -48,7 +48,15 @@ export default class GetRSEPipelineElement extends BaseStreamingPostProcessingPi return errorModel; } - transformResponseModel(responseModel: ListRSEsResponse, dto: RSEDetailsDTO): ListRSEsResponse { + transformResponseModel(responseModel: ListRSEsResponse, dto: RSEDetailsDTO): ListRSEsResponse | ListRSEsError { + if (dto.status === 'error') { + return { + status: 'error', + message: '', + name: '', + code: 500, + }; + } responseModel.id = dto.id; responseModel.deterministic = dto.deterministic; responseModel.rse_type = dto.rse_type; diff --git a/test/api/rse/list-rses.test.ts b/test/api/rse/list-rses.test.ts index 4ddd95bdc..4b7f3462f 100644 --- a/test/api/rse/list-rses.test.ts +++ b/test/api/rse/list-rses.test.ts @@ -10,56 +10,78 @@ import { MockHttpStreamableResponseFactory } from 'test/fixtures/http-fixtures'; import MockRucioServerFactory, { MockEndpoint } from 'test/fixtures/rucio-server'; describe('List RSEs Feature tests', () => { - beforeEach(() => { - fetchMock.doMock(); - const rseStream = Readable.from([JSON.stringify({ rse: 'XRD1' })].join('\n')); - - const xrd1 = JSON.stringify({ - availability_delete: true, - availability_read: true, - availability_write: true, - deterministic: true, - domain: ['lan', 'wan'], - id: '464cd7656db842c78261bcc2a087bbcb', - lfn2pfn_algorithm: 'hash', - protocols: [ - { - hostname: 'xrd1', - scheme: 'root', - port: 1094, - prefix: '//rucio', - impl: 'rucio.rse.protocols.xrootd.Default', - domains: { - lan: { - read: 1, - write: 1, - delete: 1, - }, - wan: { - read: 1, - write: 1, - delete: 1, - third_party_copy_read: 1, - third_party_copy_write: 1, - }, + const rseStream = Readable.from([JSON.stringify({ rse: 'XRD1' })].join('\n')); + + const xrd1 = JSON.stringify({ + availability_delete: true, + availability_read: true, + availability_write: true, + deterministic: true, + domain: ['lan', 'wan'], + id: '464cd7656db842c78261bcc2a087bbcb', + lfn2pfn_algorithm: 'hash', + protocols: [ + { + hostname: 'xrd1', + scheme: 'root', + port: 1094, + prefix: '//rucio', + impl: 'rucio.rse.protocols.xrootd.Default', + domains: { + lan: { + read: 1, + write: 1, + delete: 1, + }, + wan: { + read: 1, + write: 1, + delete: 1, + third_party_copy_read: 1, + third_party_copy_write: 1, }, - extended_attributes: null, }, - ], - qos_class: null, - rse: 'XRD1', - rse_type: 'DISK', - sign_url: null, - staging_area: false, - verify_checksum: true, - volatile: false, - read_protocol: 1, - write_protocol: 1, - delete_protocol: 1, - third_party_copy_read_protocol: 1, - third_party_copy_write_protocol: 1, - availability: 7, - }); + extended_attributes: null, + }, + ], + qos_class: null, + rse: 'XRD1', + rse_type: 'DISK', + sign_url: null, + staging_area: false, + verify_checksum: true, + volatile: false, + read_protocol: 1, + write_protocol: 1, + delete_protocol: 1, + third_party_copy_read_protocol: 1, + third_party_copy_write_protocol: 1, + availability: 7, + }); + + beforeEach(() => { + fetchMock.doMock(); + }); + + afterEach(() => { + fetchMock.dontMock(); + }); + + it('should return with INVALID RSE EXPRESSION error if rseExpression is undefined', async () => { + const res = MockHttpStreamableResponseFactory.getMockResponse(); + const controller = appContainer.get>(CONTROLLERS.LIST_RSES); + const controllerParams: ListRSEsControllerParameters = { + rucioAuthToken: MockRucioServerFactory.VALID_RUCIO_TOKEN, + response: res as unknown as NextApiResponse, + rseExpression: '', + }; + + await controller.execute(controllerParams); + const data = await res._getJSONData(); + expect(data.status).toBe('error'); + expect(data.message).toBe('RSE Expression is undefined or an empty string'); + }); + it('should list rses as a stream', async () => { const listRSEsEndpoint: MockEndpoint = { url: `${MockRucioServerFactory.RUCIO_HOST}/rses/?expression=XRD1`, method: 'GET', @@ -85,34 +107,75 @@ describe('List RSEs Feature tests', () => { }, }; MockRucioServerFactory.createMockRucioServer(true, [listRSEsEndpoint, getXRD1Endpoint]); - }); - afterEach(() => { - fetchMock.dontMock(); - }); - - it('should return with INVALID RSE EXPRESSION error if rseExpression is undefined', async () => { const res = MockHttpStreamableResponseFactory.getMockResponse(); + const controller = appContainer.get>(CONTROLLERS.LIST_RSES); const controllerParams: ListRSEsControllerParameters = { rucioAuthToken: MockRucioServerFactory.VALID_RUCIO_TOKEN, response: res as unknown as NextApiResponse, - rseExpression: '', + rseExpression: 'XRD1', }; await controller.execute(controllerParams); - const data = await res._getJSONData(); - expect(data.status).toBe('error'); - expect(data.message).toBe('RSE Expression is undefined or an empty string'); + + const receivedData: any[] = []; + const onData = (data: any) => { + receivedData.push(JSON.parse(data)); + }; + + const done = new Promise((resolve, reject) => { + res.on('data', onData); + res.on('end', () => { + res.off('data', onData); + resolve(); + }); + res.on('error', err => { + res.off('data', onData); + reject(err); + }); + }); + + await done; + + expect(receivedData.length).toEqual(1); + expect(receivedData[0].id).toEqual('464cd7656db842c78261bcc2a087bbcb'); + expect(receivedData[0].rse_type).toEqual(RSEType.DISK); }); - it('should list rses as a stream', async () => { + it('should return an error for RSEs which status cannot be fetched', async () => { + const listRSEsEndpoint: MockEndpoint = { + url: `${MockRucioServerFactory.RUCIO_HOST}/rses/?expression=*`, + method: 'GET', + includes: 'rses?expression=*', + response: { + status: 200, + headers: { + 'Content-Type': 'application/x-json-stream', + }, + body: Readable.from([JSON.stringify({ rse: 'XRD1' }), JSON.stringify({ rse: 'XRD2' })].join('\n')), + }, + }; + const getXRD1Endpoint: MockEndpoint = { + url: `${MockRucioServerFactory.RUCIO_HOST}/rses/XRD1`, + method: 'GET', + includes: 'rses/XRD1', + response: { + status: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: xrd1, + }, + }; + MockRucioServerFactory.createMockRucioServer(true, [listRSEsEndpoint, getXRD1Endpoint]); + const res = MockHttpStreamableResponseFactory.getMockResponse(); const controller = appContainer.get>(CONTROLLERS.LIST_RSES); const controllerParams: ListRSEsControllerParameters = { rucioAuthToken: MockRucioServerFactory.VALID_RUCIO_TOKEN, response: res as unknown as NextApiResponse, - rseExpression: 'XRD1', + rseExpression: '*', }; await controller.execute(controllerParams); @@ -136,8 +199,9 @@ describe('List RSEs Feature tests', () => { await done; - expect(receivedData.length).toEqual(1); + expect(receivedData.length).toEqual(2); expect(receivedData[0].id).toEqual('464cd7656db842c78261bcc2a087bbcb'); expect(receivedData[0].rse_type).toEqual(RSEType.DISK); + expect(receivedData[1].status).toEqual('error'); }); });