iotagent-node-lib 4.5.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +67 -272
  2. package/doc/README.md +1 -1
  3. package/doc/admin.md +3 -15
  4. package/doc/api.md +469 -134
  5. package/doc/deprecated.md +4 -0
  6. package/doc/devel/architecture.md +5 -135
  7. package/doc/devel/development.md +224 -12
  8. package/doc/getting-started.md +114 -53
  9. package/doc/roadmap.md +5 -5
  10. package/docker/Mosquitto/Dockerfile +2 -2
  11. package/docker/Mosquitto/README.md +14 -11
  12. package/lib/constants.js +3 -0
  13. package/lib/fiware-iotagent-lib.js +12 -15
  14. package/lib/jexlTranformsMap.js +3 -1
  15. package/lib/model/dbConn.js +1 -4
  16. package/lib/services/common/alarmManagement.js +3 -0
  17. package/lib/services/groups/groupService.js +1 -1
  18. package/lib/services/ngsi/entities-NGSI-LD.js +320 -570
  19. package/lib/services/ngsi/entities-NGSI-v2.js +36 -1
  20. package/lib/services/ngsi/ngsiService.js +3 -1
  21. package/lib/services/northBound/deviceGroupAdministrationServer.js +42 -6
  22. package/lib/services/northBound/deviceProvisioningServer.js +0 -1
  23. package/lib/services/northBound/northboundServer.js +2 -0
  24. package/lib/services/stats/statsRegistry.js +128 -101
  25. package/lib/templates/createDevice.json +0 -24
  26. package/lib/templates/createDeviceLax.json +0 -23
  27. package/lib/templates/deviceGroup.json +1 -25
  28. package/lib/templates/updateDevice.json +0 -24
  29. package/lib/templates/updateDeviceLax.json +0 -23
  30. package/package.json +2 -2
  31. package/scripts/legacy_expression_tool/README.md +0 -1
  32. package/test/functional/README.md +22 -17
  33. package/test/functional/functional-tests-runner.js +9 -4
  34. package/test/functional/functional-tests.js +4 -4
  35. package/test/functional/testCases.js +245 -4
  36. package/test/unit/examples/deviceProvisioningRequests/provisionFullDevice.json +1 -13
  37. package/test/unit/examples/groupProvisioningRequests/multipleConfigGroupsCreation.json +44 -0
  38. package/test/unit/examples/groupProvisioningRequests/provisionDuplicateConfigGroup.json +35 -0
  39. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroup.json +36 -0
  40. package/test/unit/examples/groupProvisioningRequests/provisionFullConfigGroupAlternate.json +36 -0
  41. package/test/unit/general/deviceService-test.js +102 -0
  42. package/test/unit/general/statistics-service_test.js +1 -74
  43. package/test/unit/mongodb/mongodb-configGroup-registry-test.js +452 -0
  44. package/test/unit/mongodb/mongodb-connectionoptions-test.js +2 -3
  45. package/test/unit/mongodb/mongodb-group-registry-test.js +34 -33
  46. package/test/unit/mongodb/mongodb-service-registry-test.js +477 -0
  47. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin1a.json +4 -4
  48. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin2.json +22 -22
  49. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin29.json +4 -4
  50. package/test/unit/ngsi-ld/examples/contextRequests/updateContextExpressionPlugin32.json +14 -15
  51. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin1.json +23 -23
  52. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin15.json +0 -5
  53. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin4.json +11 -16
  54. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin5.json +23 -28
  55. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin6.json +8 -13
  56. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin7.json +0 -5
  57. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityPlugin8.json +24 -29
  58. package/test/unit/ngsi-ld/examples/contextRequests/updateContextMultientityTimestampPlugin2.json +12 -17
  59. package/test/unit/ngsi-ld/examples/contextRequests/updateContextStaticLinkedAttributes.json +12 -10
  60. package/test/unit/ngsi-ld/expressions/jexlBasedTransformations-test.js +0 -102
  61. package/test/unit/ngsi-ld/plugins/multientity-plugin_test.js +4 -5
  62. package/test/unit/ngsi-ld/provisioning/listProvisionedDevices-test.js +0 -4
  63. package/test/unit/ngsiv2/general/deviceService-test.js +94 -1
  64. package/test/unit/ngsiv2/general/iotam-autoregistration-test.js +195 -0
  65. package/test/unit/ngsiv2/provisioning/device-group-api-test.js +259 -0
  66. package/test/unit/ngsiv2/provisioning/device-provisioning-configGroup-api_test.js +1189 -0
  67. package/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +0 -4
  68. package/test/unit/statsRegistry/openmetrics-test.js +167 -0
  69. package/lib/templates/queryContext.json +0 -25
  70. package/test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json +0 -35
  71. package/test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json +0 -17
  72. package/test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json +0 -31
  73. package/test/unit/general/statistics-persistence_test.js +0 -121
  74. package/test/unit/ngsi-ld/examples/contextRequests/createBidirectionalDevice.json +0 -17
  75. package/test/unit/ngsi-ld/examples/contextRequests/updateContextProcessTimestamp.json +0 -12
  76. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  77. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithDatasetId.json +0 -21
  78. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -17
  79. package/test/unit/ngsi-ld/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -23
  80. package/test/unit/ngsi-ld/plugins/timestamp-processing-plugin_test.js +0 -132
  81. package/test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json +0 -8
  82. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotification.json +0 -13
  83. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotificationWithMetadata.json +0 -19
  84. package/test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json +0 -24
