Files: 1e3ac999b894c127c15636b20fa61d8a5e60dd0f / tests / index.js
31745 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 (kernel) { |
12 | this.kernel = kernel |
13 | } |
14 | |
15 | initialize (message) { |
16 | this.kernel.state.code = message.data.byteLength ? message.data : undefined |
17 | const port = message.ports[0] |
18 | if (port) { |
19 | this.kernel.ports.bind('root', port) |
20 | } |
21 | } |
22 | |
23 | onIdle () { |
24 | this.kernel.shutdown() |
25 | } |
26 | } |
27 | |
28 | node.on('ready', () => { |
29 | tape('basic', async t => { |
30 | t.plan(3) |
31 | let message |
32 | const expectedState = { |
33 | '/': 'zdpuB1wc9Pb6jUzfNt4nAxAEUxB7kNhg4vbq7YLcEyBUb6iAB' |
34 | } |
35 | |
36 | class testVMContainer extends BaseContainer { |
37 | run (m) { |
38 | t.true(m === message, 'should recive a message') |
39 | } |
40 | } |
41 | |
42 | const hypervisor = new Hypervisor(node.dag) |
43 | hypervisor.registerContainer('test', testVMContainer) |
44 | |
45 | const rootContainer = await hypervisor.createInstance('test') |
46 | |
47 | const [portRef1, portRef2] = rootContainer.ports.createChannel() |
48 | const initMessage = rootContainer.createMessage({ |
49 | data: Buffer.from('test code'), |
50 | ports: [portRef2] |
51 | }) |
52 | |
53 | rootContainer.createInstance('test', initMessage) |
54 | |
55 | rootContainer.ports.bind('first', portRef1) |
56 | message = rootContainer.createMessage() |
57 | rootContainer.send(portRef1, message) |
58 | |
59 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
60 | t.deepEquals(stateRoot, expectedState, 'expected root!') |
61 | t.equals(hypervisor.scheduler.oldest(), 0) |
62 | }) |
63 | |
64 | tape('basic - do not store containers with no ports bound', async t => { |
65 | t.plan(1) |
66 | const expectedState = { |
67 | '/': 'zdpuAozDi6tKPbqmHJxo7aNES2xVt1MkaCLyxcioEKzz3M2WH' |
68 | } |
69 | |
70 | class testVMContainer extends BaseContainer { |
71 | initialize () {} |
72 | } |
73 | |
74 | const hypervisor = new Hypervisor(node.dag) |
75 | hypervisor.registerContainer('test', testVMContainer) |
76 | |
77 | const root = await hypervisor.createInstance('test') |
78 | const [portRef1, portRef2] = root.ports.createChannel() |
79 | |
80 | root.ports.bind('one', portRef1) |
81 | root.createInstance('test', root.createMessage({ |
82 | ports: [portRef2] |
83 | })) |
84 | |
85 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
86 | t.deepEquals(stateRoot, expectedState, 'expected root!') |
87 | }) |
88 | |
89 | tape('one child contract with saturated ports', async t => { |
90 | t.plan(2) |
91 | let message |
92 | const expectedState = { |
93 | '/': 'zdpuAtVcH6MUnvt2RXnLsDXyLB3CBSQ7aydfh2ogSKGCejJCQ' |
94 | } |
95 | |
96 | class testVMContainer2 extends BaseContainer { |
97 | run (m) { |
98 | t.true(m === message, 'should recive a message') |
99 | } |
100 | } |
101 | |
102 | class testVMContainer extends BaseContainer { |
103 | run (m) { |
104 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
105 | this.kernel.createInstance('test2', this.kernel.createMessage({ |
106 | ports: [portRef2] |
107 | })) |
108 | this.kernel.ports.bind('child', portRef1) |
109 | this.kernel.incrementTicks(2) |
110 | this.kernel.send(portRef1, m) |
111 | } |
112 | } |
113 | |
114 | const hypervisor = new Hypervisor(node.dag) |
115 | hypervisor.registerContainer('test', testVMContainer) |
116 | hypervisor.registerContainer('test2', testVMContainer2) |
117 | |
118 | const root = await hypervisor.createInstance('test') |
119 | const [portRef1, portRef2] = root.ports.createChannel() |
120 | root.createInstance('test', root.createMessage({ |
121 | ports: [portRef2] |
122 | })) |
123 | |
124 | root.ports.bind('first', portRef1) |
125 | message = root.createMessage({ |
126 | data: 'test' |
127 | }) |
128 | |
129 | root.send(portRef1, message) |
130 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
131 | t.deepEquals(stateRoot, expectedState, 'expected state') |
132 | }) |
133 | |
134 | tape('one child contract', async t => { |
135 | t.plan(4) |
136 | let message |
137 | const expectedState = { |
138 | '/': 'zdpuAtVcH6MUnvt2RXnLsDXyLB3CBSQ7aydfh2ogSKGCejJCQ' |
139 | } |
140 | let hasResolved = false |
141 | |
142 | class testVMContainer2 extends BaseContainer { |
143 | run (m) { |
144 | t.true(m === message, 'should recive a message') |
145 | return new Promise((resolve, reject) => { |
146 | setTimeout(() => { |
147 | this.kernel.incrementTicks(1) |
148 | hasResolved = true |
149 | resolve() |
150 | }, 200) |
151 | }) |
152 | } |
153 | } |
154 | |
155 | class testVMContainer extends BaseContainer { |
156 | run (m) { |
157 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
158 | this.kernel.createInstance('test2', this.kernel.createMessage({ |
159 | ports: [portRef2] |
160 | })) |
161 | this.kernel.ports.bind('child', portRef1) |
162 | this.kernel.send(portRef1, m) |
163 | this.kernel.incrementTicks(1) |
164 | } |
165 | } |
166 | |
167 | const hypervisor = new Hypervisor(node.dag) |
168 | hypervisor.registerContainer('test', testVMContainer) |
169 | hypervisor.registerContainer('test2', testVMContainer2) |
170 | |
171 | let root = await hypervisor.createInstance('test') |
172 | const rootId = root.id |
173 | const [portRef1, portRef2] = root.ports.createChannel() |
174 | root.createInstance('test', root.createMessage({ |
175 | ports: [portRef2] |
176 | })) |
177 | |
178 | root.ports.bind('first', portRef1) |
179 | message = root.createMessage() |
180 | |
181 | root.send(portRef1, message) |
182 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
183 | t.true(hasResolved, 'should resolve before generating the state root') |
184 | t.deepEquals(stateRoot, expectedState, 'expected state') |
185 | |
186 | // test reviving the state |
187 | class testVMContainer3 extends BaseContainer { |
188 | run (m) { |
189 | const port = this.kernel.ports.get('child') |
190 | this.kernel.send(port, m) |
191 | this.kernel.incrementTicks(1) |
192 | } |
193 | } |
194 | |
195 | hypervisor.registerContainer('test', testVMContainer3) |
196 | root = await hypervisor.getInstance(rootId) |
197 | const port = root.ports.get('first') |
198 | root.send(port, message) |
199 | }) |
200 | |
201 | tape('traps', async t => { |
202 | t.plan(1) |
203 | class Root extends BaseContainer { |
204 | async run (m) { |
205 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
206 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
207 | const [portRef5, portRef6] = this.kernel.ports.createChannel() |
208 | |
209 | this.kernel.ports.bind('one', portRef1) |
210 | this.kernel.ports.bind('two', portRef3) |
211 | this.kernel.ports.bind('three', portRef5) |
212 | |
213 | const message1 = this.kernel.createMessage({ |
214 | ports: [portRef2] |
215 | }) |
216 | const message2 = this.kernel.createMessage({ |
217 | ports: [portRef4] |
218 | }) |
219 | const message3 = this.kernel.createMessage({ |
220 | ports: [portRef6] |
221 | }) |
222 | |
223 | this.kernel.createInstance('root', message1) |
224 | this.kernel.createInstance('root', message2) |
225 | this.kernel.createInstance('root', message3) |
226 | |
227 | throw new Error('it is a trap!!!') |
228 | } |
229 | } |
230 | |
231 | const hypervisor = new Hypervisor(node.dag) |
232 | |
233 | hypervisor.registerContainer('root', Root) |
234 | const root = await hypervisor.createInstance('root') |
235 | await root.run(root.createMessage()) |
236 | const stateRoot = await hypervisor.createStateRoot() |
237 | |
238 | t.deepEquals(stateRoot, { |
239 | '/': 'zdpuAwrMmQXqFusve7zcRYxVUuji4NVzZR5GyjwyStsjteCoW' |
240 | }, 'should revert the state') |
241 | }) |
242 | |
243 | tape('message should arrive in the correct oder if sent in order', async t => { |
244 | t.plan(2) |
245 | let runs = 0 |
246 | |
247 | class Root extends BaseContainer { |
248 | run (m) { |
249 | if (!runs) { |
250 | runs++ |
251 | |
252 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
253 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
254 | |
255 | this.kernel.ports.bind('two', portRef3) |
256 | this.kernel.ports.bind('one', portRef1) |
257 | |
258 | const message1 = this.kernel.createMessage({ |
259 | ports: [portRef2] |
260 | }) |
261 | const message2 = this.kernel.createMessage({ |
262 | ports: [portRef4] |
263 | }) |
264 | |
265 | this.kernel.createInstance('first', message1) |
266 | this.kernel.createInstance('second', message2) |
267 | |
268 | this.kernel.send(portRef1, this.kernel.createMessage()) |
269 | this.kernel.send(portRef3, this.kernel.createMessage()) |
270 | } else if (runs === 1) { |
271 | runs++ |
272 | t.equals(m.data, 'first', 'should recive the first message') |
273 | } else if (runs === 2) { |
274 | t.equals(m.data, 'second', 'should recived the second message') |
275 | } |
276 | } |
277 | } |
278 | |
279 | class First extends BaseContainer { |
280 | run (m) { |
281 | this.kernel.incrementTicks(2) |
282 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
283 | data: 'first' |
284 | })) |
285 | } |
286 | } |
287 | |
288 | class Second extends BaseContainer { |
289 | run (m) { |
290 | this.kernel.incrementTicks(3) |
291 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
292 | data: 'second' |
293 | })) |
294 | } |
295 | } |
296 | |
297 | const hypervisor = new Hypervisor(node.dag) |
298 | |
299 | hypervisor.registerContainer('root', Root) |
300 | hypervisor.registerContainer('first', First) |
301 | hypervisor.registerContainer('second', Second) |
302 | |
303 | const root = await hypervisor.createInstance('root') |
304 | |
305 | const [portRef1, portRef2] = root.ports.createChannel() |
306 | root.createInstance('root', root.createMessage({ |
307 | ports: [portRef2] |
308 | })) |
309 | |
310 | root.ports.bind('first', portRef1) |
311 | const message = root.createMessage() |
312 | root.send(portRef1, message) |
313 | }) |
314 | |
315 | tape('message should arrive in the correct oder if sent in order', async t => { |
316 | t.plan(2) |
317 | let runs = 0 |
318 | |
319 | class Root extends BaseContainer { |
320 | run (m) { |
321 | if (!runs) { |
322 | runs++ |
323 | |
324 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
325 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
326 | |
327 | this.kernel.ports.bind('one', portRef1) |
328 | this.kernel.ports.bind('two', portRef3) |
329 | |
330 | const message1 = this.kernel.createMessage({ |
331 | ports: [portRef2] |
332 | }) |
333 | const message2 = this.kernel.createMessage({ |
334 | ports: [portRef4] |
335 | }) |
336 | |
337 | this.kernel.createInstance('first', message1) |
338 | this.kernel.createInstance('second', message2) |
339 | |
340 | this.kernel.send(portRef1, this.kernel.createMessage()) |
341 | this.kernel.send(portRef3, this.kernel.createMessage()) |
342 | } else if (runs === 1) { |
343 | runs++ |
344 | t.equals(m.data, 'second', 'should recived the second message') |
345 | } else if (runs === 2) { |
346 | t.equals(m.data, 'first', 'should recive the first message') |
347 | } |
348 | } |
349 | } |
350 | |
351 | class First extends BaseContainer { |
352 | run (m) { |
353 | this.kernel.incrementTicks(2) |
354 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
355 | data: 'first' |
356 | })) |
357 | } |
358 | } |
359 | |
360 | class Second extends BaseContainer { |
361 | run (m) { |
362 | this.kernel.incrementTicks(1) |
363 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
364 | data: 'second' |
365 | })) |
366 | } |
367 | } |
368 | |
369 | const hypervisor = new Hypervisor(node.dag) |
370 | |
371 | hypervisor.registerContainer('root', Root) |
372 | hypervisor.registerContainer('first', First) |
373 | hypervisor.registerContainer('second', Second) |
374 | |
375 | const root = await hypervisor.createInstance('root') |
376 | |
377 | const [portRef1, portRef2] = root.ports.createChannel() |
378 | root.createInstance('root', root.createMessage({ |
379 | ports: [portRef2] |
380 | })) |
381 | |
382 | root.ports.bind('first', portRef1) |
383 | const message = root.createMessage() |
384 | root.send(portRef1, message) |
385 | }) |
386 | |
387 | tape('message should arrive in the correct oder if sent in order', async t => { |
388 | t.plan(2) |
389 | let runs = 0 |
390 | |
391 | class Root extends BaseContainer { |
392 | run (m) { |
393 | if (!runs) { |
394 | runs++ |
395 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
396 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
397 | |
398 | this.kernel.ports.bind('one', portRef1) |
399 | this.kernel.ports.bind('two', portRef3) |
400 | |
401 | const message1 = this.kernel.createMessage({ |
402 | ports: [portRef2] |
403 | }) |
404 | const message2 = this.kernel.createMessage({ |
405 | ports: [portRef4] |
406 | }) |
407 | |
408 | this.kernel.createInstance('first', message1) |
409 | this.kernel.createInstance('second', message2) |
410 | |
411 | this.kernel.send(portRef1, this.kernel.createMessage()) |
412 | this.kernel.send(portRef3, this.kernel.createMessage()) |
413 | |
414 | this.kernel.incrementTicks(6) |
415 | } else if (runs === 1) { |
416 | runs++ |
417 | t.equals(m.data, 'first', 'should recive the first message') |
418 | } else if (runs === 2) { |
419 | t.equals(m.data, 'second', 'should recived the second message') |
420 | } |
421 | } |
422 | } |
423 | |
424 | class First extends BaseContainer { |
425 | run (m) { |
426 | this.kernel.incrementTicks(1) |
427 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
428 | data: 'first' |
429 | })) |
430 | } |
431 | } |
432 | |
433 | class Second extends BaseContainer { |
434 | run (m) { |
435 | this.kernel.incrementTicks(2) |
436 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
437 | data: 'second' |
438 | })) |
439 | } |
440 | } |
441 | |
442 | const hypervisor = new Hypervisor(node.dag) |
443 | |
444 | hypervisor.registerContainer('root', Root) |
445 | hypervisor.registerContainer('first', First) |
446 | hypervisor.registerContainer('second', Second) |
447 | |
448 | const root = await hypervisor.createInstance('root') |
449 | const [portRef1, portRef2] = root.ports.createChannel() |
450 | root.createInstance('root', root.createMessage({ |
451 | ports: [portRef2] |
452 | })) |
453 | |
454 | root.ports.bind('first', portRef1) |
455 | const message = root.createMessage() |
456 | root.send(portRef1, message) |
457 | }) |
458 | |
459 | tape('saturation', async t => { |
460 | t.plan(2) |
461 | let runs = 0 |
462 | |
463 | class Root extends BaseContainer { |
464 | run (m) { |
465 | if (!runs) { |
466 | runs++ |
467 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
468 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
469 | |
470 | this.kernel.ports.bind('one', portRef1) |
471 | this.kernel.ports.bind('two', portRef3) |
472 | |
473 | const message1 = this.kernel.createMessage({ |
474 | ports: [portRef2] |
475 | }) |
476 | const message2 = this.kernel.createMessage({ |
477 | ports: [portRef4] |
478 | }) |
479 | |
480 | this.kernel.createInstance('first', message1) |
481 | this.kernel.createInstance('second', message2) |
482 | |
483 | this.kernel.send(portRef1, this.kernel.createMessage()) |
484 | this.kernel.send(portRef3, this.kernel.createMessage()) |
485 | |
486 | this.kernel.incrementTicks(6) |
487 | } else if (runs === 1) { |
488 | runs++ |
489 | t.equals(m.data, 'first', 'should recive the first message') |
490 | } else if (runs === 2) { |
491 | runs++ |
492 | t.equals(m.data, 'second', 'should recived the second message') |
493 | } |
494 | } |
495 | } |
496 | |
497 | class First extends BaseContainer { |
498 | run (m) { |
499 | this.kernel.incrementTicks(2) |
500 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
501 | data: 'first' |
502 | })) |
503 | } |
504 | } |
505 | |
506 | class Second extends BaseContainer { |
507 | run (m) { |
508 | this.kernel.incrementTicks(3) |
509 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
510 | data: 'second' |
511 | })) |
512 | } |
513 | } |
514 | |
515 | class Waiter extends BaseContainer { |
516 | initialize () { |
517 | return new Promise((resolve, reject) => { |
518 | setTimeout(() => { |
519 | resolve() |
520 | }, 200) |
521 | }) |
522 | } |
523 | } |
524 | |
525 | const hypervisor = new Hypervisor(node.dag) |
526 | |
527 | hypervisor.registerContainer('root', Root) |
528 | hypervisor.registerContainer('first', First) |
529 | hypervisor.registerContainer('second', Second) |
530 | hypervisor.registerContainer('waiter', Waiter) |
531 | |
532 | const root = await hypervisor.createInstance('root') |
533 | const [portRef1, portRef2] = root.ports.createChannel() |
534 | |
535 | const message = root.createMessage() |
536 | root.send(portRef1, message) |
537 | root.ports.bind('first', portRef1) |
538 | root.createInstance('root', root.createMessage({ |
539 | ports: [portRef2] |
540 | })) |
541 | |
542 | const [portRef3, portRef4] = root.ports.createChannel() |
543 | root.ports.bind('sencond', portRef3) |
544 | root.createInstance('waiter', root.createMessage({ |
545 | ports: [portRef4] |
546 | })) |
547 | |
548 | root.incrementTicks(100) |
549 | root.send(portRef1, root.createMessage({data: 'testss'})) |
550 | hypervisor.scheduler.done(root.id) |
551 | }) |
552 | |
553 | tape('message should arrive in the correct order, even in a tie of ticks', async t => { |
554 | t.plan(2) |
555 | |
556 | let runs = 0 |
557 | |
558 | class Root extends BaseContainer { |
559 | run (m) { |
560 | if (!runs) { |
561 | runs++ |
562 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
563 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
564 | |
565 | this.kernel.ports.bind('two', portRef3) |
566 | this.kernel.ports.bind('one', portRef1) |
567 | |
568 | const message1 = this.kernel.createMessage({ |
569 | ports: [portRef2] |
570 | }) |
571 | const message2 = this.kernel.createMessage({ |
572 | ports: [portRef4] |
573 | }) |
574 | |
575 | this.kernel.createInstance('first', message1) |
576 | this.kernel.createInstance('second', message2) |
577 | |
578 | this.kernel.send(portRef1, this.kernel.createMessage()) |
579 | this.kernel.send(portRef3, this.kernel.createMessage()) |
580 | |
581 | this.kernel.incrementTicks(6) |
582 | } else if (runs === 1) { |
583 | runs++ |
584 | t.equals(m.data, 'second', 'should recived the second message') |
585 | } else if (runs === 2) { |
586 | t.equals(m.data, 'first', 'should recive the first message') |
587 | } |
588 | } |
589 | } |
590 | |
591 | class First extends BaseContainer { |
592 | run (m) { |
593 | this.kernel.incrementTicks(2) |
594 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
595 | data: 'first' |
596 | })) |
597 | } |
598 | } |
599 | |
600 | class Second extends BaseContainer { |
601 | run (m) { |
602 | this.kernel.incrementTicks(2) |
603 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
604 | data: 'second' |
605 | })) |
606 | } |
607 | } |
608 | |
609 | const hypervisor = new Hypervisor(node.dag) |
610 | |
611 | hypervisor.registerContainer('root', Root) |
612 | hypervisor.registerContainer('first', First) |
613 | hypervisor.registerContainer('second', Second) |
614 | |
615 | const root = await hypervisor.createInstance('root') |
616 | const [portRef1, portRef2] = root.ports.createChannel() |
617 | const message = root.createMessage() |
618 | |
619 | root.send(portRef1, message) |
620 | root.ports.bind('first', portRef1) |
621 | root.createInstance('root', root.createMessage({ |
622 | ports: [portRef2] |
623 | })) |
624 | }) |
625 | |
626 | tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => { |
627 | t.plan(2) |
628 | |
629 | let runs = 0 |
630 | |
631 | class Root extends BaseContainer { |
632 | run (m) { |
633 | if (!runs) { |
634 | runs++ |
635 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
636 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
637 | |
638 | this.kernel.ports.bind('one', portRef1) |
639 | this.kernel.ports.bind('two', portRef3) |
640 | |
641 | const message1 = this.kernel.createMessage({ |
642 | ports: [portRef2] |
643 | }) |
644 | const message2 = this.kernel.createMessage({ |
645 | ports: [portRef4] |
646 | }) |
647 | |
648 | this.kernel.createInstance('first', message1) |
649 | this.kernel.createInstance('second', message2) |
650 | |
651 | this.kernel.send(portRef1, this.kernel.createMessage()) |
652 | this.kernel.send(portRef3, this.kernel.createMessage()) |
653 | |
654 | this.kernel.incrementTicks(6) |
655 | } else if (runs === 1) { |
656 | runs++ |
657 | t.equals(m.data, 'first', 'should recive the first message') |
658 | } else if (runs === 2) { |
659 | t.equals(m.data, 'second', 'should recived the second message') |
660 | } |
661 | } |
662 | } |
663 | |
664 | class First extends BaseContainer { |
665 | run (m) { |
666 | this.kernel.incrementTicks(2) |
667 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
668 | data: 'first' |
669 | })) |
670 | } |
671 | } |
672 | |
673 | class Second extends BaseContainer { |
674 | run (m) { |
675 | this.kernel.incrementTicks(2) |
676 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
677 | data: 'second' |
678 | })) |
679 | } |
680 | } |
681 | |
682 | const hypervisor = new Hypervisor(node.dag) |
683 | |
684 | hypervisor.registerContainer('root', Root) |
685 | hypervisor.registerContainer('first', First) |
686 | hypervisor.registerContainer('second', Second) |
687 | |
688 | const root = await hypervisor.createInstance('root') |
689 | const [portRef1, portRef2] = root.ports.createChannel() |
690 | const message = root.createMessage() |
691 | |
692 | root.send(portRef1, message) |
693 | root.ports.bind('first', portRef1) |
694 | root.createInstance('root', root.createMessage({ |
695 | ports: [portRef2] |
696 | })) |
697 | }) |
698 | |
699 | tape('send to the same container at the same time', async t => { |
700 | t.plan(2) |
701 | |
702 | let runs = 0 |
703 | let instance |
704 | |
705 | class Root extends BaseContainer { |
706 | run (m) { |
707 | let one = this.kernel.ports.get('one') |
708 | if (!one) { |
709 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
710 | this.kernel.ports.bind('one', portRef1) |
711 | const message1 = this.kernel.createMessage({ |
712 | ports: [portRef2] |
713 | }) |
714 | this.kernel.createInstance('first', message1) |
715 | } else { |
716 | this.kernel.send(one, this.kernel.createMessage()) |
717 | this.kernel.send(one, this.kernel.createMessage()) |
718 | } |
719 | } |
720 | } |
721 | |
722 | class First extends BaseContainer { |
723 | run (m) { |
724 | ++runs |
725 | if (runs === 2) { |
726 | t.equals(instance, this, 'should have same instances') |
727 | } else { |
728 | instance = this |
729 | } |
730 | } |
731 | } |
732 | |
733 | const hypervisor = new Hypervisor(node.dag) |
734 | |
735 | hypervisor.registerContainer('root', Root) |
736 | hypervisor.registerContainer('first', First) |
737 | |
738 | const root = await hypervisor.createInstance('root') |
739 | const [portRef1, portRef2] = root.ports.createChannel() |
740 | root.ports.bind('first', portRef1) |
741 | root.createInstance('root', root.createMessage({ |
742 | ports: [portRef2] |
743 | })) |
744 | |
745 | const message = root.createMessage() |
746 | root.send(portRef1, message) |
747 | await hypervisor.createStateRoot() |
748 | root.send(portRef1, root.createMessage()) |
749 | await hypervisor.createStateRoot() |
750 | t.equals(runs, 2) |
751 | }) |
752 | |
753 | tape('checking ports', async t => { |
754 | t.plan(4) |
755 | const hypervisor = new Hypervisor(node.dag) |
756 | hypervisor.registerContainer('base', BaseContainer) |
757 | |
758 | const root = await hypervisor.createInstance('base') |
759 | |
760 | const [portRef1, portRef2] = root.ports.createChannel() |
761 | root.createInstance('base', root.createMessage({ |
762 | ports: [portRef2] |
763 | })) |
764 | root.ports.bind('test', portRef1) |
765 | |
766 | try { |
767 | root.createMessage({ |
768 | ports: [portRef1] |
769 | }) |
770 | } catch (e) { |
771 | t.pass('should thow if sending a port that is bound') |
772 | } |
773 | |
774 | try { |
775 | await root.ports.bind('test', portRef1) |
776 | } catch (e) { |
777 | t.pass('should thow if binding an already bound port') |
778 | } |
779 | |
780 | try { |
781 | const [portRef3] = root.ports.createChannel() |
782 | await root.ports.bind('test', portRef3) |
783 | } catch (e) { |
784 | t.pass('should thow if binding an already bound name') |
785 | } |
786 | |
787 | await root.ports.unbind('test') |
788 | const message = root.createMessage({ |
789 | ports: [portRef1] |
790 | }) |
791 | t.equals(message.ports[0], portRef1, 'should create a message if the port is unbound') |
792 | }) |
793 | |
794 | tape('port deletion', async t => { |
795 | const expectedSr = { |
796 | '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z' |
797 | } |
798 | class Root extends BaseContainer { |
799 | run (m) { |
800 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
801 | this.kernel.ports.bind('one', portRef1) |
802 | const message1 = this.kernel.createMessage({ |
803 | ports: [portRef2] |
804 | }) |
805 | |
806 | this.kernel.createInstance('first', message1) |
807 | this.kernel.send(portRef1, this.kernel.createMessage()) |
808 | this.kernel.incrementTicks(6) |
809 | } |
810 | } |
811 | |
812 | class First extends BaseContainer { |
813 | run (m) { |
814 | this.kernel.incrementTicks(2) |
815 | this.kernel.ports.delete('root') |
816 | } |
817 | } |
818 | |
819 | const hypervisor = new Hypervisor(node.dag) |
820 | |
821 | hypervisor.registerContainer('root', Root) |
822 | hypervisor.registerContainer('first', First) |
823 | |
824 | const root = await hypervisor.createInstance('root') |
825 | const [portRef1, portRef2] = root.ports.createChannel() |
826 | root.ports.bind('first', portRef1) |
827 | root.createInstance('root', root.createMessage({ |
828 | ports: [portRef2] |
829 | })) |
830 | |
831 | const message = root.createMessage() |
832 | root.send(portRef1, message) |
833 | |
834 | const sr = await hypervisor.createStateRoot() |
835 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
836 | |
837 | t.end() |
838 | }) |
839 | |
840 | tape('clear unbounded ports', async t => { |
841 | const expectedSr = { |
842 | '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z' |
843 | } |
844 | class Root extends BaseContainer { |
845 | run (m) { |
846 | this.kernel.createInstance('root') |
847 | } |
848 | } |
849 | |
850 | const hypervisor = new Hypervisor(node.dag) |
851 | |
852 | hypervisor.registerContainer('root', Root) |
853 | |
854 | const root = await hypervisor.createInstance('root') |
855 | const [portRef1, portRef2] = root.ports.createChannel() |
856 | root.ports.bind('first', portRef1) |
857 | root.createInstance('root', root.createMessage({ |
858 | ports: [portRef2] |
859 | })) |
860 | |
861 | const message = root.createMessage() |
862 | root.send(portRef1, message) |
863 | const sr = await hypervisor.createStateRoot() |
864 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
865 | |
866 | t.end() |
867 | }) |
868 | |
869 | tape('should remove subgraphs', async t => { |
870 | const expectedSr = { |
871 | '/': 'zdpuB2QXxn1KQtLFfBqaritTRoe5BuKP5sNFSrPtRT6sxkY7Z' |
872 | } |
873 | class Root extends BaseContainer { |
874 | run (m) { |
875 | const [, portRef2] = this.kernel.ports.createChannel() |
876 | this.kernel.createInstance('sub', this.kernel.createMessage({ |
877 | ports: [portRef2] |
878 | })) |
879 | } |
880 | } |
881 | |
882 | class Sub extends BaseContainer { |
883 | initailize (message) { |
884 | this.kernel.ports.bind('root', message.ports[0]) |
885 | const [portRef1, portRef2] = root.ports.createChannel() |
886 | root.ports.bind('child', portRef1) |
887 | root.createInstance('root', root.createMessage({ |
888 | ports: [portRef2] |
889 | })) |
890 | } |
891 | } |
892 | |
893 | const hypervisor = new Hypervisor(node.dag) |
894 | |
895 | hypervisor.registerContainer('root', Root) |
896 | hypervisor.registerContainer('sub', Sub) |
897 | |
898 | const root = await hypervisor.createInstance('root') |
899 | const [portRef1, portRef2] = root.ports.createChannel() |
900 | root.ports.bind('first', portRef1) |
901 | root.createInstance('root', root.createMessage({ |
902 | ports: [portRef2] |
903 | })) |
904 | |
905 | root.send(portRef1, root.createMessage()) |
906 | const sr = await hypervisor.createStateRoot() |
907 | |
908 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
909 | t.end() |
910 | }) |
911 | |
912 | tape('should not remove connected nodes', async t => { |
913 | const expectedSr = { |
914 | '/': 'zdpuAwsZTd5mRZBCYA1FJSHrpYDPgSZSiaTQp9xkUeajaoMHM' |
915 | } |
916 | class Root extends BaseContainer { |
917 | run (m) { |
918 | if (m.ports.length) { |
919 | const port = this.kernel.ports.get('test1') |
920 | this.kernel.send(port, m) |
921 | this.kernel.ports.unbind('test1') |
922 | } else { |
923 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
924 | this.kernel.createInstance('sub', this.kernel.createMessage({ |
925 | ports: [portRef2] |
926 | })) |
927 | this.kernel.ports.bind('test1', portRef1) |
928 | |
929 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
930 | this.kernel.createInstance('sub', this.kernel.createMessage({ |
931 | ports: [portRef4] |
932 | })) |
933 | this.kernel.ports.bind('test2', portRef3) |
934 | this.kernel.send(portRef3, this.kernel.createMessage({ |
935 | data: 'getChannel' |
936 | })) |
937 | } |
938 | } |
939 | } |
940 | |
941 | class Sub extends BaseContainer { |
942 | run (message) { |
943 | if (message.data === 'getChannel') { |
944 | const ports = this.kernel.ports.createChannel() |
945 | this.kernel.ports.bind('channel', ports[0]) |
946 | this.kernel.send(message.fromPort, this.kernel.createMessage({ |
947 | data: 'bindPort', |
948 | ports: [ports[1]] |
949 | })) |
950 | } else if (message.data === 'bindPort') { |
951 | this.kernel.ports.bind('channel', message.ports[0]) |
952 | } |
953 | } |
954 | } |
955 | |
956 | const hypervisor = new Hypervisor(node.dag) |
957 | |
958 | hypervisor.registerContainer('root', Root) |
959 | hypervisor.registerContainer('sub', Sub) |
960 | |
961 | const root = await hypervisor.createInstance('root') |
962 | const [portRef1, portRef2] = root.ports.createChannel() |
963 | root.ports.bind('first', portRef1) |
964 | root.createInstance('root', root.createMessage({ |
965 | ports: [portRef2] |
966 | })) |
967 | |
968 | root.send(portRef1, root.createMessage()) |
969 | const sr = await hypervisor.createStateRoot() |
970 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
971 | // await hypervisor.graph.tree(sr, Infinity) |
972 | |
973 | t.end() |
974 | }) |
975 | |
976 | tape('should remove multiple subgraphs', async t => { |
977 | const expectedSr = { |
978 | '/': 'zdpuAmi9tkYTpoVsZvqQgxpQFRhCgYFVv4W3fjjfVhf1j8swv' |
979 | } |
980 | class Root extends BaseContainer { |
981 | run (m) { |
982 | if (m.ports.length) { |
983 | const port = this.kernel.ports.get('test1') |
984 | this.kernel.send(port, m) |
985 | this.kernel.ports.unbind('test1') |
986 | this.kernel.ports.unbind('test2') |
987 | } else { |
988 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
989 | this.kernel.createInstance('sub', this.kernel.createMessage({ |
990 | ports: [portRef2] |
991 | })) |
992 | this.kernel.ports.bind('test1', portRef1) |
993 | |
994 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
995 | this.kernel.createInstance('sub', this.kernel.createMessage({ |
996 | ports: [portRef4] |
997 | })) |
998 | this.kernel.ports.bind('test2', portRef3) |
999 | this.kernel.send(portRef3, this.kernel.createMessage({ |
1000 | data: 'getChannel' |
1001 | })) |
1002 | } |
1003 | } |
1004 | } |
1005 | |
1006 | class Sub extends BaseContainer { |
1007 | run (message) { |
1008 | if (message.data === 'getChannel') { |
1009 | const ports = this.kernel.ports.createChannel() |
1010 | this.kernel.ports.bind('channel', ports[0]) |
1011 | this.kernel.send(message.fromPort, this.kernel.createMessage({ |
1012 | data: 'bindPort', |
1013 | ports: [ports[1]] |
1014 | })) |
1015 | } else if (message.data === 'bindPort') { |
1016 | this.kernel.ports.bind('channel', message.ports[0]) |
1017 | } |
1018 | } |
1019 | } |
1020 | |
1021 | const hypervisor = new Hypervisor(node.dag) |
1022 | |
1023 | hypervisor.registerContainer('root', Root) |
1024 | hypervisor.registerContainer('sub', Sub) |
1025 | |
1026 | const root = await hypervisor.createInstance('root') |
1027 | |
1028 | const [portRef1, portRef2] = root.ports.createChannel() |
1029 | root.ports.bind('first', portRef1) |
1030 | root.createInstance('root', root.createMessage({ |
1031 | ports: [portRef2] |
1032 | })) |
1033 | |
1034 | root.send(portRef1, root.createMessage()) |
1035 | |
1036 | const sr = await hypervisor.createStateRoot() |
1037 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
1038 | |
1039 | t.end() |
1040 | }) |
1041 | |
1042 | tape('response ports', async t => { |
1043 | t.plan(2) |
1044 | let runs = 0 |
1045 | const returnValue = 'this is a test' |
1046 | |
1047 | class testVMContainer extends BaseContainer { |
1048 | run (m) { |
1049 | runs++ |
1050 | if (runs === 1) { |
1051 | return returnValue |
1052 | } else { |
1053 | t.equals(m.data, returnValue, 'should have correct return value') |
1054 | } |
1055 | } |
1056 | } |
1057 | |
1058 | const hypervisor = new Hypervisor(node.dag) |
1059 | |
1060 | hypervisor.registerContainer('test', testVMContainer) |
1061 | |
1062 | const rootContainer = await hypervisor.createInstance('test') |
1063 | |
1064 | const [portRef1, portRef2] = rootContainer.ports.createChannel() |
1065 | const initMessage = rootContainer.createMessage({ |
1066 | ports: [portRef2] |
1067 | }) |
1068 | |
1069 | rootContainer.createInstance('test', initMessage) |
1070 | |
1071 | rootContainer.ports.bind('first', portRef1) |
1072 | const message = rootContainer.createMessage() |
1073 | const rPort = rootContainer.getResponsePort(message) |
1074 | const rPort2 = rootContainer.getResponsePort(message) |
1075 | |
1076 | t.equals(rPort2, rPort) |
1077 | |
1078 | rootContainer.send(portRef1, message) |
1079 | rootContainer.ports.bind('response', rPort) |
1080 | }) |
1081 | }) |
1082 |
Built with git-ssb-web