blob: df594fb741892b6c887cd18f0a7fc7eb5d558fd6 [file] [log] [blame]
Illyoung Choi59820ed2019-06-24 17:01:00 -07001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18(function () {
19 'use strict';
20
21 const path = require('path');
22 const chai = require('chai');
23 const expect = chai.expect;
24 const sinonChai = require('sinon-chai');
25 chai.use(sinonChai);
26 const io = require('socket.io-client');
27 const async = require('async');
28 const _ = require('lodash');
29 const server = require('../src/server.js');
30 const port = 4000;
31 const eventrouter = require('../src/controllers/eventrouter.js');
32 const essenceLoader = require('../src/workflows/loader.js');
33 const essenceFileName = path.join(__dirname, 'test_multi_workflow_essence.json');
34
35 var probeClient;
36 var workflowManagerClients = [];
37 var workflowRunClients = [];
38 var workflowIds = [];
39 var workflowRunInfos = [];
40
41 var receivedKickstartMessages = [[],[]];
42
43 describe('Workflow kickstart test', function() {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -070044 this.slow(5000);
Illyoung Choi59820ed2019-06-24 17:01:00 -070045
46 before(function() {
47 // Start our server
48 server.start(port);
49 });
50
51 after(function() {
52 server.stop();
53 });
54
55 beforeEach(function(done) {
56 async.series([
57 (callback) => {
58 // connect a probe to the server
59 // to send events for test
60 probeClient = io.connect(`http://localhost:${port}`, {
61 query: 'id=probe_id&type=probe' +
62 '&name=probe@xos.org'
63 });
64
65 probeClient.on('connect', () => {
66 callback(null, true);
67 });
68 return;
69 },
70 (callback) => {
71 // connect first workflow manager to the server
72 // this manager will kickstart a workflow
73 let workflowManagerClient = io.connect(`http://localhost:${port}`, {
74 query: 'id=workflow_manager_id1&type=workflow_manager' +
75 '&name=manager1@xos.org'
76 });
77
78 workflowManagerClient.on(eventrouter.serviceEvents.WORKFLOW_KICKSTART, (message) => {
79 // save it for check
80 receivedKickstartMessages[0].push(message);
81
82 // save workflow_id and workflow_run_id
83 workflowRunInfos.push({
84 workflowId: message.workflow_id,
85 workflowRunId: message.workflow_run_id
86 });
87
88 setTimeout(() => {
89 // call-back
90 workflowManagerClient.emit(eventrouter.serviceEvents.WORKFLOW_KICKSTART, {
91 workflow_id: message.workflow_id,
92 workflow_run_id: message.workflow_run_id
93 })
Illyoung Choie3ce4cf2019-06-28 11:07:47 -070094 }, 1000);
Illyoung Choi59820ed2019-06-24 17:01:00 -070095 });
96
97 workflowManagerClient.on('connect', () => {
98 callback(null, true);
99 });
100
101 workflowManagerClients.push(workflowManagerClient);
102 return;
103 },
104 (callback) => {
105 // connect second workflow manager to the server
106 // this manager will not kickstart a workflow
107 let workflowManagerClient = io.connect(`http://localhost:${port}`, {
108 query: 'id=workflow_manager_id2&type=workflow_manager' +
109 '&name=manager2@xos.org'
110 });
111
112 workflowManagerClient.on(eventrouter.serviceEvents.WORKFLOW_KICKSTART, (message) => {
113 receivedKickstartMessages[1].push(message);
114 });
115
116 workflowManagerClient.on('connect', () => {
117 callback(null, true);
118 });
119
120 workflowManagerClients.push(workflowManagerClient);
121 return;
122 },
123 (callback) => {
124 let essence = essenceLoader.loadEssence(essenceFileName, true);
125
126 // register the workflow
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700127 workflowManagerClients[0].emit(eventrouter.serviceEvents.WORKFLOW_REG_ESSENCE, {
128 essence: essence
129 });
Illyoung Choi59820ed2019-06-24 17:01:00 -0700130
131 _.forOwn(essence, (_value, workflowId) => {
132 // save
133 workflowIds.push(workflowId);
134 });
135
136 // handle return
137 workflowManagerClients[0].on(
138 eventrouter.serviceEvents.WORKFLOW_REG_ESSENCE,
139 (workflowRegResult) => {
140 callback(null, workflowRegResult);
141 }
142 );
143 return;
144 }
145 ],
146 function(err, results) {
147 // we do not actually check results;
148 if(results.includes(false)) {
149 done.fail(err);
150 }
151 else {
152 done();
153 }
154 });
155 return;
156 });
157
158 afterEach(function() {
159 // remove workflow runs
160 _.forOwn(workflowRunInfos, (workflowRunInfo) => {
161 workflowManagerClients[0].emit(server.serviceEvents.WORKFLOW_RUN_REMOVE, {
162 workflow_id: workflowRunInfo.workflowId,
163 workflow_run_id: workflowRunInfo.workflowRunId
164 });
165 });
166 workflowRunInfos.length = 0;
167
168 // remove workflows
169 _.forOwn(workflowIds, (workflowId) => {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700170 workflowManagerClients[0].emit(server.serviceEvents.WORKFLOW_REMOVE, {
171 workflow_id: workflowId
172 });
Illyoung Choi59820ed2019-06-24 17:01:00 -0700173 });
174 workflowIds.length = 0;
175
176 // remove message store
177 receivedKickstartMessages.forEach((receivedKickstartMessageStore) => {
178 receivedKickstartMessageStore.length = 0;
179 });
180
181 // disconnect clients
182 workflowManagerClients.forEach((workflowManagerClient) => {
183 if(workflowManagerClient.connected) {
184 workflowManagerClient.disconnect();
185 }
186 });
187 workflowManagerClients.length = 0;
188
189 workflowRunClients.forEach((workflowRunClient) => {
190 if(workflowRunClient.connected) {
191 workflowRunClient.disconnect();
192 }
193 });
194 workflowRunClients.length = 0;
195
196 if(probeClient.connected) {
197 probeClient.disconnect();
198 }
199 probeClient = null;
200 });
201
202 it('should have two workflows', function(done) {
203 workflowManagerClients[0].on(eventrouter.serviceEvents.WORKFLOW_LIST, (result) => {
204 let workflowsList = result.result;
205 expect(workflowsList.length).to.equal(2);
206 workflowsList.forEach((workflowIdInList) => {
207 expect(workflowIds).to.includes(workflowIdInList);
208 });
209 done();
210 });
211
212 workflowManagerClients[0].emit(eventrouter.serviceEvents.WORKFLOW_LIST, {});
213 });
214
215 it('all managers should receive kickstart messages', function(done) {
216 // kickstart the workflow
217 probeClient.emit('onu.events', {serialNumber: 'testSerialXXX', other: 'test_other_field'});
218 setTimeout(() => {
219 expect(receivedKickstartMessages.length, 'num of message stores').to.equal(2);
220 receivedKickstartMessages.forEach((receivedKickstartMessageStore) => {
221 expect(receivedKickstartMessageStore.length, 'num of messages in a store').to.equal(1);
222 });
223 done();
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700224 }, 1000);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700225 });
226
227 it('should have only one workflow run', function(done) {
228 this.timeout(5000);
229
230 // kickstart the workflow
231 probeClient.emit('onu.events', {serialNumber: 'testSerialXXX', other: 'test_other_field'});
232 setTimeout(() => {
233 // kickstart will take 2 seconds roughly
234 expect(workflowRunInfos.length, 'num of workflow runs').to.equal(1);
235 // the workflow must be 'should_be_called'
236 expect(workflowRunInfos[0].workflowId, 'workflow id').to.equal('should_be_called');
237 done();
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700238 }, 2000);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700239 });
240
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700241 it('should read an event that is used for workflow kickstart', function(done) {
Illyoung Choi59820ed2019-06-24 17:01:00 -0700242 this.timeout(5000);
243
244 // kickstart the workflow
245 probeClient.emit('onu.events', {serialNumber: 'testSerialXXX', other: 'test_other_field'});
246 setTimeout(() => {
247 // kickstart will take 2 seconds roughly
248 expect(workflowRunInfos.length, 'num of workflow runs').to.equal(1);
249 // the workflow must be 'should_be_called'
250 expect(workflowRunInfos[0].workflowId, 'workflow id').to.equal('should_be_called');
251
252 // connect a workflow run client to the server
253 let workflowRunClient = io.connect(`http://localhost:${port}`, {
254 query: 'id=workflow_run_id1&type=workflow_run' +
255 `&workflow_id=${workflowRunInfos[0].workflowId}` +
256 `&workflow_run_id=${workflowRunInfos[0].workflowRunId}` +
257 '&name=run1@xos.org'
258 });
259 workflowRunClients.push(workflowRunClient);
260
261 workflowRunClient.on('connect', () => {
262 workflowRunClient.emit(eventrouter.serviceEvents.WORKFLOW_RUN_FETCH_EVENT, {
263 workflow_id: workflowRunInfos[0].workflowId,
264 workflow_run_id: workflowRunInfos[0].workflowRunId,
265 task_id: 'onu_event_handler',
266 topic: 'onu.events'
267 });
268 });
269
270 workflowRunClient.on(eventrouter.serviceEvents.WORKFLOW_RUN_FETCH_EVENT, (result) => {
271 let event = result.result;
272 expect(event.topic).to.equal('onu.events');
273 expect(event.message.serialNumber).to.equal('testSerialXXX');
274 done();
275 });
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700276 }, 2000);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700277 });
278
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700279 it('should map a workflow run using key-field', function(done) {
280 this.timeout(5000);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700281
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700282 // kickstart the workflow
283 probeClient.emit(
284 'onu.events',
285 {serialNumber: 'testSerialXXX', other: 'test_other_field'}
286 );
287 probeClient.emit(
288 'datamodel.AttWorkflowDriverServiceInstance',
289 {operation: 'update', serialNumber: 'testSerialXXX', other: 'updated_test_other_field'}
290 );
Illyoung Choi59820ed2019-06-24 17:01:00 -0700291 setTimeout(() => {
Illyoung Choie3ce4cf2019-06-28 11:07:47 -0700292 // kickstart will take 2 seconds roughly
293 expect(workflowRunInfos.length, 'num of workflow runs').to.equal(1);
294 // the workflow must be 'should_be_called'
295 expect(workflowRunInfos[0].workflowId, 'workflow id').to.equal('should_be_called');
296
297 // connect a workflow run client to the server
298 let workflowRunClient = io.connect(`http://localhost:${port}`, {
299 query: 'id=workflow_run_id1&type=workflow_run' +
300 `&workflow_id=${workflowRunInfos[0].workflowId}` +
301 `&workflow_run_id=${workflowRunInfos[0].workflowRunId}` +
302 '&name=run1@xos.org'
303 });
304 workflowRunClients.push(workflowRunClient);
305
306 workflowRunClient.on('connect', () => {
307 // check message counts
308 workflowRunClient.emit(eventrouter.serviceEvents.WORKFLOW_RUN_COUNT_EVENTS, {
309 workflow_id: workflowRunInfos[0].workflowId,
310 workflow_run_id: workflowRunInfos[0].workflowRunId
311 });
312 });
313
314 let eventRaised = 0;
315 workflowRunClient.on(eventrouter.serviceEvents.WORKFLOW_RUN_COUNT_EVENTS, (result) => {
316 let count = result.result;
317 expect(count, 'number of events queued').to.equal(2);
318
319 // fetch two events
320 workflowRunClient.emit(eventrouter.serviceEvents.WORKFLOW_RUN_FETCH_EVENT, {
321 workflow_id: workflowRunInfos[0].workflowId,
322 workflow_run_id: workflowRunInfos[0].workflowRunId,
323 task_id: 'onu_event_handler',
324 topic: 'onu.events'
325 });
326 eventRaised++;
327
328 workflowRunClient.emit(eventrouter.serviceEvents.WORKFLOW_RUN_FETCH_EVENT, {
329 workflow_id: workflowRunInfos[0].workflowId,
330 workflow_run_id: workflowRunInfos[0].workflowRunId,
331 task_id: 'onu_model_event_handler',
332 topic: 'datamodel.AttWorkflowDriverServiceInstance'
333 });
334 eventRaised++;
335 });
336
337 workflowRunClient.on(eventrouter.serviceEvents.WORKFLOW_RUN_FETCH_EVENT, (result) => {
338 let event = result.result;
339 if(eventRaised === 2) {
340 expect(event.topic).to.equal('onu.events');
341 expect(event.message.serialNumber).to.equal('testSerialXXX');
342 }
343 else if(eventRaised === 1) {
344 expect(event.topic).to.equal('datamodel.AttWorkflowDriverServiceInstance');
345 expect(event.message.serialNumber).to.equal('testSerialXXX');
346 }
347 eventRaised--;
348
349 if(eventRaised === 0) {
350 done();
351 }
352 });
353 }, 2000);
Illyoung Choi59820ed2019-06-24 17:01:00 -0700354 });
Illyoung Choi59820ed2019-06-24 17:01:00 -0700355 });
356})();