UNPKG

aws-iot-device-sdk-v2

Version:
336 lines 15.6 kB
"use strict"; /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const aws_crt_1 = require("aws-crt"); const uuid_1 = require("uuid"); const events_1 = require("events"); const iotjobsclientv2_1 = require("./iotjobsclientv2"); const client_iot_1 = require("@aws-sdk/client-iot"); const model = __importStar(require("./model")); jest.setTimeout(30000); function hasTestEnvironment() { if (process.env.AWS_TEST_MQTT5_IOT_CORE_HOST === undefined) { return false; } if (process.env.AWS_TEST_MQTT5_IOT_CERTIFICATE_PATH === undefined) { return false; } if (process.env.AWS_TEST_MQTT5_IOT_KEY_PATH === undefined) { return false; } if (process.env.AWS_TEST_MQTT5_IOT_CORE_REGION === undefined) { return false; } return true; } const conditional_test = (condition) => condition ? it : it.skip; function build_protocol_client_mqtt5() { let builder = aws_crt_1.iot.AwsIotMqtt5ClientConfigBuilder.newDirectMqttBuilderWithMtlsFromPath( // @ts-ignore process.env.AWS_TEST_MQTT5_IOT_CORE_HOST, process.env.AWS_TEST_MQTT5_IOT_CERTIFICATE_PATH, process.env.AWS_TEST_MQTT5_IOT_KEY_PATH); builder.withConnectProperties({ clientId: `test-${(0, uuid_1.v4)()}`, keepAliveIntervalSeconds: 1200, }); return new aws_crt_1.mqtt5.Mqtt5Client(builder.build()); } function build_protocol_client_mqtt311() { // @ts-ignore let builder = aws_crt_1.iot.AwsIotMqttConnectionConfigBuilder.new_mtls_builder_from_path(process.env.AWS_TEST_MQTT5_IOT_CERTIFICATE_PATH, process.env.AWS_TEST_MQTT5_IOT_KEY_PATH); // @ts-ignore builder.with_endpoint(process.env.AWS_TEST_MQTT5_IOT_CORE_HOST); builder.with_client_id(`test-${(0, uuid_1.v4)()}`); let client = new aws_crt_1.mqtt.MqttClient(); return client.new_connection(builder.build()); } var ProtocolVersion; (function (ProtocolVersion) { ProtocolVersion[ProtocolVersion["Mqtt311"] = 0] = "Mqtt311"; ProtocolVersion[ProtocolVersion["Mqtt5"] = 1] = "Mqtt5"; })(ProtocolVersion || (ProtocolVersion = {})); class JobsTestingContext { startProtocolClient() { return __awaiter(this, void 0, void 0, function* () { if (!this.protocolStarted) { this.protocolStarted = true; if (this.mqtt5Client) { let connected = (0, events_1.once)(this.mqtt5Client, aws_crt_1.mqtt5.Mqtt5Client.CONNECTION_SUCCESS); this.mqtt5Client.start(); yield connected; } if (this.mqtt311Client) { yield this.mqtt311Client.connect(); } } }); } stopProtocolClient() { return __awaiter(this, void 0, void 0, function* () { if (this.protocolStarted) { this.protocolStarted = false; if (this.mqtt5Client) { let stopped = (0, events_1.once)(this.mqtt5Client, aws_crt_1.mqtt5.Mqtt5Client.STOPPED); this.mqtt5Client.stop(); yield stopped; this.mqtt5Client.close(); } if (this.mqtt311Client) { yield this.mqtt311Client.disconnect(); } } }); } constructor(options) { var _a, _b; this.protocolStarted = false; if (options.version == ProtocolVersion.Mqtt5) { this.mqtt5Client = build_protocol_client_mqtt5(); let rrOptions = { maxRequestResponseSubscriptions: 6, maxStreamingSubscriptions: 2, operationTimeoutInSeconds: (_a = options.timeoutSeconds) !== null && _a !== void 0 ? _a : 60, }; this.client = iotjobsclientv2_1.IotJobsClientv2.newFromMqtt5(this.mqtt5Client, rrOptions); } else { this.mqtt311Client = build_protocol_client_mqtt311(); let rrOptions = { maxRequestResponseSubscriptions: 6, maxStreamingSubscriptions: 2, operationTimeoutInSeconds: (_b = options.timeoutSeconds) !== null && _b !== void 0 ? _b : 60, }; this.client = iotjobsclientv2_1.IotJobsClientv2.newFromMqtt311(this.mqtt311Client, rrOptions); } } open() { return __awaiter(this, void 0, void 0, function* () { yield this.startProtocolClient(); }); } close() { return __awaiter(this, void 0, void 0, function* () { this.client.close(); yield this.stopProtocolClient(); }); } } function doCreateDestroyTest(version) { return __awaiter(this, void 0, void 0, function* () { let context = new JobsTestingContext({ version: version }); yield context.open(); yield context.close(); }); } conditional_test(hasTestEnvironment())('jobsv2 - create destroy mqtt5', () => __awaiter(void 0, void 0, void 0, function* () { yield doCreateDestroyTest(ProtocolVersion.Mqtt5); })); conditional_test(hasTestEnvironment())('jobsv2 - create destroy mqtt311', () => __awaiter(void 0, void 0, void 0, function* () { yield doCreateDestroyTest(ProtocolVersion.Mqtt311); })); //@ts-ignore let jobResources = {}; function createJob(client, index) { var _a; return __awaiter(this, void 0, void 0, function* () { let jobId = 'jobid-' + (0, uuid_1.v4)(); let jobDocument = { test: `do-something${index}` }; const createJobCommand = new client_iot_1.CreateJobCommand({ jobId: jobId, targets: [(_a = jobResources.thingGroupArn) !== null && _a !== void 0 ? _a : ""], document: JSON.stringify(jobDocument), targetSelection: "CONTINUOUS" }); yield client.send(createJobCommand); return jobId; }); } function deleteJob(client, jobId) { return __awaiter(this, void 0, void 0, function* () { if (jobId) { const command = new client_iot_1.DeleteJobCommand({ jobId: jobId, force: true }); yield client.send(command); } }); } beforeEach(() => __awaiter(void 0, void 0, void 0, function* () { jobResources = {}; const client = new client_iot_1.IoTClient({ region: process.env.AWS_TEST_MQTT5_IOT_CORE_REGION, }); let thingGroupName = 'tgn-' + (0, uuid_1.v4)(); const createThingGroupCommand = new client_iot_1.CreateThingGroupCommand({ thingGroupName: thingGroupName }); const createThingGroupResponse = yield client.send(createThingGroupCommand); jobResources.thingGroupName = thingGroupName; jobResources.thingGroupArn = createThingGroupResponse.thingGroupArn; let thingName = 't-' + (0, uuid_1.v4)(); const createThingCommand = new client_iot_1.CreateThingCommand({ thingName: thingName }); yield client.send(createThingCommand); jobResources.thingName = thingName; yield new Promise(r => setTimeout(r, 1000)); jobResources.jobId1 = yield createJob(client, 1); yield new Promise(r => setTimeout(r, 1000)); })); afterEach(() => __awaiter(void 0, void 0, void 0, function* () { const client = new client_iot_1.IoTClient({ region: process.env.AWS_TEST_MQTT5_IOT_CORE_REGION, }); yield new Promise(r => setTimeout(r, 1000)); yield deleteJob(client, jobResources.jobId1); yield new Promise(r => setTimeout(r, 1000)); if (jobResources.thingName) { const command = new client_iot_1.DeleteThingCommand({ thingName: jobResources.thingName }); yield client.send(command); yield new Promise(r => setTimeout(r, 1000)); } if (jobResources.thingGroupName) { const command = new client_iot_1.DeleteThingGroupCommand({ thingGroupName: jobResources.thingGroupName }); yield client.send(command); } jobResources = {}; })); function verifyNoJobExecutions(context) { var _a; return __awaiter(this, void 0, void 0, function* () { let response = yield context.client.getPendingJobExecutions({ thingName: (_a = jobResources.thingName) !== null && _a !== void 0 ? _a : "" }); // @ts-ignore expect(response.inProgressJobs.length).toEqual(0); // @ts-ignore expect(response.queuedJobs.length).toEqual(0); }); } function attachThingToThingGroup(client) { return __awaiter(this, void 0, void 0, function* () { const addThingToThingGroupCommand = new client_iot_1.AddThingToThingGroupCommand({ thingName: jobResources.thingName, thingGroupName: jobResources.thingGroupName }); yield client.send(addThingToThingGroupCommand); }); } function doProcessingTest(version) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q; return __awaiter(this, void 0, void 0, function* () { const client = new client_iot_1.IoTClient({}); let context = new JobsTestingContext({ version: version }); yield context.open(); // set up streaming operations for our test's thing let jobExecutionChangedStream = context.client.createJobExecutionsChangedStream({ thingName: (_a = jobResources.thingName) !== null && _a !== void 0 ? _a : "" }); jobExecutionChangedStream.open(); let nextJobExecutionChangedStream = context.client.createNextJobExecutionChangedStream({ thingName: (_b = jobResources.thingName) !== null && _b !== void 0 ? _b : "" }); nextJobExecutionChangedStream.open(); let initialExecutionChangedWaiter = (0, events_1.once)(jobExecutionChangedStream, 'incomingPublish'); let initialNextJobExecutionChangedWaiter = (0, events_1.once)(nextJobExecutionChangedStream, 'incomingPublish'); // thing is brand new, nothing should be pending yield verifyNoJobExecutions(context); // as soon as we attach the thing to the thing group which has a continuous job associated with it, a // job execution should become queued for our thing yield attachThingToThingGroup(client); let initialJobExecutionChanged = (yield initialExecutionChangedWaiter)[0].message; // @ts-ignore expect(initialJobExecutionChanged.jobs['QUEUED'].length).toEqual(1); // @ts-ignore expect(initialJobExecutionChanged.jobs['QUEUED'][0].jobId).toEqual(jobResources.jobId1); let initialNextJobExecutionChanged = (yield initialNextJobExecutionChangedWaiter)[0].message; expect((_c = initialNextJobExecutionChanged.execution) === null || _c === void 0 ? void 0 : _c.jobId).toEqual(jobResources.jobId1); expect((_d = initialNextJobExecutionChanged.execution) === null || _d === void 0 ? void 0 : _d.status).toEqual(model.JobStatus.QUEUED); let finalExecutionChangedWaiter = (0, events_1.once)(jobExecutionChangedStream, 'incomingPublish'); let finalNextJobExecutionChangedWaiter = (0, events_1.once)(nextJobExecutionChangedStream, 'incomingPublish'); // tell the service we'll run the next job let startNextResponse = yield context.client.startNextPendingJobExecution({ thingName: (_e = jobResources.thingName) !== null && _e !== void 0 ? _e : "" }); expect((_f = startNextResponse.execution) === null || _f === void 0 ? void 0 : _f.jobId).toEqual(jobResources.jobId1); // pretend to do the job yield new Promise(r => setTimeout(r, 1000)); // job execution should be in progress let describeResponse = yield context.client.describeJobExecution({ thingName: (_g = jobResources.thingName) !== null && _g !== void 0 ? _g : "", jobId: (_h = jobResources.jobId1) !== null && _h !== void 0 ? _h : "", }); expect((_j = describeResponse.execution) === null || _j === void 0 ? void 0 : _j.jobId).toEqual(jobResources.jobId1); expect((_k = describeResponse.execution) === null || _k === void 0 ? void 0 : _k.status).toEqual(model.JobStatus.IN_PROGRESS); // tell the service we completed the job successfully yield context.client.updateJobExecution({ thingName: (_l = jobResources.thingName) !== null && _l !== void 0 ? _l : "", jobId: (_m = jobResources.jobId1) !== null && _m !== void 0 ? _m : "", status: model.JobStatus.SUCCEEDED }); yield new Promise(r => setTimeout(r, 3000)); let finalJobExecutionChanged = (yield finalExecutionChangedWaiter)[0].message; expect(finalJobExecutionChanged.jobs).toEqual({}); let finalNextJobExecutionChanged = (yield finalNextJobExecutionChangedWaiter)[0].message; expect(finalNextJobExecutionChanged.timestamp).toBeDefined(); let getPendingResponse = yield context.client.getPendingJobExecutions({ thingName: (_o = jobResources.thingName) !== null && _o !== void 0 ? _o : "" }); expect((_p = getPendingResponse.queuedJobs) === null || _p === void 0 ? void 0 : _p.length).toEqual(0); expect((_q = getPendingResponse.inProgressJobs) === null || _q === void 0 ? void 0 : _q.length).toEqual(0); context.client.close(); yield context.close(); }); } conditional_test(hasTestEnvironment())('jobsv2 processing mqtt5', () => __awaiter(void 0, void 0, void 0, function* () { yield doProcessingTest(ProtocolVersion.Mqtt5); })); conditional_test(hasTestEnvironment())('jobsv2 processing mqtt311', () => __awaiter(void 0, void 0, void 0, function* () { yield doProcessingTest(ProtocolVersion.Mqtt311); })); //# sourceMappingURL=iotjobsclientv2.spec.js.map