Files: 864bc27090fe788a4bf5a86c00246ca6e4391dd0 / tests / index.js
19076 bytesRaw
1 | const tape = require('tape') |
2 | const IPFS = require('ipfs') |
3 | const Hypervisor = require('../') |
4 | |
5 | // start ipfs |
6 | const node = new IPFS({ |
7 | start: false |
8 | }) |
9 | |
10 | class BaseContainer { |
11 | constructor (exInterface) { |
12 | this.exInterface = exInterface |
13 | } |
14 | |
15 | initailize (message) { |
16 | const port = message.ports[0] |
17 | if (port) { |
18 | this.exInterface.ports.bind('root', port) |
19 | } |
20 | } |
21 | } |
22 | |
23 | node.on('ready', () => { |
24 | tape('basic', async t => { |
25 | t.plan(2) |
26 | let message |
27 | const expectedState = { |
28 | '/': 'zdpuAyGKaZ3nbBQdgESbEgVYr81TcAFB6LE2MQQPWLZaYxuF3' |
29 | } |
30 | |
31 | class testVMContainer extends BaseContainer { |
32 | run (m) { |
33 | t.true(m === message, 'should recive a message') |
34 | } |
35 | } |
36 | |
37 | const hypervisor = new Hypervisor(node.dag) |
38 | hypervisor.registerContainer('test', testVMContainer) |
39 | |
40 | const rootContainer = await hypervisor.createInstance('test') |
41 | const port = rootContainer.ports.create('test') |
42 | message = rootContainer.createMessage() |
43 | rootContainer.ports.bind('first', port) |
44 | rootContainer.send(port, message) |
45 | |
46 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
47 | t.deepEquals(stateRoot, expectedState, 'expected root!') |
48 | }) |
49 | |
50 | tape('one child contract with saturated ports', async t => { |
51 | t.plan(2) |
52 | let message |
53 | const expectedState = { |
54 | '/': 'zdpuAtVcH6MUnvt2RXnLsDXyLB3CBSQ7aydfh2ogSKGCejJCQ' |
55 | } |
56 | |
57 | class testVMContainer2 extends BaseContainer { |
58 | run (m) { |
59 | t.true(m === message, 'should recive a message') |
60 | } |
61 | } |
62 | |
63 | class testVMContainer extends BaseContainer { |
64 | run (m) { |
65 | const port = this.exInterface.ports.create('test2') |
66 | this.exInterface.ports.bind('child', port) |
67 | this.exInterface.incrementTicks(2) |
68 | this.exInterface.send(port, m) |
69 | } |
70 | } |
71 | |
72 | const hypervisor = new Hypervisor(node.dag) |
73 | hypervisor.registerContainer('test', testVMContainer) |
74 | hypervisor.registerContainer('test2', testVMContainer2) |
75 | |
76 | let root = await hypervisor.createInstance('test') |
77 | let port = root.ports.create('test') |
78 | |
79 | root.ports.bind('first', port) |
80 | message = root.createMessage() |
81 | |
82 | root.send(port, message) |
83 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
84 | t.deepEquals(stateRoot, expectedState, 'expected state') |
85 | }) |
86 | |
87 | tape('one child contract', async t => { |
88 | t.plan(4) |
89 | let message |
90 | const expectedState = { |
91 | '/': 'zdpuAtVcH6MUnvt2RXnLsDXyLB3CBSQ7aydfh2ogSKGCejJCQ' |
92 | } |
93 | let hasResolved = false |
94 | |
95 | class testVMContainer2 extends BaseContainer { |
96 | run (m) { |
97 | t.true(m === message, 'should recive a message') |
98 | return new Promise((resolve, reject) => { |
99 | setTimeout(() => { |
100 | this.exInterface.incrementTicks(1) |
101 | hasResolved = true |
102 | resolve() |
103 | }, 200) |
104 | }) |
105 | } |
106 | } |
107 | |
108 | class testVMContainer extends BaseContainer { |
109 | run (m) { |
110 | const port = this.exInterface.ports.create('test2') |
111 | this.exInterface.ports.bind('child', port) |
112 | this.exInterface.send(port, m) |
113 | this.exInterface.incrementTicks(1) |
114 | } |
115 | } |
116 | |
117 | const hypervisor = new Hypervisor(node.dag) |
118 | hypervisor.registerContainer('test', testVMContainer) |
119 | hypervisor.registerContainer('test2', testVMContainer2) |
120 | |
121 | let root = await hypervisor.createInstance('test') |
122 | const rootId = root.id |
123 | let port = root.ports.create('test') |
124 | |
125 | root.ports.bind('first', port) |
126 | message = root.createMessage() |
127 | |
128 | root.send(port, message) |
129 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
130 | t.true(hasResolved, 'should resolve before generating the state root') |
131 | t.deepEquals(stateRoot, expectedState, 'expected state') |
132 | // test reviving the state |
133 | class testVMContainer3 extends BaseContainer { |
134 | run (m) { |
135 | const port = this.exInterface.ports.get('child') |
136 | this.exInterface.send(port, m) |
137 | this.exInterface.incrementTicks(1) |
138 | } |
139 | } |
140 | |
141 | hypervisor.registerContainer('test', testVMContainer3) |
142 | root = await hypervisor.getInstance(rootId) |
143 | port = root.ports.get('first') |
144 | root.send(port, message) |
145 | }) |
146 | |
147 | tape('traps', async t => { |
148 | t.plan(1) |
149 | class Root extends BaseContainer { |
150 | async run (m) { |
151 | const one = this.exInterface.ports.create('root') |
152 | const two = this.exInterface.ports.create('root') |
153 | const three = this.exInterface.ports.create('root') |
154 | |
155 | this.exInterface.ports.bind('one', one) |
156 | this.exInterface.ports.bind('two', two) |
157 | this.exInterface.ports.bind('three', three) |
158 | |
159 | throw new Error('it is a trap!!!') |
160 | } |
161 | } |
162 | |
163 | const hypervisor = new Hypervisor(node.dag) |
164 | |
165 | hypervisor.registerContainer('root', Root) |
166 | const root = await hypervisor.createInstance('root') |
167 | await root.run(root.createMessage()) |
168 | const stateRoot = await hypervisor.createStateRoot() |
169 | |
170 | t.deepEquals(stateRoot, { |
171 | '/': 'zdpuAwrMmQXqFusve7zcRYxVUuji4NVzZR5GyjwyStsjteCoW' |
172 | }, 'should revert the state') |
173 | }) |
174 | |
175 | tape('message should arrive in the correct oder if sent in order', async t => { |
176 | t.plan(2) |
177 | let runs = 0 |
178 | |
179 | class Root extends BaseContainer { |
180 | run (m) { |
181 | if (!runs) { |
182 | runs++ |
183 | const one = this.exInterface.ports.create('first') |
184 | const two = this.exInterface.ports.create('second') |
185 | |
186 | this.exInterface.ports.bind('one', one) |
187 | this.exInterface.ports.bind('two', two) |
188 | |
189 | this.exInterface.send(one, this.exInterface.createMessage()) |
190 | this.exInterface.send(two, this.exInterface.createMessage()) |
191 | } else if (runs === 1) { |
192 | runs++ |
193 | t.equals(m.data, 'second', 'should recived the second message') |
194 | } else if (runs === 2) { |
195 | t.equals(m.data, 'first', 'should recive the first message') |
196 | } |
197 | } |
198 | } |
199 | |
200 | class First extends BaseContainer { |
201 | run (m) { |
202 | this.exInterface.incrementTicks(2) |
203 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'first'})) |
204 | } |
205 | } |
206 | |
207 | class Second extends BaseContainer { |
208 | run (m) { |
209 | this.exInterface.incrementTicks(1) |
210 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'second'})) |
211 | } |
212 | } |
213 | |
214 | const hypervisor = new Hypervisor(node.dag) |
215 | |
216 | hypervisor.registerContainer('root', Root) |
217 | hypervisor.registerContainer('first', First) |
218 | hypervisor.registerContainer('second', Second) |
219 | |
220 | const root = await hypervisor.createInstance('root') |
221 | const port = root.ports.create('root') |
222 | root.ports.bind('first', port) |
223 | |
224 | root.send(port, root.createMessage()) |
225 | }) |
226 | |
227 | tape('message should arrive in the correct oder if sent in order', async t => { |
228 | t.plan(2) |
229 | let runs = 0 |
230 | |
231 | class Root extends BaseContainer { |
232 | run (m) { |
233 | if (!runs) { |
234 | runs++ |
235 | const one = this.exInterface.ports.create('first') |
236 | const two = this.exInterface.ports.create('second') |
237 | |
238 | this.exInterface.ports.bind('one', one) |
239 | this.exInterface.ports.bind('two', two) |
240 | |
241 | this.exInterface.send(one, this.exInterface.createMessage()) |
242 | this.exInterface.send(two, this.exInterface.createMessage()) |
243 | |
244 | this.exInterface.incrementTicks(6) |
245 | } else if (runs === 1) { |
246 | runs++ |
247 | t.equals(m.data, 'first', 'should recive the first message') |
248 | } else if (runs === 2) { |
249 | t.equals(m.data, 'second', 'should recived the second message') |
250 | } |
251 | } |
252 | } |
253 | |
254 | class First extends BaseContainer { |
255 | run (m) { |
256 | this.exInterface.incrementTicks(1) |
257 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'first'})) |
258 | } |
259 | } |
260 | |
261 | class Second extends BaseContainer { |
262 | run (m) { |
263 | this.exInterface.incrementTicks(2) |
264 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'second'})) |
265 | } |
266 | } |
267 | |
268 | const hypervisor = new Hypervisor(node.dag) |
269 | |
270 | hypervisor.registerContainer('root', Root) |
271 | hypervisor.registerContainer('first', First) |
272 | hypervisor.registerContainer('second', Second) |
273 | |
274 | const root = await hypervisor.createInstance('root') |
275 | const port = root.ports.create('root') |
276 | root.ports.bind('first', port) |
277 | |
278 | root.send(port, root.createMessage()) |
279 | }) |
280 | |
281 | tape('message should arrive in the correct order, even in a tie of ticks', async t => { |
282 | t.plan(2) |
283 | |
284 | let runs = 0 |
285 | |
286 | class Root extends BaseContainer { |
287 | run (m) { |
288 | if (!runs) { |
289 | runs++ |
290 | const one = this.exInterface.ports.create('first') |
291 | const two = this.exInterface.ports.create('second') |
292 | |
293 | this.exInterface.ports.bind('two', two) |
294 | this.exInterface.ports.bind('one', one) |
295 | |
296 | this.exInterface.send(one, this.exInterface.createMessage()) |
297 | this.exInterface.send(two, this.exInterface.createMessage()) |
298 | |
299 | this.exInterface.incrementTicks(6) |
300 | } else if (runs === 1) { |
301 | runs++ |
302 | t.equals(m.data, 'second', 'should recived the second message') |
303 | } else if (runs === 2) { |
304 | t.equals(m.data, 'first', 'should recive the first message') |
305 | } |
306 | } |
307 | } |
308 | |
309 | class First extends BaseContainer { |
310 | run (m) { |
311 | this.exInterface.incrementTicks(2) |
312 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
313 | data: 'first' |
314 | })) |
315 | } |
316 | } |
317 | |
318 | class Second extends BaseContainer { |
319 | run (m) { |
320 | this.exInterface.incrementTicks(2) |
321 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
322 | data: 'second' |
323 | })) |
324 | } |
325 | } |
326 | |
327 | const hypervisor = new Hypervisor(node.dag) |
328 | |
329 | hypervisor.registerContainer('root', Root) |
330 | hypervisor.registerContainer('first', First) |
331 | hypervisor.registerContainer('second', Second) |
332 | |
333 | const root = await hypervisor.createInstance('root') |
334 | |
335 | const port = root.ports.create('root') |
336 | root.ports.bind('first', port) |
337 | |
338 | root.send(port, root.createMessage()) |
339 | }) |
340 | |
341 | tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => { |
342 | t.plan(2) |
343 | |
344 | let runs = 0 |
345 | |
346 | class Root extends BaseContainer { |
347 | run (m) { |
348 | if (!runs) { |
349 | runs++ |
350 | const one = this.exInterface.ports.create('first') |
351 | const two = this.exInterface.ports.create('second') |
352 | |
353 | this.exInterface.ports.bind('one', one) |
354 | this.exInterface.ports.bind('two', two) |
355 | |
356 | this.exInterface.send(two, this.exInterface.createMessage()) |
357 | this.exInterface.send(one, this.exInterface.createMessage()) |
358 | |
359 | this.exInterface.incrementTicks(6) |
360 | } else if (runs === 1) { |
361 | runs++ |
362 | t.equals(m.data, 'first', 'should recive the first message') |
363 | } else if (runs === 2) { |
364 | t.equals(m.data, 'second', 'should recived the second message') |
365 | } |
366 | } |
367 | } |
368 | |
369 | class First extends BaseContainer { |
370 | run (m) { |
371 | this.exInterface.incrementTicks(2) |
372 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
373 | data: 'first' |
374 | })) |
375 | } |
376 | } |
377 | |
378 | class Second extends BaseContainer { |
379 | run (m) { |
380 | this.exInterface.incrementTicks(2) |
381 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
382 | data: 'second' |
383 | })) |
384 | } |
385 | } |
386 | |
387 | const hypervisor = new Hypervisor(node.dag) |
388 | |
389 | hypervisor.registerContainer('root', Root) |
390 | hypervisor.registerContainer('first', First) |
391 | hypervisor.registerContainer('second', Second) |
392 | |
393 | const root = await hypervisor.createInstance('root') |
394 | const port = root.ports.create('root') |
395 | root.ports.bind('first', port) |
396 | root.send(port, root.createMessage()) |
397 | }) |
398 | |
399 | tape('checking ports', async t => { |
400 | t.plan(4) |
401 | const hypervisor = new Hypervisor(node.dag) |
402 | hypervisor.registerContainer('base', BaseContainer) |
403 | |
404 | const root = await hypervisor.createInstance('base') |
405 | let port = root.ports.create('base') |
406 | await root.ports.bind('test', port) |
407 | |
408 | try { |
409 | root.createMessage({ |
410 | ports: [port] |
411 | }) |
412 | } catch (e) { |
413 | t.pass('should thow if sending a port that is bound') |
414 | } |
415 | |
416 | try { |
417 | await root.ports.bind('test', port) |
418 | } catch (e) { |
419 | t.pass('should thow if binding an already bound port') |
420 | } |
421 | |
422 | try { |
423 | let port2 = root.ports.create('base') |
424 | await root.ports.bind('test', port2) |
425 | } catch (e) { |
426 | t.pass('should thow if binding an already bound name') |
427 | } |
428 | |
429 | await root.ports.unbind('test') |
430 | const message = root.createMessage({ports: [port]}) |
431 | t.equals(message.ports[0], port, 'should create a message if the port is unbound') |
432 | }) |
433 | |
434 | tape('port deletion', async t => { |
435 | const expectedSr = { |
436 | '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z' |
437 | } |
438 | class Root extends BaseContainer { |
439 | run (m) { |
440 | const one = this.exInterface.ports.create('first') |
441 | this.exInterface.ports.bind('one', one) |
442 | this.exInterface.send(one, this.exInterface.createMessage()) |
443 | this.exInterface.incrementTicks(6) |
444 | } |
445 | } |
446 | |
447 | class First extends BaseContainer { |
448 | run (m) { |
449 | this.exInterface.incrementTicks(2) |
450 | this.exInterface.ports.delete('root') |
451 | } |
452 | } |
453 | |
454 | const hypervisor = new Hypervisor(node.dag) |
455 | |
456 | hypervisor.registerContainer('root', Root) |
457 | hypervisor.registerContainer('first', First) |
458 | |
459 | const root = await hypervisor.createInstance('root') |
460 | const port = root.ports.create('root') |
461 | root.ports.bind('first', port) |
462 | root.send(port, root.createMessage()) |
463 | const sr = await hypervisor.createStateRoot() |
464 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
465 | |
466 | t.end() |
467 | }) |
468 | |
469 | tape('clear unbounded ports', async t => { |
470 | const expectedSr = { |
471 | '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z' |
472 | } |
473 | class Root extends BaseContainer { |
474 | run (m) { |
475 | this.exInterface.ports.create('root') |
476 | } |
477 | } |
478 | |
479 | const hypervisor = new Hypervisor(node.dag) |
480 | |
481 | hypervisor.registerContainer('root', Root) |
482 | |
483 | const root = await hypervisor.createInstance('root') |
484 | const port = root.ports.create('root') |
485 | root.ports.bind('first', port) |
486 | root.send(port, root.createMessage()) |
487 | const sr = await hypervisor.createStateRoot() |
488 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
489 | |
490 | t.end() |
491 | }) |
492 | |
493 | tape('should remove subgraphs', async t => { |
494 | const expectedSr = { |
495 | '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z' |
496 | } |
497 | class Root extends BaseContainer { |
498 | run (m) { |
499 | this.exInterface.ports.create('sub') |
500 | } |
501 | } |
502 | |
503 | class Sub extends BaseContainer { |
504 | initailize (message) { |
505 | this.exInterface.ports.bind('root', message.ports[0]) |
506 | const port = this.exInterface.ports.create('root') |
507 | this.exInterface.ports.bind('child', port) |
508 | } |
509 | } |
510 | |
511 | const hypervisor = new Hypervisor(node.dag) |
512 | |
513 | hypervisor.registerContainer('root', Root) |
514 | hypervisor.registerContainer('sub', Sub) |
515 | |
516 | const root = await hypervisor.createInstance('root') |
517 | const port = root.ports.create('root') |
518 | root.ports.bind('first', port) |
519 | root.send(port, root.createMessage()) |
520 | const sr = await hypervisor.createStateRoot() |
521 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
522 | |
523 | t.end() |
524 | }) |
525 | |
526 | tape('should not remove connected nodes', async t => { |
527 | const expectedSr = { |
528 | '/': 'zdpuAwsZTd5mRZBCYA1FJSHrpYDPgSZSiaTQp9xkUeajaoMHM' |
529 | } |
530 | class Root extends BaseContainer { |
531 | run (m) { |
532 | if (m.ports.length) { |
533 | const port = this.exInterface.ports.get('test1') |
534 | this.exInterface.send(port, m) |
535 | this.exInterface.ports.unbind('test1') |
536 | // this.exInterface.ports.unbind('test2') |
537 | } else { |
538 | const port1 = this.exInterface.ports.create('sub') |
539 | this.exInterface.ports.bind('test1', port1) |
540 | const port2 = this.exInterface.ports.create('sub') |
541 | this.exInterface.ports.bind('test2', port2) |
542 | this.exInterface.send(port2, this.exInterface.createMessage({data: 'getChannel'})) |
543 | } |
544 | } |
545 | } |
546 | |
547 | class Sub extends BaseContainer { |
548 | run (message) { |
549 | if (message.data === 'getChannel') { |
550 | const ports = this.exInterface.ports.createChannel() |
551 | this.exInterface.ports.bind('channel', ports[0]) |
552 | this.exInterface.send(message.fromPort, this.exInterface.createMessage({ |
553 | data: 'bindPort', |
554 | ports: [ports[1]] |
555 | })) |
556 | } else if (message.data === 'bindPort') { |
557 | this.exInterface.ports.bind('channel', message.ports[0]) |
558 | } |
559 | } |
560 | } |
561 | |
562 | const hypervisor = new Hypervisor(node.dag) |
563 | |
564 | hypervisor.registerContainer('root', Root) |
565 | hypervisor.registerContainer('sub', Sub) |
566 | |
567 | const root = await hypervisor.createInstance('root') |
568 | const port = root.ports.create('root') |
569 | root.ports.bind('first', port) |
570 | root.send(port, root.createMessage()) |
571 | const sr = await hypervisor.createStateRoot() |
572 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
573 | // await hypervisor.graph.tree(sr, Infinity) |
574 | // console.log(JSON.stringify(sr, null, 2)) |
575 | |
576 | t.end() |
577 | }) |
578 | |
579 | tape('should remove multiple subgraphs', async t => { |
580 | const expectedSr = { |
581 | '/': 'zdpuAmi9tkYTpoVsZvqQgxpQFRhCgYFVv4W3fjjfVhf1j8swv' |
582 | } |
583 | class Root extends BaseContainer { |
584 | run (m) { |
585 | if (m.ports.length) { |
586 | const port = this.exInterface.ports.get('test1') |
587 | this.exInterface.send(port, m) |
588 | this.exInterface.ports.unbind('test1') |
589 | this.exInterface.ports.unbind('test2') |
590 | } else { |
591 | const port1 = this.exInterface.ports.create('sub') |
592 | this.exInterface.ports.bind('test1', port1) |
593 | const port2 = this.exInterface.ports.create('sub') |
594 | this.exInterface.ports.bind('test2', port2) |
595 | this.exInterface.send(port2, this.exInterface.createMessage({data: 'getChannel'})) |
596 | } |
597 | } |
598 | } |
599 | |
600 | class Sub extends BaseContainer { |
601 | run (message) { |
602 | if (message.data === 'getChannel') { |
603 | const ports = this.exInterface.ports.createChannel() |
604 | this.exInterface.ports.bind('channel', ports[0]) |
605 | this.exInterface.send(message.fromPort, this.exInterface.createMessage({ |
606 | data: 'bindPort', |
607 | ports: [ports[1]] |
608 | })) |
609 | } else if (message.data === 'bindPort') { |
610 | this.exInterface.ports.bind('channel', message.ports[0]) |
611 | } |
612 | } |
613 | } |
614 | |
615 | const hypervisor = new Hypervisor(node.dag) |
616 | |
617 | hypervisor.registerContainer('root', Root) |
618 | hypervisor.registerContainer('sub', Sub) |
619 | |
620 | const root = await hypervisor.createInstance('root') |
621 | const port = root.ports.create('root') |
622 | root.ports.bind('first', port) |
623 | root.send(port, root.createMessage()) |
624 | const sr = await hypervisor.createStateRoot() |
625 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
626 | |
627 | t.end() |
628 | }) |
629 | }) |
630 |
Built with git-ssb-web