-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
39 changed files
with
3,805 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
268 changes: 268 additions & 0 deletions
268
projects/aas-server/src/test/aas-provider/aas-provider.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,268 @@ | ||
/****************************************************************************** | ||
* | ||
* Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, | ||
* eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft | ||
* zur Foerderung der angewandten Forschung e.V. | ||
* | ||
*****************************************************************************/ | ||
|
||
import 'reflect-metadata'; | ||
import { Readable } from 'stream'; | ||
import { AASDocument, aas } from 'common'; | ||
import { describe, beforeEach, it, expect, jest } from '@jest/globals'; | ||
|
||
import { Logger } from '../../app/logging/logger.js'; | ||
import { AASProvider } from '../../app/aas-provider/aas-provider.js'; | ||
import { Parallel } from '../../app/aas-provider/parallel.js'; | ||
import { LocalFileStorage } from '../../app/file-storage/local-file-storage.js'; | ||
import { AASPackage } from '../../app/packages/aas-package.js'; | ||
import { sampleDocument } from '../assets/sample-document.js'; | ||
import { AASResourceFactory } from '../../app/packages/aas-resource-factory.js'; | ||
import { AASResource } from '../../app/packages/aas-resource.js'; | ||
import { createSpyObj } from '../utils.js'; | ||
import { AASServerConfiguration, createEndpoint } from '../../app/configuration.js'; | ||
import { AASResourceScanFactory } from '../../app/aas-provider/aas-resource-scan-factory.js'; | ||
import { WSServer } from '../../app/ws-server.js'; | ||
import { Variable } from '../../app/variable.js'; | ||
import { FileStorageFactory } from '../../app/file-storage/file-storage-factory.js'; | ||
|
||
describe('AASProvider', function () { | ||
let aasProvider: AASProvider; | ||
let variable: jest.Mocked<Variable>; | ||
let fileStorageFactory: jest.Mocked<FileStorageFactory>; | ||
const logger = createSpyObj<Logger>(['error', 'warning', 'info', 'debug', 'start', 'stop']); | ||
const parallel = createSpyObj<Parallel>(['execute', 'on']); | ||
const wsServer = createSpyObj<WSServer>(['notify', 'close', 'on']); | ||
const resourceFactory = createSpyObj<AASResourceFactory>(['create', 'testAsync']); | ||
|
||
beforeEach(function () { | ||
fileStorageFactory = createSpyObj<FileStorageFactory>(['create']); | ||
fileStorageFactory.create.mockReturnValue(new LocalFileStorage('./src/test/assets/samples')); | ||
resourceFactory.testAsync.mockReturnValue(new Promise<void>(resolve => resolve())); | ||
variable = createSpyObj<Variable>({}, { ENDPOINTS: [] }); | ||
}); | ||
|
||
describe('addEndpointAsync', function () { | ||
beforeEach(function () { | ||
variable.ENDPOINTS.push(createEndpoint('file:///shop', 'Shop').href); | ||
aasProvider = new AASProvider( | ||
variable, { | ||
endpoints: [ | ||
createEndpoint('file:///shop', 'Shop').href | ||
] | ||
}, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
}); | ||
|
||
it('adds an existing endpoint to the configuration', async function () { | ||
await aasProvider.addEndpointAsync('samples', createEndpoint('file:///samples', 'samples')); | ||
const workspaces = aasProvider.getWorkspaces(); | ||
expect(workspaces.length).toEqual(2); | ||
}); | ||
}); | ||
|
||
describe('removeEndpointAsync', function () { | ||
beforeEach(function () { | ||
variable.ENDPOINTS.push( | ||
createEndpoint('file:///shop', 'Shop').href, | ||
createEndpoint('file:///samples', 'Samples').href); | ||
|
||
aasProvider = new AASProvider( | ||
variable, { | ||
endpoints: | ||
[ | ||
createEndpoint('file:///shop', 'Shop').href, | ||
createEndpoint('file:///samples', 'Samples').href | ||
] | ||
}, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
}); | ||
|
||
it('removes an endpoint from the configuration', async function () { | ||
await aasProvider.removeEndpointAsync('Shop'); | ||
const workspaces = aasProvider.getWorkspaces(); | ||
expect(workspaces.length).toEqual(1); | ||
if (workspaces.length > 0) { | ||
expect(workspaces[0].name).toEqual('Samples'); | ||
} else { | ||
expect(workspaces.length).toBeGreaterThan(0); | ||
} | ||
}); | ||
}); | ||
|
||
describe('resetAsync', function () { | ||
beforeEach(function () { | ||
variable.ENDPOINTS.push( | ||
createEndpoint('file:///shop', 'Shop').href, | ||
createEndpoint('file:///samples', 'Samples').href); | ||
|
||
const configuration: AASServerConfiguration = { | ||
endpoints: [ | ||
createEndpoint('file:///samples', 'Samples').href | ||
] | ||
}; | ||
|
||
aasProvider = new AASProvider( | ||
variable, | ||
configuration, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
}); | ||
|
||
it('resets the configuration', async function () { | ||
let workspaces = aasProvider.getWorkspaces(); | ||
expect(workspaces.length).toEqual(1); | ||
expect(workspaces[0].name).toEqual('Samples'); | ||
|
||
await aasProvider.resetAsync(); | ||
workspaces = aasProvider.getWorkspaces(); | ||
expect(workspaces.length).toEqual(2); | ||
expect(workspaces[0].name).toEqual('Shop'); | ||
expect(workspaces[1].name).toEqual('Samples'); | ||
}); | ||
}); | ||
|
||
describe('getPackageAsync', function () { | ||
beforeEach(async function () { | ||
const configuration: AASServerConfiguration = { | ||
endpoints: [createEndpoint('file:///samples', 'Samples').href] | ||
}; | ||
|
||
variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); | ||
aasProvider = new AASProvider( | ||
variable, | ||
configuration, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); | ||
}); | ||
|
||
it('downloads an AASX package', async function () { | ||
const source = createSpyObj<AASResource>(['openAsync', 'closeAsync', 'getPackageAsync']); | ||
source.getPackageAsync.mockReturnValue(new Promise<NodeJS.ReadableStream>(resolve => { | ||
const stream = new Readable(); | ||
stream.push('Hello World!'); | ||
stream.push(null); | ||
resolve(stream); | ||
})); | ||
|
||
resourceFactory.create.mockReturnValue(source); | ||
await expect(aasProvider.getDocumentAsync( | ||
'http://customer.com/aas/9175_7013_7091_9168', | ||
'file:///samples')).resolves.toBeDefined(); | ||
}); | ||
}); | ||
|
||
describe('addDocumentAsync', function () { | ||
beforeEach(async function () { | ||
const configuration: AASServerConfiguration = { | ||
endpoints: [createEndpoint('file:///samples', 'Samples').href] | ||
}; | ||
|
||
variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); | ||
aasProvider = new AASProvider( | ||
variable, | ||
configuration, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); | ||
}); | ||
|
||
it('uploads an AASX package', async function () { | ||
const source = createSpyObj<AASResource>(['openAsync', 'closeAsync', 'postPackageAsync']); | ||
const aasPackage = createSpyObj<AASPackage>(['createDocumentAsync']); | ||
aasPackage.createDocumentAsync.mockReturnValue(new Promise<AASDocument>(resolve => resolve(sampleDocument))); | ||
source.postPackageAsync.mockReturnValue(new Promise<AASPackage>(resolve => resolve(aasPackage))); | ||
resourceFactory.create.mockReturnValue(source); | ||
await expect(aasProvider.addDocumentsAsync( | ||
'file:///samples', | ||
[createSpyObj<Express.Multer.File>(['buffer'])])).resolves.toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe('deletePackageAsync', function () { | ||
beforeEach(async function () { | ||
const configuration: AASServerConfiguration = { | ||
endpoints: [createEndpoint('file:///samples', 'Samples').href] | ||
}; | ||
|
||
variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); | ||
aasProvider = new AASProvider( | ||
variable, | ||
configuration, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); | ||
}); | ||
|
||
it('deletes an AASX package', async function () { | ||
const source = createSpyObj<AASResource>(['openAsync', 'closeAsync', 'deletePackageAsync']); | ||
source.deletePackageAsync.mockReturnValue(new Promise<void>(resolve => resolve())); | ||
resourceFactory.create.mockReturnValue(source); | ||
await expect(aasProvider.deleteDocumentAsync( | ||
'file:///samples', | ||
'http://customer.com/aas/9175_7013_7091_9168')).resolves.toBeUndefined(); | ||
|
||
expect(source.deletePackageAsync).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe('invoke', function () { | ||
beforeEach(async function () { | ||
const configuration: AASServerConfiguration = { | ||
endpoints: [createEndpoint('file:///samples', 'Samples').href] | ||
}; | ||
|
||
variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); | ||
aasProvider = new AASProvider( | ||
variable, | ||
configuration, | ||
logger, | ||
parallel, | ||
resourceFactory); | ||
|
||
aasProvider.start(wsServer); | ||
await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); | ||
}); | ||
|
||
it('invokes an operation', async function () { | ||
const operation: aas.Operation = { | ||
idShort: 'noop', | ||
modelType: 'Operation' | ||
}; | ||
|
||
const source = createSpyObj<AASResource>(['openAsync', 'closeAsync', 'invoke']); | ||
source.invoke.mockReturnValue(new Promise<aas.Operation>(resolve => resolve(operation))); | ||
resourceFactory.create.mockReturnValue(source); | ||
|
||
await expect(aasProvider.invoke( | ||
'file:///samples', | ||
'http://customer.com/aas/9175_7013_7091_9168', | ||
operation)).resolves.toEqual(operation); | ||
|
||
expect(source.openAsync).toHaveBeenCalled(); | ||
expect(source.invoke).toHaveBeenCalled(); | ||
expect(source.closeAsync).toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); |
93 changes: 93 additions & 0 deletions
93
projects/aas-server/src/test/aas-provider/aas-registry-scan.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/****************************************************************************** | ||
* | ||
* Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, | ||
* eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft | ||
* zur Foerderung der angewandten Forschung e.V. | ||
* | ||
*****************************************************************************/ | ||
|
||
import http, { IncomingMessage } from 'http'; | ||
import { AASContainer } from 'common'; | ||
import { describe, beforeEach, it, expect, jest } from '@jest/globals'; | ||
|
||
import { AASRegistryScan } from '../../app/aas-provider/aas-registry-scan.js'; | ||
import { Logger } from '../../app/logging/logger.js'; | ||
import { Socket } from 'net'; | ||
import testRegistry from '../assets/test-registry.js' | ||
import { createSpyObj } from '../utils.js'; | ||
import { AssetAdministrationShellDescriptor } from '../../app/types/registry.js'; | ||
|
||
describe('AASRegistryScan', function () { | ||
let registryScan: AASRegistryScan; | ||
let logger: jest.Mocked<Logger>; | ||
let endpoint: URL; | ||
let descriptors: AssetAdministrationShellDescriptor[]; | ||
|
||
beforeEach(function () { | ||
descriptors = testRegistry as unknown as AssetAdministrationShellDescriptor[]; | ||
endpoint = new URL('http://localhost/registry/api/v1/registry/'); | ||
endpoint.searchParams.append('name', 'AAS Registry'); | ||
endpoint.searchParams.append('type', 'AASRegistry'); | ||
|
||
logger = createSpyObj<Logger>(['error', 'warning', 'info', 'debug', 'start', 'stop']); | ||
}); | ||
|
||
it('should create', function () { | ||
expect(new AASRegistryScan(logger, endpoint.href, [])).toBeTruthy(); | ||
}); | ||
|
||
it('adds new containers', async function () { | ||
jest.spyOn(http, 'request').mockImplementation((_, callback) => { | ||
const stream = new IncomingMessage(new Socket()); | ||
stream.push(JSON.stringify(descriptors)); | ||
stream.push(null); | ||
stream.statusCode = 201, | ||
stream.statusMessage = 'Created', | ||
(callback as (res: IncomingMessage) => void)(stream); | ||
|
||
return new http.ClientRequest('http://localhost:1234/registry/api/v1/registry/'); | ||
}); | ||
|
||
registryScan = new AASRegistryScan(logger, endpoint.href, []); | ||
const spy = jest.fn(); | ||
registryScan.on('added', spy); | ||
await expect(registryScan.scanAsync()).resolves.toBeUndefined(); | ||
expect(spy).toHaveBeenCalledTimes(descriptors.length); | ||
registryScan.off('added', spy); | ||
}); | ||
|
||
it('removes unavailable containers', async function () { | ||
jest.spyOn(http, 'request').mockImplementation((_, callback) => { | ||
const stream = new IncomingMessage(new Socket()); | ||
stream.push(JSON.stringify([])); | ||
stream.push(null); | ||
stream.statusCode = 200, | ||
stream.statusMessage = 'OK', | ||
(callback as (res: IncomingMessage) => void)(stream); | ||
|
||
return new http.ClientRequest('http://localhost:1234/registry/api/v1/registry/'); | ||
}); | ||
|
||
const containers: AASContainer[] = [ | ||
{ | ||
name: 'http://172.16.160.171:51000', | ||
url: 'http://172.16.160.171:51000/?type=AasxServer' | ||
}, | ||
{ | ||
name: 'http://172.16.160.188:50010', | ||
url: 'http://172.16.160.188:50010/?type=AasxServer' | ||
}, | ||
{ | ||
name: 'http://172.16.160.171:54000', | ||
url: 'http://172.16.160.171:54000/?type=AasxServer' | ||
} | ||
]; | ||
|
||
registryScan = new AASRegistryScan(logger, endpoint.href, containers); | ||
const spy = jest.fn(); | ||
registryScan.on('removed', spy); | ||
await expect(registryScan.scanAsync()).resolves.toBeUndefined(); | ||
expect(spy).toHaveBeenCalledTimes(containers.length); | ||
registryScan.off('removed', spy); | ||
}); | ||
}); |
Oops, something went wrong.