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