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