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