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