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