@@ -153,6 +153,36 @@ const groupCreation = {
153
153
  'fiware-servicepath': '/testingPath'
154
154
  }
155
155
  };
156
+
157
+ const configGroupCreation = {
158
+ url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/groups',
159
+ method: 'POST',
160
+ json: {
161
+ groups: [
162
+ {
163
+ resource: '',
164
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
165
+ entity_type: 'TheLightType',
166
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
167
+ cbHost: 'http://192.168.1.1:1026',
168
+ commands: [],
169
+ lazy: [],
170
+ attributes: [
171
+ {
172
+ name: 'status',
173
+ type: 'Boolean'
174
+ }
175
+ ],
176
+ static_attributes: []
177
+ }
178
+ ]
179
+ },
180
+ headers: {
181
+ 'fiware-service': 'testservice',
182
+ 'fiware-servicepath': '/testingPath'
183
+ }
184
+ };
185
+
156
186
  const deviceCreation = {
157
187
  url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices',
158
188
  method: 'POST',
@@ -180,6 +210,7 @@ describe('NGSI-v2 - Device Service: utils', function () {
180
210
  async.series([iotAgentLib.clearAll, iotAgentLib.deactivate], done);
181
211
  });
182
212
 
213
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
183
214
  describe('When an existing device tries to be retrieved with retrieveOrCreate()', function () {
184
215
  beforeEach(function (done) {
185
216
  contextBrokerMock = nock('http://192.168.1.1:1026')
@@ -213,6 +244,41 @@ describe('NGSI-v2 - Device Service: utils', function () {
213
244
  });
214
245
  });
215
246
 
247
+ describe('When an existing device tries to be retrieved with retrieveOrCreate()', function () {
248
+ beforeEach(function (done) {
249
+ contextBrokerMock = nock('http://192.168.1.1:1026')
250
+ .matchHeader('fiware-service', 'testservice')
251
+ .matchHeader('fiware-servicepath', '/testingPath')
252
+ .post('/v2/registrations')
253
+ .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' });
254
+
255
+ contextBrokerMock
256
+ .matchHeader('fiware-service', 'testservice')
257
+ .matchHeader('fiware-servicepath', '/testingPath')
258
+ .post('/v2/entities?options=upsert')
259
+ .reply(204);
260
+
261
+ async.series(
262
+ [request.bind(request, configGroupCreation), request.bind(request, deviceCreation)],
263
+ function (error, results) {
264
+ done();
265
+ }
266
+ );
267
+ });
268
+
269
+ it('should return the existing device', function (done) {
270
+ iotAgentLib.retrieveDevice('Light1', '801230BJKL23Y9090DSFL123HJK09H324HV8732', function (error, device) {
271
+ should.not.exist(error);
272
+ should.exist(device);
273
+
274
+ device.id.should.equal('Light1');
275
+ done();
276
+ });
277
+ });
278
+ });
279
+
280
+ // #FIXME1649: this test will be removed if at the end /iot/services API (now Deprecated) is removed
281
+
216
282
  describe('When an unexisting device tries to be retrieved for an existing APIKey', function () {
217
283
  beforeEach(function (done) {
218
284
  contextBrokerMock = nock('http://192.168.1.1:1026')
@@ -249,6 +315,42 @@ describe('NGSI-v2 - Device Service: utils', function () {
249
315
  });
250
316
  });
251
317
 
318
+ describe('When an unexisting device tries to be retrieved for an existing APIKey', function () {
319
+ beforeEach(function (done) {
320
+ contextBrokerMock = nock('http://192.168.1.1:1026')
321
+ .matchHeader('fiware-service', 'testservice')
322
+ .matchHeader('fiware-servicepath', '/testingPath')
323
+ .post('/v2/registrations')
324
+ .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' });
325
+
326
+ contextBrokerMock
327
+ .matchHeader('fiware-service', 'testservice')
328
+ .matchHeader('fiware-servicepath', '/testingPath')
329
+ .post('/v2/entities?options=upsert')
330
+ .reply(204);
331
+
332
+ async.series([request.bind(request, configGroupCreation)], function (error, results) {
333
+ done();
334
+ });
335
+ });
336
+
337
+ it('should register the device and return it', function (done) {
338
+ iotAgentLib.retrieveDevice(
339
+ 'UNEXISTENT_DEV',
340
+ '801230BJKL23Y9090DSFL123HJK09H324HV8732',
341
+ function (error, device) {
342
+ should.not.exist(error);
343
+ should.exist(device);
344
+
345
+ device.id.should.equal('UNEXISTENT_DEV');
346
+ should.exist(device.protocol);
347
+ device.protocol.should.equal('MQTT_UL');
348
+ done();
349
+ }
350
+ );
351
+ });
352
+ });
353
+
252
354
  describe('When an unexisting device tries to be retrieved for an unexisting APIKey', function () {
253
355
  it('should raise an error', function (done) {
254
356
  iotAgentLib.retrieveDevice(
@@ -35,9 +35,6 @@ const iotAgentConfig = {
35
35
  host: 'localhost',
36
36
  baseRoot: '/'
37
37
  },
38
- stats: {
39
- interval: 100
40
- },
41
38
  types: {},
42
39
  service: 'smartgondor',
43
40
  subservice: 'gardens',
@@ -51,9 +48,7 @@ describe('Statistics service', function () {
51
48
  oldConfig = commonConfig.getConfig();
52
49
  commonConfig.setConfig(iotAgentConfig);
53
50
 
54
- statsService.globalLoad({}, function () {
55
- statsService.clearTimers(done);
56
- });
51
+ statsService.globalLoad({}, done);
57
52
  });
58
53
 
59
54
  afterEach(function (done) {
@@ -74,16 +69,6 @@ describe('Statistics service', function () {
74
69
  );
75
70
  });
76
71
 
77
- it('should appear the modified value in the getCurrent() statistics', function (done) {
78
- statsService.add(statName, statValue, function () {
79
- statsService.getCurrent(statName, function (error, value) {
80
- should.not.exist(error);
81
- should.exist(value);
82
- value.should.equal(statValue);
83
- done();
84
- });
85
- });
86
- });
87
72
  it('should add the value to the global values', function (done) {
88
73
  statsService.add(statName, statValue, function () {
89
74
  statsService.getGlobal(statName, function (error, value) {
@@ -119,62 +104,4 @@ describe('Statistics service', function () {
119
104
  });
120
105
  });
121
106
  });
122
- describe('When the current statistics are reset', function () {
123
- beforeEach(function (done) {
124
- statsService.add('statA', 42, function () {
125
- statsService.add('statB', 52, done);
126
- });
127
- });
128
-
129
- it('should return a value of zero for any of the individual statistics', function (done) {
130
- statsService.resetCurrent(function (error) {
131
- should.not.exist(error);
132
-
133
- statsService.getAllCurrent(function (error, data) {
134
- should.exist(data);
135
- should.exist(data.statA);
136
- should.exist(data.statB);
137
- data.statA.should.equal(0);
138
- data.statB.should.equal(0);
139
- done();
140
- });
141
- });
142
- });
143
- });
144
- describe('When a new periodic stats action is set', function () {
145
- let valueCurrent = 0;
146
- let valueGlobal = 0;
147
- let times = 0;
148
-
149
- beforeEach(function (done) {
150
- statsService.globalLoad(
151
- {
152
- stat1: 10
153
- },
154
- function () {
155
- statsService.add('stat1', 5, done);
156
- }
157
- );
158
- });
159
-
160
- function mockedAction(current, global, callback) {
161
- valueCurrent = current.stat1;
162
- valueGlobal = global.stat1;
163
- times++;
164
- callback();
165
- }
166
-
167
- it('should be triggered with the periodicity stated in the config.stats.interval parameter', function (done) {
168
- statsService.addTimerAction(mockedAction, function () {
169
- setTimeout(function () {
170
- statsService.clearTimers(function () {
171
- valueCurrent.should.equal(5);
172
- valueGlobal.should.equal(15);
173
- times.should.equal(4);
174
- done();
175
- });
176
- }, 480);
177
- });
178
- });
179
- });
180
107
  });
@@ -0,0 +1,452 @@
1
+ /*
2
+ * Copyright 2024 Telefonica Investigación y Desarrollo, S.A.U
3
+ *
4
+ * This file is part of fiware-iotagent-lib
5
+ *
6
+ * fiware-iotagent-lib is free software: you can redistribute it and/or
7
+ * modify it under the terms of the GNU Affero General Public License as
8
+ * published by the Free Software Foundation, either version 3 of the License,
9
+ * or (at your option) any later version.
10
+ *
11
+ * fiware-iotagent-lib is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
+ * See the GNU Affero General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Affero General Public
17
+ * License along with fiware-iotagent-lib.
18
+ * If not, see http://www.gnu.org/licenses/.
19
+ *
20
+ * For those usages not covered by the GNU Affero General Public License
21
+ * please contact with::[contacto@tid.es]
22
+ *
23
+ * Modified by: Daniel Calvo - ATOS Research & Innovation
24
+ */
25
+
26
+ /* eslint-disable no-unused-vars */
27
+
28
+ const iotAgentLib = require('../../../lib/fiware-iotagent-lib');
29
+ const _ = require('underscore');
30
+ const utils = require('../../tools/utils');
31
+ const request = utils.request;
32
+ const async = require('async');
33
+ const should = require('should');
34
+ const iotAgentConfig = {
35
+ logLevel: 'FATAL',
36
+ contextBroker: {
37
+ host: '192.168.1.1',
38
+ port: '1026'
39
+ },
40
+ server: {
41
+ name: 'testAgent',
42
+ port: 4041,
43
+ host: 'localhost',
44
+ baseRoot: '/'
45
+ },
46
+ types: {},
47
+ deviceRegistry: {
48
+ type: 'mongodb'
49
+ },
50
+ mongodb: {
51
+ host: 'localhost',
52
+ port: '27017',
53
+ db: 'iotagent'
54
+ },
55
+ service: 'smartgondor',
56
+ subservice: 'gardens',
57
+ providerUrl: 'http://smartgondor.com',
58
+ deviceRegistrationDuration: 'P1M'
59
+ };
60
+ const mongo = require('mongodb').MongoClient;
61
+ const mongoUtils = require('./mongoDBUtils');
62
+ const optionsCreation = {
63
+ url: 'http://localhost:4041/iot/groups',
64
+ method: 'POST',
65
+ json: {
66
+ groups: [
67
+ {
68
+ resource: '/deviceTest',
69
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
70
+ entity_type: 'Light',
71
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
72
+ cbHost: 'http://unexistentHost:1026',
73
+ commands: [
74
+ {
75
+ name: 'wheel1',
76
+ type: 'Wheel'
77
+ }
78
+ ],
79
+ lazy: [
80
+ {
81
+ name: 'luminescence',
82
+ type: 'Lumens'
83
+ }
84
+ ],
85
+ attributes: [
86
+ {
87
+ name: 'status',
88
+ type: 'Boolean'
89
+ }
90
+ ],
91
+ internal_attributes: [
92
+ {
93
+ customField: 'customValue'
94
+ }
95
+ ]
96
+ }
97
+ ]
98
+ },
99
+ headers: {
100
+ 'fiware-service': 'testservice',
101
+ 'fiware-servicepath': '/testingPath'
102
+ }
103
+ };
104
+ const optionsDelete = {
105
+ url: 'http://localhost:4041/iot/groups',
106
+ method: 'DELETE',
107
+ json: {},
108
+ headers: {
109
+ 'fiware-service': 'testservice',
110
+ 'fiware-servicepath': '/testingPath'
111
+ },
112
+ qs: {
113
+ resource: '/deviceTest',
114
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
115
+ }
116
+ };
117
+ const optionsList = {
118
+ url: 'http://localhost:4041/iot/groups',
119
+ method: 'GET',
120
+ json: {},
121
+ headers: {
122
+ 'fiware-service': 'testservice',
123
+ 'fiware-servicepath': '/*'
124
+ }
125
+ };
126
+ const optionsUpdate = {
127
+ url: 'http://localhost:4041/iot/groups',
128
+ method: 'PUT',
129
+ json: {
130
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732',
131
+ trust: '8970A9078A803H3BL98PINEQRW8342HBAMS',
132
+ cbHost: 'http://anotherUnexistentHost:1026',
133
+ commands: [
134
+ {
135
+ name: 'wheel1',
136
+ type: 'Wheel'
137
+ }
138
+ ],
139
+ lazy: [
140
+ {
141
+ name: 'luminescence',
142
+ type: 'Lumens'
143
+ }
144
+ ],
145
+ attributes: [
146
+ {
147
+ name: 'status',
148
+ type: 'Boolean'
149
+ }
150
+ ],
151
+ static_attributes: [
152
+ {
153
+ name: 'bootstrapServer',
154
+ type: 'Address',
155
+ value: '127.0.0.1'
156
+ }
157
+ ]
158
+ },
159
+ headers: {
160
+ 'fiware-service': 'testservice',
161
+ 'fiware-servicepath': '/testingPath'
162
+ },
163
+ qs: {
164
+ resource: '/deviceTest',
165
+ apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732'
166
+ }
167
+ };
168
+ const optionsGet = {
169
+ url: 'http://localhost:4041/iot/groups',
170
+ method: 'GET',
171
+ json: {},
172
+ headers: {
173
+ 'fiware-service': 'testservice',
174
+ 'fiware-servicepath': '/testingPath'
175
+ }
176
+ };
177
+ let iotAgentDb;
178
+
179
+ describe('MongoDB Group Registry test', function () {
180
+ beforeEach(function (done) {
181
+ mongoUtils.cleanDbs(function () {
182
+ iotAgentLib.activate(iotAgentConfig, function () {
183
+ mongo.connect('mongodb://localhost:27017/iotagent', { useNewUrlParser: true }, function (err, db) {
184
+ iotAgentDb = db;
185
+ done();
186
+ });
187
+ });
188
+ });
189
+ });
190
+
191
+ afterEach(function (done) {
192
+ iotAgentLib.deactivate(function () {
193
+ iotAgentDb.close(function (error) {
194
+ mongoUtils.cleanDbs(done);
195
+ });
196
+ });
197
+ });
198
+ describe('When a new device group creation request arrives', function () {
199
+ it('should store it in the DB', function (done) {
200
+ request(optionsCreation, function (error, response, body) {
201
+ iotAgentDb
202
+ .db()
203
+ .collection('groups')
204
+ .find({})
205
+ .toArray(function (err, docs) {
206
+ should.not.exist(err);
207
+ should.exist(docs);
208
+ should.exist(docs.length);
209
+ docs.length.should.equal(1);
210
+ should.exist(docs[0].type);
211
+ should.exist(docs[0].internalAttributes);
212
+ should.exist(docs[0].attributes);
213
+ should.exist(docs[0].apikey);
214
+ docs[0].type.should.equal('Light');
215
+ docs[0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732');
216
+ docs[0].internalAttributes.length.should.equal(1);
217
+ docs[0].internalAttributes[0].customField.should.equal('customValue');
218
+ docs[0].attributes.length.should.equal(1);
219
+ docs[0].attributes[0].name.should.equal('status');
220
+ done();
221
+ });
222
+ });
223
+ });
224
+ it('should store the service information from the headers into the DB', function (done) {
225
+ request(optionsCreation, function (error, response, body) {
226
+ iotAgentDb
227
+ .db()
228
+ .collection('groups')
229
+ .find({})
230
+ .toArray(function (err, docs) {
231
+ should.not.exist(err);
232
+ should.exist(docs[0].service);
233
+ should.exist(docs[0].subservice);
234
+ docs[0].service.should.equal('testservice');
235
+ docs[0].subservice.should.equal('/testingPath');
236
+ done();
237
+ });
238
+ });
239
+ });
240
+ });
241
+
242
+ describe('When a new device group creation request arrives with an existant (apikey, resource) pair', function () {
243
+ it('should return a DUPLICATE_GROUP error', function (done) {
244
+ request(optionsCreation, function (error, response, body) {
245
+ request(optionsCreation, function (error, response, body) {
246
+ response.statusCode.should.equal(409);
247
+ body.name.should.equal('DUPLICATE_GROUP');
248
+ done();
249
+ });
250
+ });
251
+ });
252
+ });
253
+
254
+ describe('When a device group removal request arrives', function () {
255
+ beforeEach(function (done) {
256
+ request(optionsCreation, done);
257
+ });
258
+
259
+ it('should remove it from the database', function (done) {
260
+ request(optionsDelete, function (error, response, body) {
261
+ iotAgentDb
262
+ .db()
263
+ .collection('groups')
264
+ .find({})
265
+ .toArray(function (err, docs) {
266
+ should.not.exist(err);
267
+ should.exist(docs);
268
+ should.exist(docs.length);
269
+ docs.length.should.equal(0);
270
+ done();
271
+ });
272
+ });
273
+ });
274
+
275
+ it('should return a 204 OK statusCode', function (done) {
276
+ request(optionsDelete, function (error, response, body) {
277
+ response.statusCode.should.equal(204);
278
+ done();
279
+ });
280
+ });
281
+ });
282
+
283
+ describe('When a device group update request arrives', function () {
284
+ beforeEach(function (done) {
285
+ request(optionsCreation, done);
286
+ });
287
+
288
+ it('should update the values in the database', function (done) {
289
+ request(optionsUpdate, function (error, response, body) {
290
+ iotAgentDb
291
+ .db()
292
+ .collection('groups')
293
+ .find({})
294
+ .toArray(function (err, docs) {
295
+ should.not.exist(err);
296
+ should.exist(docs);
297
+ should.exist(docs[0].cbHost);
298
+ docs[0].cbHost.should.equal('http://anotherUnexistentHost:1026');
299
+ should.exist(docs[0].staticAttributes);
300
+ docs[0].staticAttributes.length.should.equal(1);
301
+ done();
302
+ });
303
+ });
304
+ });
305
+ });
306
+
307
+ describe('When a multiple device group creation arrives', function () {
308
+ const optionsMultipleCreation = _.clone(optionsCreation);
309
+
310
+ beforeEach(function (done) {
311
+ optionsMultipleCreation.json = utils.readExampleFile(
312
+ './test/unit/examples/groupProvisioningRequests/multipleConfigGroupsCreation.json'
313
+ );
314
+
315
+ done();
316
+ });
317
+
318
+ it('should create the values in the database', function (done) {
319
+ request(optionsMultipleCreation, function (error, response, body) {
320
+ iotAgentDb
321
+ .db()
322
+ .collection('groups')
323
+ .find({})
324
+ .toArray(function (err, docs) {
325
+ should.not.exist(err);
326
+ should.exist(docs);
327
+ docs.length.should.equal(2);
328
+ done();
329
+ });
330
+ });
331
+ });
332
+ });
333
+
334
+ describe('When a device group listing request arrives', function () {
335
+ beforeEach(function (done) {
336
+ const optionsCreation1 = _.clone(optionsCreation);
337
+ const optionsCreation2 = _.clone(optionsCreation);
338
+ const optionsCreation3 = _.clone(optionsCreation);
339
+
340
+ optionsCreation2.json = { groups: [] };
341
+ optionsCreation3.json = { groups: [] };
342
+
343
+ optionsCreation2.json.groups[0] = _.clone(optionsCreation.json.groups[0]);
344
+ optionsCreation3.json.groups[0] = _.clone(optionsCreation.json.groups[0]);
345
+
346
+ optionsCreation2.json.groups[0].apikey = 'qwertyuiop';
347
+ optionsCreation3.json.groups[0].apikey = 'lkjhgfds';
348
+
349
+ async.series(
350
+ [
351
+ async.apply(request, optionsCreation1),
352
+ async.apply(request, optionsCreation2),
353
+ async.apply(request, optionsCreation3)
354
+ ],
355
+ done
356
+ );
357
+ });
358
+
359
+ it('should return all the configured device groups from the database', function (done) {
360
+ request(optionsList, function (error, response, body) {
361
+ body.count.should.equal(3);
362
+ done();
363
+ });
364
+ });
365
+ });
366
+
367
+ describe('When a device group listing arrives with a limit', function () {
368
+ const optionsConstrained = {
369
+ url: 'http://localhost:4041/iot/groups',
370
+ method: 'GET',
371
+ qs: {
372
+ limit: 3,
373
+ offset: 2
374
+ },
375
+ json: {},
376
+ headers: {
377
+ 'fiware-service': 'testservice',
378
+ 'fiware-servicepath': '/*'
379
+ }
380
+ };
381
+
382
+ beforeEach(function (done) {
383
+ const optionsCreationList = [];
384
+ const creationFns = [];
385
+
386
+ for (let i = 0; i < 10; i++) {
387
+ optionsCreationList[i] = _.clone(optionsCreation);
388
+ optionsCreationList[i].json = { groups: [] };
389
+ optionsCreationList[i].json.groups[0] = _.clone(optionsCreation.json.groups[0]);
390
+ optionsCreationList[i].json.groups[0].apikey = 'qwertyuiop' + i;
391
+ creationFns.push(async.apply(request, optionsCreationList[i]));
392
+ }
393
+
394
+ async.series(creationFns, done);
395
+ });
396
+
397
+ it('should return the appropriate count of groups', function (done) {
398
+ request(optionsConstrained, function (error, response, body) {
399
+ body.count.should.equal(10);
400
+ done();
401
+ });
402
+ });
403
+ });
404
+
405
+ describe('When a device info request arrives', function () {
406
+ beforeEach(function (done) {
407
+ async.series([async.apply(request, optionsCreation)], done);
408
+ });
409
+
410
+ it('should return all the configured device groups from the database', function (done) {
411
+ request(optionsGet, function (error, response, body) {
412
+ should.exist(body);
413
+ should.exist(body.count);
414
+ body.count.should.equal(1);
415
+ should.exist(body.groups);
416
+ should.exist(body.groups.length);
417
+ body.groups.length.should.equal(1);
418
+ body.groups[0].service.should.equal('testservice');
419
+ done();
420
+ });
421
+ });
422
+ });
423
+
424
+ describe('When a device info request arrives and multiple groups have been created', function () {
425
+ beforeEach(function (done) {
426
+ const optionsCreationList = [];
427
+ const creationFns = [];
428
+
429
+ for (let i = 0; i < 10; i++) {
430
+ optionsCreationList[i] = _.clone(optionsCreation);
431
+ optionsCreationList[i].json = { groups: [] };
432
+ optionsCreationList[i].json.groups[0] = _.clone(optionsCreation.json.groups[0]);
433
+ optionsCreationList[i].json.groups[0].apikey = 'qwertyuiop' + i;
434
+ creationFns.push(async.apply(request, optionsCreationList[i]));
435
+ }
436
+
437
+ async.series(creationFns, done);
438
+ });
439
+
440
+ it('should return all the configured device groups from the database', function (done) {
441
+ request(optionsGet, function (error, response, body) {
442
+ should.exist(body);
443
+ should.exist(body.count);
444
+ body.count.should.equal(10);
445
+ should.exist(body.groups);
446
+ should.exist(body.groups.length);
447
+ body.groups.length.should.equal(10);
448
+ done();
449
+ });
450
+ });
451
+ });
452
+ });
@@ -41,9 +41,8 @@ const iotAgentConfig = {
41
41
  host: 'localhost',
42
42
  baseRoot: '/'
43
43
  },
44
- stats: {
45
- interval: 50,
46
- persistence: true
44
+ deviceRegistry: {
45
+ type: 'mongodb'
47
46
  },
48
47
  types: {},
49
48
  service: 'smartgondor',