'use strict'; const { expect } = require('chai'); const sinon = require('sinon'); const { pki } = require('node-forge'); const { calculatePartialFingerprintOfEscapedPemCertificate, } = require('../../modules/certificate'); const { Ven } = require('../../client/ven'); const app = require('../../server'); const { port } = require('../../config'); function getVenClient() { const commonName = 'aabbccddeeff'; const keypair = pki.rsa.generateKeyPair({ bits: 1024, e: 0x10001 }); const cert = pki.createCertificate(); cert.publicKey = keypair.publicKey; cert.serialNumber = '01'; cert.validity.notBefore = new Date('2000-01-01T00:00:00.000Z'); cert.validity.notAfter = new Date('2100-01-01T00:00:00.000Z'); const attrs = [ { name: 'commonName', value: commonName, }, { name: 'countryName', value: 'US', }, { shortName: 'ST', value: 'New York', }, { name: 'localityName', value: 'New York', }, { name: 'organizationName', value: 'Test', }, { shortName: 'OU', value: 'Test', }, ]; cert.setSubject(attrs); cert.setIssuer(attrs); cert.sign(keypair.privateKey); const clientCrtPem = pki.certificateToPem(cert); const fingerprint = calculatePartialFingerprintOfEscapedPemCertificate( clientCrtPem, ); return new Ven( `http://127.0.0.1:${port}`, clientCrtPem, commonName, fingerprint, 'ven.js1', ); } describe('VEN to VTN interactions', function() { describe('registration and event retrieval', async function() { let clock; after(async () => { clock.restore(); }); let ven; before(async () => { clock = sinon.useFakeTimers( new Date('2020-04-26T01:00:00.000Z').getTime(), ); await app.start(); ven = getVenClient(); }); it('should successfully return a vtnId from queryRegistration', async () => { const queryResponse = await ven.queryRegistration(); expect(queryResponse.vtnId).to.be.a('string'); }); it('should successfully register and receive a vtnId and registrationId', async () => { const registrationResponse = await ven.register(); expect(registrationResponse.vtnId).to.be.a('string'); expect(registrationResponse.registrationId).to.be.a('string'); }); it('should successfully return a registrationId and venId from queryRegistration', async () => { const queryResponse = await ven.queryRegistration(); expect(queryResponse.vtnId).to.be.a('string'); expect(queryResponse.registrationId).to.be.a('string'); expect(queryResponse.venId).to.be.a('string'); }); it('should return an event from requestEvents', async () => { const eventResponse = await ven.requestEvents(); expect(eventResponse.events.length).to.eql(1); expect(eventResponse.vtnId).to.be.a('string'); }); it('should successfully cancel that registration', async () => { const cancelResponse = await ven.cancelRegistration(); expect(cancelResponse.registrationId).to.be.a('string'); expect(cancelResponse.venId).to.be.a('string'); }); after(async () => { await app.stop(); }); }).timeout(5000); describe('poll', async function() { let ven; let clock; after(async () => { clock.restore(); }); before(async () => { clock = sinon.useFakeTimers( new Date('2020-04-26T01:00:00.000Z').getTime(), ); await app.start(); ven = getVenClient(); await ven.register(); }); it('should successfully poll for events', async () => { const pollResponse = await ven.poll(); expect(pollResponse._type).to.eql('oadrDistributeEvent'); expect(pollResponse.events.length).to.eql(1); }); it('should not return the same event twice', async () => { const pollResponse = await ven.poll(); expect(pollResponse._type).to.eql('oadrResponse'); }); after(async () => { await app.stop(); }); }).timeout(5000); describe('report', async function() { let ven; let clock; after(async () => { clock.restore(); }); before(async () => { clock = sinon.useFakeTimers( new Date('2020-04-26T01:00:00.000Z').getTime(), ); await app.start(); ven = getVenClient(); await ven.register(); await ven.poll(); // poll for any events that may be waiting }); it('should successfully subscribe to reports and receive data', async () => { const reqs = [ { reportRequestId: '31c5ce71a68a73ece370', reportSpecifierId: 'TELEMETRY_STATUS', createdDateTime: '2020-05-07T10:05:41.421-06:00', duration: 'PT1H', reportName: 'METADATA_TELEMETRY_STATUS', descriptions: [ { reportId: 'TelemetryStatusReport', reportType: 'x-resourceStatus', readingType: 'x-notApplicable', samplingRate: { minPeriod: 'PT1M', maxPeriod: 'PT1H', onChange: false, }, }, ], }, { reportRequestId: '3d92d98e0b65d94e60a7', reportSpecifierId: 'TELEMETRY_USAGE', createdDateTime: '2020-05-07T10:05:41.421-06:00', duration: 'PT1H', reportName: 'METADATA_TELEMETRY_USAGE', descriptions: [ { reportId: 'TelemetryUsageReport', reportType: 'usage', readingType: 'Direct Read', samplingRate: { minPeriod: 'PT1M', maxPeriod: 'PT1H', onChange: false, }, }, ], }, ]; // register reports await ven.registerReports(reqs); const pollResponse = await ven.poll(); // poll has a request to create reports expect(pollResponse._type).to.eql('oadrCreateReport'); const createRequestId = pollResponse.reportRequestId; const [ telemetryStatusReportRequestId, telemetryUsageReportRequestId, ] = pollResponse.requests.map(x => x.reportRequestId); // notify vtn that reports have been created await ven.notifyCreatedReports(createRequestId, [ telemetryStatusReportRequestId, telemetryUsageReportRequestId, ]); // poll is empty, no reports to create const pollResponse2 = await ven.poll(); expect(pollResponse2._type).to.eql('oadrResponse'); // send report const reports = [ { createdDateTime: '2020-05-08T21:27:49.591-06:00', duration: 'PT1M', intervals: [ { duration: 'PT1M', reportPayloads: [ { dataQuality: 'Quality Good - Non Specific', payloadFloat: 161.97970171999845, reportId: 'TelemetryUsageReport', }, ], startDate: '2020-05-08T21:26:49.562-06:00', }, ], reportName: 'TELEMETRY_USAGE', reportRequestId: telemetryUsageReportRequestId, reportSpecifierId: 'TELEMETRY_USAGE', startDate: '2020-05-08T21:26:49.562-06:00', }, { createdDateTime: '2020-05-13T10:56:11.058-06:00', duration: 'PT1M', intervals: [ { duration: 'PT1M', reportPayloads: [ { dataQuality: 'Quality Good - Non Specific', payloadStatus: { online: true, manualOverride: false, loadControlState: { oadrLevelOffset: { oadrNormal: 40, oadrCurrent: 50, }, }, }, reportId: 'TelemetryStatusReport', }, ], startDate: '2020-05-13T10:56:11.058-06:00', }, ], reportName: 'TELEMETRY_STATUS', reportRequestId: telemetryStatusReportRequestId, reportSpecifierId: 'TELEMETRY_STATUS', startDate: '2020-05-13T10:56:11.058-06:00', }, ]; await ven.sendReportData(reports); }).timeout(10000); after(async () => { await app.stop(); }); }).timeout(5000); describe('optIn', async function() { let clock; after(async () => { clock.restore(); }); let ven, events, pollResponse; before(async () => { clock = sinon.useFakeTimers( new Date('2020-04-26T01:00:00.000Z').getTime(), ); await app.start(); ven = getVenClient(); await ven.register(); pollResponse = await ven.poll(); events = pollResponse.events; }); it('should successfully opt in', async () => { const eventId = events[0].eventDescriptor.eventId; const modificationNumber = events[0].eventDescriptor.modificationNumber; await ven.opt('optIn', eventId, modificationNumber); }); it('should be able to opt out after opting in', async () => { const eventId = events[0].eventDescriptor.eventId; const modificationNumber = events[0].eventDescriptor.modificationNumber; await ven.opt('optOut', eventId, modificationNumber); }); after(async () => { await app.stop(); }); }).timeout(5000); });