UNPKG

16.2 kBJavaScriptView Raw
1var assert = require('assert');
2var os = require('os');
3var util = require('util');
4var request = require('supertest');
5var zetta = require('../');
6var Query = require('calypso').Query;
7var rels = require('zetta-rels');
8var Scout = require('./fixture/example_scout');
9var Driver = require('./fixture/example_driver');
10var HttpDriver = require('./fixture/example_http_driver');
11var Registry = require('./fixture/mem_registry');
12var PeerRegistry = require('./fixture/mem_peer_registry');
13var zettacluster = require('zetta-cluster');
14var Scientist = require('zetta-scientist');
15var Runtime = require('../zetta_runtime');
16var Device = Runtime.Device;
17
18function TestDriver() {
19 Device.call(this);
20 this.foo = 'fooData';
21 this.bar = 'barData';
22 this.id = '123456789';
23}
24util.inherits(TestDriver, Device);
25
26TestDriver.prototype.init = function(config) {
27 config
28 .name('Test')
29 .type('testdriver')
30 .state('ready');
31};
32
33
34function getHttpServer(app) {
35 return app.httpServer.server;
36}
37
38function getBody(fn) {
39 return function(res) {
40 try {
41 if(res.text) {
42 var body = JSON.parse(res.text);
43 } else {
44 var body = '';
45 }
46 } catch(err) {
47 throw new Error('Failed to parse json body');
48 }
49
50 fn(res, body);
51 }
52}
53
54function checkDeviceOnRootUri(entity) {
55 assert.deepEqual(entity.class, ['device']);
56 assert.deepEqual(entity.rel, ["http://rels.zettajs.io/device"]);
57
58 assert(entity.properties.name);
59 assert(entity.properties.type);
60 assert(entity.properties.state);
61 assert(!entity.actions); // should not have actions on it
62
63 assert(entity.links);
64 hasLinkRel(entity.links, rels.self);
65 hasLinkRel(entity.links, rels.server);
66}
67
68function hasLinkRel(links, rel, title, href) {
69 var found = false;
70
71 links.forEach(function(link) {
72 if(link.rel.indexOf(rel) != -1) {
73 found = true;
74
75 if(title !== undefined && link.title !== title) {
76 throw new Error('link title does not match');
77 }
78
79 if(href !== undefined && link.href !== href) {
80 throw new Error('link href does not match');
81 }
82 }
83 });
84
85 if(!found) {
86 throw new Error('Link rel:'+rel+' not found in links');
87 }
88}
89
90
91describe('Zetta Query Api', function() {
92 var reg = null;
93 var peerRegistry = null;
94
95 beforeEach(function() {
96 reg = new Registry();
97 peerRegistry = new PeerRegistry();
98 });
99
100 describe('invalid query', function() {
101 var app = null;
102
103 beforeEach(function() {
104 app = zetta({ registry: reg, peerRegistry: peerRegistry })
105 .silent()
106 .use(Scout)
107 .name('local')
108 .expose('*')
109 ._run();
110 });
111
112 it('returns an error on /', function(done) {
113 request(getHttpServer(app))
114 .get('/?ql=where%20')
115 .expect(getBody(function(res, body){
116 assert.deepEqual(body.class, ['query-error']);
117 }))
118 .end(done);
119 });
120
121 it('returns an error on / when querying across servers', function(done) {
122 request(getHttpServer(app))
123 .get('/?server=*&ql=where%20')
124 .expect(getBody(function(res, body){
125 assert.deepEqual(body.class, ['query-error']);
126 }))
127 .end(done);
128 });
129
130 it('returns an error on /servers/<id>', function(done) {
131 request(getHttpServer(app))
132 .get('/servers/local?ql=where%20')
133 .expect(getBody(function(res, body){
134 assert.deepEqual(body.class, ['query-error']);
135 }))
136 .end(done);
137 });
138 });
139
140 describe('queries on / with just a ql parameter', function() {
141 var app = null;
142
143 beforeEach(function() {
144 app = zetta({ registry: reg, peerRegistry: peerRegistry })
145 .silent()
146 .use(Scout)
147 .name('local')
148 .expose('*')
149 ._run();
150 });
151
152 it('should have two classes', function(done) {
153 request(getHttpServer(app))
154 .get('/?ql=where%20type%20=%20"testdriver"')
155 .expect(getBody(function(res, body){
156 assert.deepEqual(body.class, ['server', 'search-results']);
157 }))
158 .end(done);
159 });
160
161 it('should have two properties: server name and ql', function(done) {
162 request(getHttpServer(app))
163 .get('/?ql=where%20type%20=%20"testdriver"')
164 .expect(getBody(function(res, body) {
165 assert.equal(body.properties.name, 'local');
166 assert.equal(body.properties.ql, 'where type = "testdriver"');
167 }))
168 .end(done);
169 });
170
171 it('should have one action.', function(done) {
172 request(getHttpServer(app))
173 .get('/?ql=where%20type%20=%20"testdriver"')
174 .expect(getBody(function(res, body) {
175 assert.equal(body.actions.length, 1);
176 assert.equal(body.actions[0].name, 'query-devices');
177 }))
178 .end(done);
179 });
180
181 it('should have a websocket link to monitor the query.', function(done) {
182 request(getHttpServer(app))
183 .get('/?ql=where%20type%20=%20"testdriver"')
184 .expect(getBody(function(res, body) {
185 assert.equal(body.links.length, 4);
186 hasLinkRel(body.links, 'http://rels.zettajs.io/query');
187 assert.notEqual(body.links[3].href.indexOf("topic=query%2Fwhere%20type%20%3D%20%22testdriver%22"), -1);
188 }))
189 .end(done);
190 });
191 });
192
193 describe('queries on / with a ql parameter and a server parameter', function() {
194 var app = null;
195
196 beforeEach(function() {
197 app = zetta({ registry: reg, peerRegistry: peerRegistry })
198 .silent()
199 .use(Scout)
200 .name('local')
201 .expose('*')
202 ._run();
203 });
204
205 it('should have two classes', function(done) {
206 request(getHttpServer(app))
207 .get('/?ql=where%20type%20=%20"testdriver"&server=local')
208 .expect(getBody(function(res, body){
209 assert.deepEqual(body.class, ['server', 'search-results']);
210 }))
211 .end(done);
212 });
213
214 it('should have two properties: server name and ql', function(done) {
215 request(getHttpServer(app))
216 .get('/?ql=where%20type%20=%20"testdriver"&server=local')
217 .expect(getBody(function(res, body) {
218 assert.equal(body.properties.name, 'local');
219 assert.equal(body.properties.ql, 'where type = "testdriver"');
220 }))
221 .end(done);
222 });
223
224 it('should have no actions.', function(done) {
225 request(getHttpServer(app))
226 .get('/?ql=where%20type%20=%20"testdriver"&server=local')
227 .expect(getBody(function(res, body) {
228 assert.equal(body.actions.length, 1);
229 }))
230 .end(done);
231 });
232
233 it('should have a websocket link to monitor the query.', function(done) {
234 request(getHttpServer(app))
235 .get('/?ql=where%20type%20=%20"testdriver"&server=local')
236 .expect(getBody(function(res, body) {
237 assert.equal(body.links.length, 4);
238 hasLinkRel(body.links, 'http://rels.zettajs.io/query');
239 assert.notEqual(body.links[3].href.indexOf("topic=query%2Fwhere%20type%20%3D%20%22testdriver%22"), -1);
240 }))
241 .end(done);
242 });
243 });
244
245 describe('queries on / with a ql parameter and a server parameter that is proxied to', function() {
246 var app = null;
247 var cluster = null;
248
249 beforeEach(function(done) {
250 cluster = zettacluster({ zetta: zetta })
251 .server('cloud')
252 .server('detroit1', [Scout], ['cloud'])
253 .on('ready', function() {
254 app = cluster.servers['cloud'];
255 done();
256 })
257 .run(function(err){
258 if (err) {
259 return done(err);
260 }
261 });
262 });
263
264 it('should have two classes', function(done) {
265 request(getHttpServer(app))
266 .get('/?ql=where%20type%20=%20"testdriver"&server=detroit1')
267 .expect(getBody(function(res, body){
268 assert.deepEqual(body.class, ['root', 'search-results']);
269 }))
270 .end(done);
271 });
272
273 it('should have two properties: server name and ql', function(done) {
274 request(getHttpServer(app))
275 .get('/?ql=where%20type%20=%20"testdriver"&server=detroit1')
276 .expect(getBody(function(res, body) {
277 assert.equal(body.properties.server, 'detroit1');
278 assert.equal(body.properties.ql, 'where type = "testdriver"');
279 }))
280 .end(done);
281 });
282
283 it('should have no actions.', function(done) {
284 request(getHttpServer(app))
285 .get('/?ql=where%20type%20=%20"testdriver"&server=detroit1')
286 .expect(getBody(function(res, body) {
287 assert.ok(!body.actions);
288 }))
289 .end(done);
290 });
291
292 it('should have a websocket link to monitor the query.', function(done) {
293 request(getHttpServer(app))
294 .get('/?ql=where%20type%20=%20"testdriver"&server=detroit1')
295 .expect(getBody(function(res, body) {
296 assert.equal(body.links.length, 3);
297 hasLinkRel(body.links, 'http://rels.zettajs.io/query');
298 }))
299 .end(done);
300 });
301 });
302
303 describe('queries on / for all peers', function() {
304 var app = null;
305 var cluster = null;
306
307 beforeEach(function(done) {
308 cluster = zettacluster({ zetta: zetta })
309 .server('cloud')
310 .server('detroit1', [Scout], ['cloud'])
311 .server('detroit2', [Scout], ['cloud'])
312 .on('ready', function() {
313 app = cluster.servers['cloud'];
314 done();
315 })
316 .run(function(err){
317 if (err) {
318 return done(err);
319 }
320 });
321 });
322
323 it('should return results from each server', function(done) {
324 request(getHttpServer(app))
325 .get('/?ql=where%20type%20=%20"testdriver"&server=*')
326 .expect(getBody(function(res, body) {
327 assert.equal(body.entities.length, 2);
328 hasLinkRel(body.links, 'http://rels.zettajs.io/query');
329 }))
330 .end(done);
331 });
332 });
333
334 describe('Non provisioned devices', function() {
335 beforeEach(function(done) {
336 machine = Scientist.create(TestDriver);
337 Scientist.init(machine);
338 reg.save(machine, function(err) {
339 assert.ok(!err);
340 app = zetta({ registry: reg, peerRegistry: peerRegistry })
341 .silent()
342 .use(Scout)
343 .name('local')
344 .expose('*')
345 ._run();
346 done();
347 });
348 });
349
350 it('queries on /servers/<id> should return no results', function(done) {
351 request(getHttpServer(app))
352 .get('/servers/local?ql=where%20type%20=%20"testdriver"')
353 .expect(getBody(function(res, body) {
354 assert.equal(body.entities.length, 1);
355 body.entities.forEach(function(entity) {
356 assert(entity.links);
357 })
358 }))
359 .end(done);
360 })
361
362 it('queries on /?server=<server> should return no results', function(done) {
363 request(getHttpServer(app))
364 .get('/?ql=where%20type%20=%20"testdriver"&server=local')
365 .expect(getBody(function(res, body) {
366 assert.equal(body.entities.length, 1);
367 body.entities.forEach(function(entity) {
368 assert(entity.links);
369 })
370 }))
371 .end(done);
372 })
373
374 it('queries on /?server=* should return no results', function(done) {
375 request(getHttpServer(app))
376 .get('/?ql=where%20type%20=%20"testdriver"&server=*')
377 .expect(getBody(function(res, body) {
378 assert.equal(body.entities.length, 1);
379 body.entities.forEach(function(entity) {
380 assert(entity.links);
381 })
382 }))
383 .end(done);
384 })
385
386 it('queries on / should return no results', function(done) {
387 request(getHttpServer(app))
388 .get('/?ql=where%20type%20=%20"testdriver"')
389 .expect(getBody(function(res, body) {
390 assert.equal(body.entities.length, 1);
391 body.entities.forEach(function(entity) {
392 assert(entity.links);
393 })
394 }))
395 .end(done);
396 })
397 })
398
399 describe('queries on /servers/<id>', function() {
400 var app = null;
401
402 beforeEach(function() {
403 app = zetta({ registry: reg, peerRegistry: peerRegistry })
404 .silent()
405 .use(Scout)
406 .name('local')
407 .expose('*')
408 ._run();
409 });
410
411 it('should have two classes', function(done) {
412 request(getHttpServer(app))
413 .get('/servers/local?ql=where%20type%20=%20"testdriver"')
414 .expect(getBody(function(res, body){
415 assert.deepEqual(body.class, ['server', 'search-results']);
416 }))
417 .end(done);
418 });
419
420 it('should have two properties: server name and ql', function(done) {
421 request(getHttpServer(app))
422 .get('/servers/local?ql=where%20type%20=%20"testdriver"')
423 .expect(getBody(function(res, body) {
424 assert.equal(body.properties.name, 'local');
425 assert.equal(body.properties.ql, 'where type = "testdriver"');
426 }))
427 .end(done);
428 });
429
430 it('should have one action.', function(done) {
431 request(getHttpServer(app))
432 .get('/servers/local?ql=where%20type%20=%20"testdriver"')
433 .expect(getBody(function(res, body) {
434 assert.equal(body.actions.length, 1);
435 assert.equal(body.actions[0].name, 'query-devices');
436 }))
437 .end(done);
438 });
439
440 it('should have a websocket link to monitor the query.', function(done) {
441 request(getHttpServer(app))
442 .get('/servers/local?ql=where%20type%20=%20"testdriver"')
443 .expect(getBody(function(res, body) {
444 assert.equal(body.links.length, 4);
445 hasLinkRel(body.links, 'http://rels.zettajs.io/query');
446 assert.notEqual(body.links[3].href.indexOf("topic=query%2Fwhere%20type%20%3D%20%22testdriver%22"), -1);
447 }))
448 .end(done);
449 });
450
451
452 it('should return empty list if no devices are provisioned on server', function(done) {
453 var app = zetta({ registry: reg, peerRegistry: peerRegistry })
454 .silent()
455 .name('local')
456 ._run();
457
458 request(getHttpServer(app))
459 .get('/servers/local?ql=where%20type%20=%20"testdriver"')
460 .expect(getBody(function(res, body){
461 assert.equal(body.entities.length, 0);
462 assert.deepEqual(body.class, ['server', 'search-results']);
463 }))
464 .end(done);
465 });
466 });
467
468 describe('proxied queries on /servers/<id>', function() {
469 var app = null;
470 var cluster = null;
471
472 beforeEach(function(done) {
473 cluster = zettacluster({ zetta: zetta })
474 .server('cloud')
475 .server('detroit1', [Scout], ['cloud'])
476 .on('ready', function() {
477 app = cluster.servers['cloud'];
478 done();
479 })
480 .run(function(err){
481 if (err) {
482 return done(err);
483 }
484 });
485
486 });
487
488 it('should have two classes', function(done) {
489 request(getHttpServer(app))
490 .get('/servers/detroit1?ql=where%20type%20=%20"testdriver"')
491 .expect(getBody(function(res, body){
492 assert.deepEqual(body.class, ['server', 'search-results']);
493 }))
494 .end(done);
495 });
496
497 it('should have two properties: server name and ql', function(done) {
498 request(getHttpServer(app))
499 .get('/servers/detroit1?ql=where%20type%20=%20"testdriver"')
500 .expect(getBody(function(res, body) {
501 assert.equal(body.properties.name, 'detroit1');
502 assert.equal(body.properties.ql, 'where type = "testdriver"');
503 }))
504 .end(done);
505 });
506
507 it('should have one action.', function(done) {
508 request(getHttpServer(app))
509 .get('/servers/detroit1?ql=where%20type%20=%20"testdriver"')
510 .expect(getBody(function(res, body) {
511 assert.equal(body.actions.length, 1);
512 assert.equal(body.actions[0].name, 'query-devices');
513 }))
514 .end(done);
515 });
516
517 it('should have a websocket link to monitor the query.', function(done) {
518 request(getHttpServer(app))
519 .get('/servers/detroit1?ql=where%20type%20=%20"testdriver"')
520 .expect(getBody(function(res, body) {
521 assert.equal(body.links.length, 4);
522 hasLinkRel(body.links, 'http://rels.zettajs.io/query');
523 assert.notEqual(body.links[3].href.indexOf("topic=query%2Fwhere%20type%20%3D%20%22testdriver%22"), -1);
524 }))
525 .end(done);
526 });
527 });
528});