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