Files: b17f430cb428dc0322dc3915948f9c7802107eda / tests / index.js
35404 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 | |
441 | const message1 = this.kernel.createMessage({ |
442 | ports: [portRef2] |
443 | }) |
444 | const message2 = this.kernel.createMessage({ |
445 | ports: [portRef4] |
446 | }) |
447 | |
448 | this.kernel.createInstance(First.typeId, message1) |
449 | this.kernel.createInstance(Second.typeId, message2) |
450 | |
451 | this.kernel.send(portRef1, this.kernel.createMessage()) |
452 | this.kernel.send(portRef3, this.kernel.createMessage()) |
453 | |
454 | this.kernel.incrementTicks(6) |
455 | |
456 | return Promise.all([ |
457 | this.kernel.ports.bind('one', portRef1), |
458 | this.kernel.ports.bind('two', portRef3) |
459 | ]) |
460 | } else if (runs === 1) { |
461 | runs++ |
462 | t.equals(m.data, 'first', 'should recive the first message') |
463 | } else if (runs === 2) { |
464 | t.equals(m.data, 'second', 'should recived the second message') |
465 | } |
466 | } |
467 | static get typeId () { |
468 | return 299 |
469 | } |
470 | } |
471 | |
472 | class First extends BaseContainer { |
473 | onMessage (m) { |
474 | this.kernel.incrementTicks(1) |
475 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
476 | data: 'first' |
477 | })) |
478 | } |
479 | static get typeId () { |
480 | return 2 |
481 | } |
482 | } |
483 | |
484 | class Second extends BaseContainer { |
485 | onMessage (m) { |
486 | this.kernel.incrementTicks(2) |
487 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
488 | data: 'second' |
489 | })) |
490 | } |
491 | } |
492 | |
493 | const hypervisor = new Hypervisor(node.dag) |
494 | |
495 | hypervisor.registerContainer(Root) |
496 | hypervisor.registerContainer(First) |
497 | hypervisor.registerContainer(Second) |
498 | |
499 | const root = await hypervisor.createInstance(Root.typeId) |
500 | const [portRef1, portRef2] = root.ports.createChannel() |
501 | root.createInstance(Root.typeId, root.createMessage({ |
502 | ports: [portRef2] |
503 | })) |
504 | |
505 | await root.ports.bind('first', portRef1) |
506 | const message = root.createMessage() |
507 | root.send(portRef1, message) |
508 | }) |
509 | |
510 | tape('saturation', async t => { |
511 | t.plan(2) |
512 | let runs = 0 |
513 | |
514 | class Root extends BaseContainer { |
515 | onMessage (m) { |
516 | if (!runs) { |
517 | runs++ |
518 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
519 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
520 | |
521 | const message1 = this.kernel.createMessage({ |
522 | ports: [portRef2] |
523 | }) |
524 | const message2 = this.kernel.createMessage({ |
525 | ports: [portRef4] |
526 | }) |
527 | |
528 | this.kernel.createInstance(First.typeId, message1) |
529 | this.kernel.createInstance(Second.typeId, message2) |
530 | |
531 | this.kernel.send(portRef1, this.kernel.createMessage()) |
532 | this.kernel.send(portRef3, this.kernel.createMessage()) |
533 | |
534 | this.kernel.incrementTicks(6) |
535 | return Promise.all([ |
536 | this.kernel.ports.bind('one', portRef1), |
537 | this.kernel.ports.bind('two', portRef3) |
538 | ]) |
539 | } else if (runs === 1) { |
540 | runs++ |
541 | t.equals(m.data, 'first', 'should recive the first message') |
542 | } else if (runs === 2) { |
543 | runs++ |
544 | t.equals(m.data, 'second', 'should recived the second message') |
545 | } |
546 | } |
547 | static get typeId () { |
548 | return 299 |
549 | } |
550 | } |
551 | |
552 | class First extends BaseContainer { |
553 | onMessage (m) { |
554 | this.kernel.incrementTicks(2) |
555 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
556 | data: 'first' |
557 | })) |
558 | } |
559 | static get typeId () { |
560 | return 29 |
561 | } |
562 | } |
563 | |
564 | class Second extends BaseContainer { |
565 | onMessage (m) { |
566 | this.kernel.incrementTicks(3) |
567 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
568 | data: 'second' |
569 | })) |
570 | } |
571 | static get typeId () { |
572 | return 2 |
573 | } |
574 | } |
575 | |
576 | class Waiter extends BaseContainer { |
577 | onCreation () { |
578 | return new Promise((resolve, reject) => { |
579 | setTimeout(() => { |
580 | resolve() |
581 | }, 200) |
582 | }) |
583 | } |
584 | } |
585 | |
586 | const hypervisor = new Hypervisor(node.dag) |
587 | |
588 | hypervisor.registerContainer(Root) |
589 | hypervisor.registerContainer(First) |
590 | hypervisor.registerContainer(Second) |
591 | hypervisor.registerContainer(Waiter) |
592 | |
593 | const root = await hypervisor.createInstance(Root.typeId) |
594 | const [portRef1, portRef2] = root.ports.createChannel() |
595 | |
596 | const message = root.createMessage() |
597 | root.send(portRef1, message) |
598 | await root.ports.bind('first', portRef1) |
599 | root.createInstance(Root.typeId, root.createMessage({ |
600 | ports: [portRef2] |
601 | })) |
602 | |
603 | const [portRef3, portRef4] = root.ports.createChannel() |
604 | await root.ports.bind('sencond', portRef3) |
605 | root.createInstance(Waiter.typeId, root.createMessage({ |
606 | ports: [portRef4] |
607 | })) |
608 | |
609 | root.incrementTicks(100) |
610 | root.send(portRef1, root.createMessage({data: 'testss'})) |
611 | hypervisor.scheduler.done(root.id) |
612 | }) |
613 | |
614 | tape('message should arrive in the correct order, even in a tie of ticks', async t => { |
615 | t.plan(2) |
616 | |
617 | let runs = 0 |
618 | |
619 | class Root extends BaseContainer { |
620 | onMessage (m) { |
621 | if (!runs) { |
622 | runs++ |
623 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
624 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
625 | |
626 | const message1 = this.kernel.createMessage({ |
627 | ports: [portRef2] |
628 | }) |
629 | const message2 = this.kernel.createMessage({ |
630 | ports: [portRef4] |
631 | }) |
632 | |
633 | this.kernel.createInstance(First.typeId, message1) |
634 | this.kernel.createInstance(Second.typeId, message2) |
635 | |
636 | this.kernel.send(portRef1, this.kernel.createMessage()) |
637 | this.kernel.send(portRef3, this.kernel.createMessage()) |
638 | |
639 | this.kernel.incrementTicks(6) |
640 | return Promise.all([ |
641 | this.kernel.ports.bind('two', portRef3), |
642 | this.kernel.ports.bind('one', portRef1) |
643 | ]) |
644 | } else if (runs === 1) { |
645 | runs++ |
646 | t.equals(m.data, 'second', 'should recived the second message') |
647 | } else if (runs === 2) { |
648 | t.equals(m.data, 'first', 'should recive the first message') |
649 | } |
650 | } |
651 | static get typeId () { |
652 | return 299 |
653 | } |
654 | } |
655 | |
656 | class First extends BaseContainer { |
657 | onMessage (m) { |
658 | this.kernel.incrementTicks(2) |
659 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
660 | data: 'first' |
661 | })) |
662 | } |
663 | static get typeId () { |
664 | return 29 |
665 | } |
666 | } |
667 | |
668 | class Second extends BaseContainer { |
669 | onMessage (m) { |
670 | this.kernel.incrementTicks(2) |
671 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
672 | data: 'second' |
673 | })) |
674 | } |
675 | static get typeId () { |
676 | return 2 |
677 | } |
678 | } |
679 | |
680 | const hypervisor = new Hypervisor(node.dag) |
681 | |
682 | hypervisor.registerContainer(Root) |
683 | hypervisor.registerContainer(First) |
684 | hypervisor.registerContainer(Second) |
685 | |
686 | const root = await hypervisor.createInstance(Root.typeId) |
687 | const [portRef1, portRef2] = root.ports.createChannel() |
688 | const message = root.createMessage() |
689 | |
690 | root.send(portRef1, message) |
691 | await root.ports.bind('first', portRef1) |
692 | root.createInstance(Root.typeId, root.createMessage({ |
693 | ports: [portRef2] |
694 | })) |
695 | }) |
696 | |
697 | tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => { |
698 | t.plan(2) |
699 | |
700 | let runs = 0 |
701 | |
702 | class Root extends BaseContainer { |
703 | async onMessage (m) { |
704 | if (!runs) { |
705 | runs++ |
706 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
707 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
708 | |
709 | await this.kernel.ports.bind('one', portRef1) |
710 | await this.kernel.ports.bind('two', portRef3) |
711 | |
712 | const message1 = this.kernel.createMessage({ |
713 | ports: [portRef2] |
714 | }) |
715 | const message2 = this.kernel.createMessage({ |
716 | ports: [portRef4] |
717 | }) |
718 | |
719 | this.kernel.createInstance(First.typeId, message1) |
720 | this.kernel.createInstance(Second.typeId, message2) |
721 | |
722 | this.kernel.send(portRef1, this.kernel.createMessage()) |
723 | this.kernel.send(portRef3, this.kernel.createMessage()) |
724 | |
725 | this.kernel.incrementTicks(6) |
726 | } else if (runs === 1) { |
727 | runs++ |
728 | t.equals(m.data, 'first', 'should recive the first message') |
729 | } else if (runs === 2) { |
730 | t.equals(m.data, 'second', 'should recived the second message') |
731 | } |
732 | } |
733 | static get typeId () { |
734 | return 299 |
735 | } |
736 | } |
737 | |
738 | class First extends BaseContainer { |
739 | onMessage (m) { |
740 | this.kernel.incrementTicks(2) |
741 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
742 | data: 'first' |
743 | })) |
744 | } |
745 | static get typeId () { |
746 | return 29 |
747 | } |
748 | } |
749 | |
750 | class Second extends BaseContainer { |
751 | onMessage (m) { |
752 | this.kernel.incrementTicks(2) |
753 | this.kernel.send(m.fromPort, this.kernel.createMessage({ |
754 | data: 'second' |
755 | })) |
756 | } |
757 | } |
758 | |
759 | const hypervisor = new Hypervisor(node.dag) |
760 | |
761 | hypervisor.registerContainer(Root) |
762 | hypervisor.registerContainer(First) |
763 | hypervisor.registerContainer(Second) |
764 | |
765 | const root = await hypervisor.createInstance(Root.typeId) |
766 | const [portRef1, portRef2] = root.ports.createChannel() |
767 | const message = root.createMessage() |
768 | |
769 | root.send(portRef1, message) |
770 | await root.ports.bind('first', portRef1) |
771 | root.createInstance(Root.typeId, root.createMessage({ |
772 | ports: [portRef2] |
773 | })) |
774 | }) |
775 | |
776 | tape('send to the same container at the same time', async t => { |
777 | t.plan(2) |
778 | |
779 | let runs = 0 |
780 | let instance |
781 | |
782 | class Root extends BaseContainer { |
783 | onMessage (m) { |
784 | let one = this.kernel.ports.get('one') |
785 | if (!one) { |
786 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
787 | const message1 = this.kernel.createMessage({ |
788 | ports: [portRef2] |
789 | }) |
790 | this.kernel.createInstance(First.typeId, message1) |
791 | return this.kernel.ports.bind('one', portRef1) |
792 | } else { |
793 | this.kernel.send(one, this.kernel.createMessage()) |
794 | this.kernel.send(one, this.kernel.createMessage()) |
795 | } |
796 | } |
797 | static get typeId () { |
798 | return 299 |
799 | } |
800 | } |
801 | |
802 | class First extends BaseContainer { |
803 | onMessage (m) { |
804 | ++runs |
805 | if (runs === 2) { |
806 | t.equals(instance, this, 'should have same instances') |
807 | } else { |
808 | instance = this |
809 | } |
810 | } |
811 | } |
812 | |
813 | const hypervisor = new Hypervisor(node.dag) |
814 | |
815 | hypervisor.registerContainer(Root) |
816 | hypervisor.registerContainer(First) |
817 | |
818 | const root = await hypervisor.createInstance(Root.typeId) |
819 | const [portRef1, portRef2] = root.ports.createChannel() |
820 | await root.ports.bind('first', portRef1) |
821 | root.createInstance(Root.typeId, root.createMessage({ |
822 | ports: [portRef2] |
823 | })) |
824 | |
825 | const message = root.createMessage() |
826 | root.send(portRef1, message) |
827 | await hypervisor.createStateRoot() |
828 | root.send(portRef1, root.createMessage()) |
829 | await hypervisor.createStateRoot() |
830 | t.equals(runs, 2) |
831 | }) |
832 | |
833 | tape('checking ports', async t => { |
834 | t.plan(4) |
835 | const hypervisor = new Hypervisor(node.dag) |
836 | hypervisor.registerContainer(BaseContainer) |
837 | |
838 | const root = await hypervisor.createInstance(BaseContainer.typeId) |
839 | |
840 | const [portRef1, portRef2] = root.ports.createChannel() |
841 | root.createInstance(BaseContainer.typeId, root.createMessage({ |
842 | ports: [portRef2] |
843 | })) |
844 | await root.ports.bind('test', portRef1) |
845 | |
846 | try { |
847 | root.createMessage({ |
848 | ports: [portRef1] |
849 | }) |
850 | } catch (e) { |
851 | t.pass('should thow if sending a port that is bound') |
852 | } |
853 | |
854 | try { |
855 | await root.ports.bind('test', portRef1) |
856 | } catch (e) { |
857 | t.pass('should thow if binding an already bound port') |
858 | } |
859 | |
860 | try { |
861 | const [portRef3] = root.ports.createChannel() |
862 | await root.ports.bind('test', portRef3) |
863 | } catch (e) { |
864 | t.pass('should thow if binding an already bound name') |
865 | } |
866 | |
867 | await root.ports.unbind('test') |
868 | const message = root.createMessage({ |
869 | ports: [portRef1] |
870 | }) |
871 | t.equals(message.ports[0], portRef1, 'should create a message if the port is unbound') |
872 | }) |
873 | |
874 | tape('port deletion', async t => { |
875 | const expectedSr = { |
876 | '/': 'zdpuAopMy53q2uvL2a4fhVEAvwXjSDW28fh8zhQUj598tb5md' |
877 | } |
878 | class Root extends BaseContainer { |
879 | onMessage (m) { |
880 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
881 | const message1 = this.kernel.createMessage({ |
882 | ports: [portRef2] |
883 | }) |
884 | |
885 | this.kernel.createInstance(First.typeId, message1) |
886 | this.kernel.send(portRef1, this.kernel.createMessage()) |
887 | this.kernel.incrementTicks(6) |
888 | return this.kernel.ports.bind('one', portRef1) |
889 | } |
890 | } |
891 | |
892 | class First extends BaseContainer { |
893 | onMessage (m) { |
894 | this.kernel.incrementTicks(2) |
895 | this.kernel.ports.delete('root') |
896 | } |
897 | static get typeId () { |
898 | return 299 |
899 | } |
900 | } |
901 | |
902 | const hypervisor = new Hypervisor(node.dag) |
903 | |
904 | hypervisor.registerContainer(Root) |
905 | hypervisor.registerContainer(First) |
906 | |
907 | const root = await hypervisor.createInstance(Root.typeId) |
908 | const [portRef1, portRef2] = root.ports.createChannel() |
909 | await root.ports.bind('first', portRef1) |
910 | root.createInstance(Root.typeId, root.createMessage({ |
911 | ports: [portRef2] |
912 | })) |
913 | |
914 | const message = root.createMessage() |
915 | root.send(portRef1, message) |
916 | |
917 | const sr = await hypervisor.createStateRoot() |
918 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
919 | await hypervisor.graph.tree(sr, Infinity, true) |
920 | |
921 | t.end() |
922 | }) |
923 | |
924 | tape('clear unbounded ports', async t => { |
925 | const expectedSr = { |
926 | '/': 'zdpuAopMy53q2uvL2a4fhVEAvwXjSDW28fh8zhQUj598tb5md' |
927 | } |
928 | class Root extends BaseContainer { |
929 | onMessage (m) { |
930 | this.kernel.createInstance(Root.typeId) |
931 | } |
932 | } |
933 | |
934 | const hypervisor = new Hypervisor(node.dag) |
935 | |
936 | hypervisor.registerContainer(Root) |
937 | |
938 | const root = await hypervisor.createInstance(Root.typeId) |
939 | const [portRef1, portRef2] = root.ports.createChannel() |
940 | await root.ports.bind('first', portRef1) |
941 | root.createInstance(Root.typeId, root.createMessage({ |
942 | ports: [portRef2] |
943 | })) |
944 | |
945 | const message = root.createMessage() |
946 | root.send(portRef1, message) |
947 | const sr = await hypervisor.createStateRoot() |
948 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
949 | |
950 | t.end() |
951 | }) |
952 | |
953 | tape('should remove subgraphs', async t => { |
954 | const expectedSr = { |
955 | '/': 'zdpuAopMy53q2uvL2a4fhVEAvwXjSDW28fh8zhQUj598tb5md' |
956 | } |
957 | class Root extends BaseContainer { |
958 | onMessage (m) { |
959 | const [, portRef2] = this.kernel.ports.createChannel() |
960 | this.kernel.createInstance(Sub.typeId, this.kernel.createMessage({ |
961 | ports: [portRef2] |
962 | })) |
963 | } |
964 | } |
965 | |
966 | class Sub extends BaseContainer { |
967 | async onInitailize (message) { |
968 | await this.kernel.ports.bind('root', message.ports[0]) |
969 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
970 | await this.kernel.ports.bind('child', portRef1) |
971 | this.kernel.createInstance(Root.typeId, this.kernel.createMessage({ |
972 | ports: [portRef2] |
973 | })) |
974 | } |
975 | static get typeId () { |
976 | return 299 |
977 | } |
978 | } |
979 | |
980 | const hypervisor = new Hypervisor(node.dag) |
981 | |
982 | hypervisor.registerContainer(Root) |
983 | hypervisor.registerContainer(Sub) |
984 | |
985 | const root = await hypervisor.createInstance(Root.typeId) |
986 | const [portRef1, portRef2] = root.ports.createChannel() |
987 | await root.ports.bind('first', portRef1) |
988 | root.createInstance(Root.typeId, root.createMessage({ |
989 | ports: [portRef2] |
990 | })) |
991 | |
992 | root.send(portRef1, root.createMessage()) |
993 | const sr = await hypervisor.createStateRoot() |
994 | |
995 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
996 | t.end() |
997 | }) |
998 | |
999 | tape('should not remove connected nodes', async t => { |
1000 | const expectedSr = { |
1001 | '/': 'zdpuApKrsvsWknDML2Mme9FyZfRnVZ1hTCoKzkooYAWT3dUDV' |
1002 | } |
1003 | class Root extends BaseContainer { |
1004 | async onMessage (m) { |
1005 | if (m.ports.length) { |
1006 | const port = this.kernel.ports.get('test1') |
1007 | this.kernel.send(port, m) |
1008 | return this.kernel.ports.unbind('test1') |
1009 | } else { |
1010 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
1011 | this.kernel.createInstance(Sub.typeId, this.kernel.createMessage({ |
1012 | ports: [portRef2] |
1013 | })) |
1014 | await this.kernel.ports.bind('test1', portRef1) |
1015 | |
1016 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
1017 | this.kernel.createInstance(Sub.typeId, this.kernel.createMessage({ |
1018 | ports: [portRef4] |
1019 | })) |
1020 | await this.kernel.ports.bind('test2', portRef3) |
1021 | this.kernel.send(portRef3, this.kernel.createMessage({ |
1022 | data: 'getChannel' |
1023 | })) |
1024 | } |
1025 | } |
1026 | } |
1027 | |
1028 | class Sub extends BaseContainer { |
1029 | onMessage (message) { |
1030 | if (message.data === 'getChannel') { |
1031 | const ports = this.kernel.ports.createChannel() |
1032 | this.kernel.send(message.fromPort, this.kernel.createMessage({ |
1033 | data: 'bindPort', |
1034 | ports: [ports[1]] |
1035 | })) |
1036 | return this.kernel.ports.bind('channel', ports[0]) |
1037 | } else if (message.data === 'bindPort') { |
1038 | return this.kernel.ports.bind('channel', message.ports[0]) |
1039 | } |
1040 | } |
1041 | static get typeId () { |
1042 | return 299 |
1043 | } |
1044 | } |
1045 | |
1046 | const hypervisor = new Hypervisor(node.dag) |
1047 | |
1048 | hypervisor.registerContainer(Root) |
1049 | hypervisor.registerContainer(Sub) |
1050 | |
1051 | const root = await hypervisor.createInstance(Root.typeId) |
1052 | const [portRef1, portRef2] = root.ports.createChannel() |
1053 | await root.ports.bind('first', portRef1) |
1054 | root.createInstance(Root.typeId, root.createMessage({ |
1055 | ports: [portRef2] |
1056 | })) |
1057 | |
1058 | root.send(portRef1, root.createMessage()) |
1059 | const sr = await hypervisor.createStateRoot() |
1060 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
1061 | // await hypervisor.graph.tree(sr, Infinity) |
1062 | |
1063 | t.end() |
1064 | }) |
1065 | |
1066 | tape('should remove multiple subgraphs', async t => { |
1067 | const expectedSr = { |
1068 | '/': 'zdpuAohccQTxM82d8N6Q82z234nQskeQoJGJu3eAVmxoQwWde' |
1069 | } |
1070 | class Root extends BaseContainer { |
1071 | async onMessage (m) { |
1072 | if (m.ports.length) { |
1073 | const port = this.kernel.ports.get('test1') |
1074 | this.kernel.send(port, m) |
1075 | await this.kernel.ports.unbind('test1') |
1076 | await this.kernel.ports.unbind('test2') |
1077 | } else { |
1078 | const [portRef1, portRef2] = this.kernel.ports.createChannel() |
1079 | this.kernel.createInstance(Sub.typeId, this.kernel.createMessage({ |
1080 | ports: [portRef2] |
1081 | })) |
1082 | await this.kernel.ports.bind('test1', portRef1) |
1083 | |
1084 | const [portRef3, portRef4] = this.kernel.ports.createChannel() |
1085 | this.kernel.createInstance(Sub.typeId, this.kernel.createMessage({ |
1086 | ports: [portRef4] |
1087 | })) |
1088 | await this.kernel.ports.bind('test2', portRef3) |
1089 | this.kernel.send(portRef3, this.kernel.createMessage({ |
1090 | data: 'getChannel' |
1091 | })) |
1092 | } |
1093 | } |
1094 | } |
1095 | |
1096 | class Sub extends BaseContainer { |
1097 | onMessage (message) { |
1098 | if (message.data === 'getChannel') { |
1099 | const ports = this.kernel.ports.createChannel() |
1100 | this.kernel.send(message.fromPort, this.kernel.createMessage({ |
1101 | data: 'bindPort', |
1102 | ports: [ports[1]] |
1103 | })) |
1104 | return this.kernel.ports.bind('channel', ports[0]) |
1105 | } else if (message.data === 'bindPort') { |
1106 | return this.kernel.ports.bind('channel', message.ports[0]) |
1107 | } |
1108 | } |
1109 | static get typeId () { |
1110 | return 299 |
1111 | } |
1112 | } |
1113 | |
1114 | const hypervisor = new Hypervisor(node.dag) |
1115 | |
1116 | hypervisor.registerContainer(Root) |
1117 | hypervisor.registerContainer(Sub) |
1118 | |
1119 | const root = await hypervisor.createInstance(Root.typeId) |
1120 | |
1121 | const [portRef1, portRef2] = root.ports.createChannel() |
1122 | await root.ports.bind('first', portRef1) |
1123 | root.createInstance(Root.typeId, root.createMessage({ |
1124 | ports: [portRef2] |
1125 | })) |
1126 | |
1127 | root.send(portRef1, root.createMessage()) |
1128 | |
1129 | const sr = await hypervisor.createStateRoot() |
1130 | t.deepEquals(sr, expectedSr, 'should produce the corret state root') |
1131 | |
1132 | t.end() |
1133 | }) |
1134 | |
1135 | tape('response ports', async t => { |
1136 | t.plan(2) |
1137 | let runs = 0 |
1138 | const returnValue = 'this is a test' |
1139 | |
1140 | class testVMContainer extends BaseContainer { |
1141 | onMessage (m) { |
1142 | runs++ |
1143 | if (runs === 1) { |
1144 | return returnValue |
1145 | } else { |
1146 | t.equals(m.data, returnValue, 'should have correct return value') |
1147 | } |
1148 | } |
1149 | } |
1150 | |
1151 | const hypervisor = new Hypervisor(node.dag) |
1152 | |
1153 | hypervisor.registerContainer(testVMContainer) |
1154 | |
1155 | const rootContainer = await hypervisor.createInstance(testVMContainer.typeId) |
1156 | |
1157 | const [portRef1, portRef2] = rootContainer.ports.createChannel() |
1158 | const initMessage = rootContainer.createMessage({ |
1159 | ports: [portRef2] |
1160 | }) |
1161 | |
1162 | rootContainer.createInstance(testVMContainer.typeId, initMessage) |
1163 | |
1164 | await rootContainer.ports.bind('first', portRef1) |
1165 | const message = rootContainer.createMessage() |
1166 | const rPort = rootContainer.getResponsePort(message) |
1167 | const rPort2 = rootContainer.getResponsePort(message) |
1168 | |
1169 | t.equals(rPort2, rPort) |
1170 | |
1171 | rootContainer.send(portRef1, message) |
1172 | await rootContainer.ports.bind('response', rPort) |
1173 | }) |
1174 | |
1175 | tape('start up', async t => { |
1176 | t.plan(1) |
1177 | class testVMContainer extends BaseContainer { |
1178 | onMessage () {} |
1179 | onStartup () { |
1180 | t.true(true, 'should start up') |
1181 | } |
1182 | } |
1183 | |
1184 | const hypervisor = new Hypervisor(node.dag) |
1185 | hypervisor.registerContainer(testVMContainer) |
1186 | await hypervisor.createInstance(testVMContainer.typeId) |
1187 | hypervisor.getInstance(hypervisor.ROOT_ID) |
1188 | }) |
1189 | |
1190 | tape('large code size', async t => { |
1191 | t.plan(1) |
1192 | const content = Buffer.from(new ArrayBuffer(1000000)) |
1193 | class testVMContainer extends BaseContainer { |
1194 | onMessage () {} |
1195 | } |
1196 | |
1197 | const hypervisor = new Hypervisor(node.dag) |
1198 | hypervisor.registerContainer(testVMContainer) |
1199 | await hypervisor.createInstance(testVMContainer.typeId, new Message({data: content})) |
1200 | const instance = await hypervisor.getInstance(hypervisor.ROOT_ID) |
1201 | t.equals(content.length, instance.code.length) |
1202 | }) |
1203 | }) |
1204 |
Built with git-ssb-web