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