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