git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 6496226a003a3eb1845cd6d43c4cdde5fca7b665

Files: 6496226a003a3eb1845cd6d43c4cdde5fca7b665 / tests / index.js

20388 bytesRaw
1const tape = require('tape')
2const IPFS = require('ipfs')
3const Hypervisor = require('../')
4
5const node = new IPFS({
6 start: false
7})
8
9class BaseContainer {
10 constructor (kernel) {
11 this.kernel = kernel
12 }
13
14 static createState (code) {
15 return {
16 nonce: [0],
17 ports: {}
18 }
19 }
20}
21
22node.on('ready', () => {
23 tape('basic', async t => {
24 t.plan(2)
25 let message
26 const expectedState = {
27 '/': 'zdpuAntkdU7yBJojcBT5Q9wBhrK56NmLnwpHPKaEGMFnAXpv7'
28 }
29
30 class testVMContainer extends BaseContainer {
31 run (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 const port = rootContainer.ports.create('test')
41 message = rootContainer.createMessage()
42 rootContainer.ports.bind(port, 'first')
43
44 await rootContainer.send(port, message)
45
46 const stateRoot = await hypervisor.createStateRoot(rootContainer, Infinity)
47 t.deepEquals(stateRoot, expectedState, 'expected root!')
48 })
49
50 tape('one child contract', async t => {
51 t.plan(4)
52 let message
53 const expectedState = {
54 '/': 'zdpuAofSzrBqwYs6z1r28fMeb8z5oSKF6CcWA6m22RqazgoTB'
55 }
56 let hasResolved = false
57
58 class testVMContainer2 extends BaseContainer {
59 run (m) {
60 t.true(m === message, 'should recive a message 2')
61 return new Promise((resolve, reject) => {
62 setTimeout(() => {
63 this.kernel.incrementTicks(1)
64 hasResolved = true
65 resolve()
66 }, 200)
67 })
68 }
69 }
70
71 class testVMContainer extends BaseContainer {
72 async run (m) {
73 const port = this.kernel.ports.create('test2')
74 this.kernel.ports.bind(port, 'child')
75 await this.kernel.send(port, m)
76 this.kernel.incrementTicks(1)
77 }
78 }
79
80 const hypervisor = new Hypervisor(node.dag)
81 hypervisor.registerContainer('test', testVMContainer)
82 hypervisor.registerContainer('test2', testVMContainer2)
83
84 let root = await hypervisor.createInstance('test')
85 let port = root.ports.create('test')
86
87 root.ports.bind(port, 'first')
88 message = root.createMessage()
89
90 await root.send(port, message)
91 const stateRoot = await hypervisor.createStateRoot(root, Infinity)
92 t.true(hasResolved, 'should resolve before generating the state root')
93 t.deepEquals(stateRoot, expectedState, 'expected state')
94
95 // test reviving the state
96 class testVMContainer3 extends BaseContainer {
97 async run (m) {
98 const port = this.kernel.ports.get('child')
99 await this.kernel.send(port, m)
100 this.kernel.incrementTicks(1)
101 }
102 }
103
104 hypervisor.registerContainer('test', testVMContainer3)
105 root = await hypervisor.createInstance('test', stateRoot)
106 port = root.ports.get('first')
107
108 root.send(port, message)
109 })
110
111 tape('ping pong', async t => {
112 class Ping extends BaseContainer {
113 async run (m) {
114 let port = this.kernel.ports.get('child')
115 if (!port) {
116 port = this.kernel.ports.create('pong')
117 this.kernel.ports.bind(port, 'child')
118 }
119
120 if (this.kernel.ticks < 100) {
121 this.kernel.incrementTicks(1)
122 return this.kernel.send(port, this.kernel.createMessage())
123 }
124 }
125 }
126
127 class Pong extends BaseContainer {
128 run (m) {
129 const port = m.fromPort
130 this.kernel.incrementTicks(2)
131 return this.kernel.send(port, this.kernel.createMessage())
132 }
133 }
134
135 const hypervisor = new Hypervisor(node.dag)
136
137 hypervisor.registerContainer('ping', Ping)
138 hypervisor.registerContainer('pong', Pong)
139 const root = await hypervisor.createInstance('pong')
140 const port = root.ports.create('ping')
141 root.ports.bind(port, 'child')
142
143 await root.send(port, root.createMessage())
144 await hypervisor.createStateRoot(root, Infinity)
145
146 t.end()
147 })
148
149 tape('queing multiple messages', async t => {
150 t.plan(2)
151 let runs = 0
152
153 class Root extends BaseContainer {
154 async run (m) {
155 const one = this.kernel.ports.create('child')
156 const two = this.kernel.ports.create('child')
157 const three = this.kernel.ports.create('child')
158
159 this.kernel.ports.bind(one, 'one')
160 this.kernel.ports.bind(two, 'two')
161 this.kernel.ports.bind(three, 'three')
162
163 await Promise.all([
164 this.kernel.send(one, this.kernel.createMessage()),
165 this.kernel.send(two, this.kernel.createMessage()),
166 this.kernel.send(three, this.kernel.createMessage())
167 ])
168
169 return new Promise((resolve, reject) => {
170 setTimeout(() => {
171 this.kernel.incrementTicks(6)
172 resolve()
173 }, 200)
174 })
175 }
176 }
177
178 class Child extends BaseContainer {
179 run (m) {
180 runs++
181 this.kernel.incrementTicks(2)
182 }
183 }
184
185 const hypervisor = new Hypervisor(node.dag)
186
187 hypervisor.registerContainer('root', Root)
188 hypervisor.registerContainer('child', Child)
189
190 const root = await hypervisor.createInstance('root')
191 const port = root.ports.create('root')
192 root.ports.bind(port, 'first')
193
194 await root.send(port, root.createMessage())
195 await root.wait(Infinity)
196
197 t.equals(runs, 3, 'the number of run should be 3')
198 const nonce = await hypervisor.graph.get(root.state, 'ports/first/link/nonce/0')
199 t.equals(nonce, 3, 'should have the correct nonce')
200 })
201
202 tape('traps', async t => {
203 t.plan(1)
204 class Root extends BaseContainer {
205 async run (m) {
206 const one = this.kernel.ports.create('child')
207 const two = this.kernel.ports.create('child')
208 const three = this.kernel.ports.create('child')
209
210 this.kernel.ports.bind(one, 'one')
211 this.kernel.ports.bind(two, 'two')
212 this.kernel.ports.bind(three, 'three')
213
214 throw new Error('it is a trap!!!')
215 }
216 }
217
218 const hypervisor = new Hypervisor(node.dag)
219
220 hypervisor.registerContainer('root', Root)
221 const root = await hypervisor.createInstance('root')
222 await root.run()
223
224 t.deepEquals(root.state, {
225 '/': {
226 nonce: [0],
227 ports: {}
228 }
229 }, 'should revert the state')
230 })
231
232 tape('invalid port referances', async t => {
233 t.plan(2)
234 class Root extends BaseContainer {
235 async run (m) {
236 const port = this.kernel.ports.create('root')
237 this.kernel.ports.bind(port, 'three')
238 this.kernel.ports.unbind('three')
239 try {
240 await this.kernel.send(port, this.kernel.createMessage())
241 } catch (e) {
242 t.pass()
243 }
244 }
245 }
246
247 const hypervisor = new Hypervisor(node.dag)
248
249 hypervisor.registerContainer('root', Root)
250 const root = await hypervisor.createInstance('root')
251 await root.run()
252
253 t.deepEquals(root.state, {
254 '/': {
255 nonce: [1],
256 ports: {}
257 }
258 })
259 })
260
261 tape('message should arrive in the correct oder if sent in order', async t => {
262 t.plan(2)
263
264 class Root extends BaseContainer {
265 async run (m) {
266 if (!this.runs) {
267 this.runs = 1
268 const one = this.kernel.ports.create('first')
269 const two = this.kernel.ports.create('second')
270
271 this.kernel.ports.bind(one, 'one')
272 this.kernel.ports.bind(two, 'two')
273
274 await Promise.all([
275 this.kernel.send(one, this.kernel.createMessage()),
276 this.kernel.send(two, this.kernel.createMessage())
277 ])
278
279 this.kernel.incrementTicks(6)
280 } else if (this.runs === 1) {
281 this.runs++
282 t.equals(m.data, 'first', 'should recive the first message')
283 } else if (this.runs === 2) {
284 t.equals(m.data, 'second', 'should recived the second message')
285 }
286 }
287 }
288
289 class First extends BaseContainer {
290 async run (m) {
291 this.kernel.incrementTicks(1)
292 await this.kernel.send(m.fromPort, this.kernel.createMessage({data: 'first'}))
293 }
294 }
295
296 class Second extends BaseContainer {
297 async run (m) {
298 this.kernel.incrementTicks(2)
299 await this.kernel.send(m.fromPort, this.kernel.createMessage({data: 'second'}))
300 }
301 }
302
303 const hypervisor = new Hypervisor(node.dag)
304
305 hypervisor.registerContainer('root', Root)
306 hypervisor.registerContainer('first', First)
307 hypervisor.registerContainer('second', Second)
308
309 const root = await hypervisor.createInstance('root')
310 const port = root.ports.create('root')
311 root.ports.bind(port, 'first')
312
313 root.send(port, root.createMessage())
314 })
315
316 tape('message should arrive in the correct order, even if sent out of order', async t => {
317 t.plan(2)
318
319 class Root extends BaseContainer {
320 run (m) {
321 if (!this.runs) {
322 this.runs = 1
323 const one = this.kernel.ports.create('first')
324 const two = this.kernel.ports.create('second')
325
326 this.kernel.ports.bind(one, 'one')
327 this.kernel.ports.bind(two, 'two')
328
329 return Promise.all([
330 this.kernel.send(one, this.kernel.createMessage()),
331 this.kernel.send(two, this.kernel.createMessage())
332 ])
333 } else if (this.runs === 1) {
334 this.runs++
335 t.equals(m.data, 'second', 'should recive the first message')
336 } else if (this.runs === 2) {
337 t.equals(m.data, 'first', 'should recived the second message')
338 }
339 }
340 }
341
342 class First extends BaseContainer {
343 run (m) {
344 this.kernel.incrementTicks(2)
345 return this.kernel.send(m.fromPort, this.kernel.createMessage({data: 'first'}))
346 }
347 }
348
349 class Second extends BaseContainer {
350 run (m) {
351 this.kernel.incrementTicks(1)
352 this.kernel.send(m.fromPort, this.kernel.createMessage({data: 'second'}))
353 }
354 }
355
356 const hypervisor = new Hypervisor(node.dag)
357
358 hypervisor.registerContainer('root', Root)
359 hypervisor.registerContainer('first', First)
360 hypervisor.registerContainer('second', Second)
361
362 const root = await hypervisor.createInstance('root')
363 const port = root.ports.create('root')
364 root.ports.bind(port, 'first')
365
366 root.send(port, root.createMessage())
367 })
368
369 tape('message should arrive in the correct order, even in a tie of ticks', async t => {
370 t.plan(2)
371
372 class Root extends BaseContainer {
373 async run (m) {
374 if (!this.runs) {
375 this.runs = 1
376 const one = this.kernel.ports.create('first')
377 const two = this.kernel.ports.create('second')
378
379 this.kernel.ports.bind(one, 'one')
380 this.kernel.ports.bind(two, 'two')
381
382 await Promise.all([
383 this.kernel.send(one, this.kernel.createMessage()),
384 this.kernel.send(two, this.kernel.createMessage())
385 ])
386
387 this.kernel.incrementTicks(6)
388 } else if (this.runs === 1) {
389 this.runs++
390 t.equals(m.data, 'first', 'should recived the second message')
391 } else if (this.runs === 2) {
392 t.equals(m.data, 'second', 'should recive the first message')
393 }
394 }
395 }
396
397 class First extends BaseContainer {
398 run (m) {
399 this.kernel.incrementTicks(2)
400 return this.kernel.send(m.fromPort, this.kernel.createMessage({
401 data: 'first'
402 }))
403 }
404 }
405
406 class Second extends BaseContainer {
407 run (m) {
408 this.kernel.incrementTicks(2)
409 return this.kernel.send(m.fromPort, this.kernel.createMessage({
410 data: 'second'
411 }))
412 }
413 }
414
415 const hypervisor = new Hypervisor(node.dag)
416
417 hypervisor.registerContainer('root', Root)
418 hypervisor.registerContainer('first', First)
419 hypervisor.registerContainer('second', Second)
420
421 const root = await hypervisor.createInstance('root')
422 const port = await root.ports.create('root')
423 root.ports.bind(port, 'first')
424 root.send(port, root.createMessage())
425 })
426
427 tape('message should arrive in the correct order, even in a tie of ticks', async t => {
428 t.plan(2)
429
430 class Root extends BaseContainer {
431 run (m) {
432 if (!this.runs) {
433 this.runs = 1
434 const two = this.kernel.ports.create('second')
435 const one = this.kernel.ports.create('first')
436
437 this.kernel.ports.bind(two, 'two')
438 this.kernel.ports.bind(one, 'one')
439
440 return Promise.all([
441 this.kernel.send(two, this.kernel.createMessage()),
442 this.kernel.send(one, this.kernel.createMessage())
443 ])
444 } else if (this.runs === 1) {
445 this.runs++
446 t.equals(m.data, 'second', 'should recive the first message')
447 } else if (this.runs === 2) {
448 t.equals(m.data, 'first', 'should recived the second message')
449 }
450 }
451 }
452
453 class First extends BaseContainer {
454 run (m) {
455 this.kernel.incrementTicks(2)
456 return this.kernel.send(m.fromPort, this.kernel.createMessage({
457 data: 'first'
458 }))
459 }
460 }
461
462 class Second extends BaseContainer {
463 run (m) {
464 this.kernel.incrementTicks(2)
465 return this.kernel.send(m.fromPort, this.kernel.createMessage({
466 data: 'second'
467 }))
468 }
469 }
470
471 const hypervisor = new Hypervisor(node.dag)
472
473 hypervisor.registerContainer('root', Root)
474 hypervisor.registerContainer('first', First)
475 hypervisor.registerContainer('second', Second)
476
477 const root = await hypervisor.createInstance('root')
478
479 const port = root.ports.create('root')
480 root.ports.bind(port, 'first')
481
482 root.send(port, root.createMessage())
483 })
484
485 tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => {
486 t.plan(2)
487
488 class Root extends BaseContainer {
489 run (m) {
490 if (!this.runs) {
491 this.runs = 1
492 const one = this.kernel.ports.create('first')
493 const two = this.kernel.ports.create('second')
494
495 this.kernel.ports.bind(one, 'one')
496 this.kernel.ports.bind(two, 'two')
497
498 return Promise.all([
499 this.kernel.send(two, this.kernel.createMessage()),
500 this.kernel.send(one, this.kernel.createMessage())
501 ])
502 } else if (this.runs === 1) {
503 this.runs++
504 t.equals(m.data, 'first', 'should recive the first message')
505 } else if (this.runs === 2) {
506 t.equals(m.data, 'second', 'should recived the second message')
507 }
508 }
509 }
510
511 class First extends BaseContainer {
512 run (m) {
513 this.kernel.incrementTicks(2)
514 return this.kernel.send(m.fromPort, this.kernel.createMessage({
515 resources: {
516 priority: 100
517 },
518 data: 'first'
519 }))
520 }
521 }
522
523 class Second extends BaseContainer {
524 run (m) {
525 this.kernel.incrementTicks(2)
526 return this.kernel.send(m.fromPort, this.kernel.createMessage({
527 data: 'second'
528 }))
529 }
530 }
531
532 const hypervisor = new Hypervisor(node.dag)
533
534 hypervisor.registerContainer('root', Root)
535 hypervisor.registerContainer('first', First)
536 hypervisor.registerContainer('second', Second)
537
538 const root = await hypervisor.createInstance('root')
539 const port = root.ports.create('root')
540 root.ports.bind(port, 'first')
541 root.send(port, root.createMessage())
542 })
543
544 tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => {
545 t.plan(2)
546
547 class Root extends BaseContainer {
548 run (m) {
549 if (!this.runs) {
550 this.runs = 1
551
552 const one = this.kernel.ports.create('first')
553 const two = this.kernel.ports.create('second')
554
555 this.kernel.ports.bind(one, 'one')
556 this.kernel.ports.bind(two, 'two')
557
558 return Promise.all([
559 this.kernel.send(two, this.kernel.createMessage()),
560 this.kernel.send(one, this.kernel.createMessage())
561 ])
562 } else if (this.runs === 1) {
563 this.runs++
564 t.equals(m.data, 'second', 'should recive the first message')
565 } else if (this.runs === 2) {
566 t.equals(m.data, 'first', 'should recived the second message')
567 }
568 }
569 }
570
571 class First extends BaseContainer {
572 run (m) {
573 this.kernel.incrementTicks(2)
574 return this.kernel.send(m.fromPort, this.kernel.createMessage({
575 data: 'first'
576 }))
577 }
578 }
579
580 class Second extends BaseContainer {
581 run (m) {
582 this.kernel.incrementTicks(2)
583 return this.kernel.send(m.fromPort, this.kernel.createMessage({
584 resources: {
585 priority: 100
586 },
587 data: 'second'
588 }))
589 }
590 }
591
592 const hypervisor = new Hypervisor(node.dag)
593
594 hypervisor.registerContainer('root', Root)
595 hypervisor.registerContainer('first', First)
596 hypervisor.registerContainer('second', Second)
597
598 const root = await hypervisor.createInstance('root')
599 const port = root.ports.create('root')
600 root.ports.bind(port, 'first')
601 root.send(port, root.createMessage())
602 })
603
604 tape('should order parent messages correctly', async t => {
605 t.plan(1)
606 class Middle extends BaseContainer {
607 run (m) {
608 if (!this.runs) {
609 this.runs = 1
610 this.kernel.incrementTicks(1)
611
612 const leaf = this.kernel.ports.create('leaf')
613 this.kernel.ports.bind(leaf, 'leaf')
614
615 return this.kernel.send(leaf, this.kernel.createMessage())
616 } else {
617 ++this.runs
618 if (this.runs === 3) {
619 t.equals(m.data, 'first')
620 }
621 }
622 }
623 }
624
625 class Leaf extends BaseContainer {
626 run (m) {
627 this.kernel.incrementTicks(2)
628 return this.kernel.send(m.fromPort, this.kernel.createMessage({
629 data: 'first'
630 }))
631 }
632 }
633
634 const hypervisor = new Hypervisor(node.dag)
635
636 hypervisor.registerContainer('root', BaseContainer)
637 hypervisor.registerContainer('middle', Middle)
638 hypervisor.registerContainer('leaf', Leaf)
639
640 const root = await hypervisor.createInstance('root')
641 root.incrementTicks(2)
642
643 const port = root.ports.create('middle')
644 root.ports.bind(port, 'first')
645
646 await root.send(port, root.createMessage())
647 root.send(port, root.createMessage())
648 })
649
650 tape('get container instance by path', async t => {
651 t.plan(1)
652 const hypervisor = new Hypervisor(node.dag)
653 hypervisor.registerContainer('base', BaseContainer)
654
655 const root = await hypervisor.createInstance('base')
656 let port = root.ports.create('base')
657 root.ports.bind(port, 'first')
658
659 const first = await root.getInstance(port)
660 port = first.ports.create('base')
661 first.ports.bind(port, 'second')
662
663 const second = await first.getInstance(port)
664 port = second.ports.create('base')
665 second.ports.bind(port, 'third')
666
667 const third = await second.getInstance(port)
668 const foundThird = await hypervisor.getInstanceByPath(root, 'first/second/third')
669 t.equals(third, foundThird, 'should find by path')
670 })
671
672 tape('copy ports', async t => {
673 t.plan(1)
674 const hypervisor = new Hypervisor(node.dag)
675 hypervisor.registerContainer('base', BaseContainer)
676
677 const root = await hypervisor.createInstance('base')
678 let port = root.ports.create('base')
679 let port2 = root.ports.copy(port)
680
681 t.equals(port2.type, port.type, 'should copy port type')
682 })
683
684 tape('checking ports', async t => {
685 t.plan(4)
686 const hypervisor = new Hypervisor(node.dag)
687 hypervisor.registerContainer('base', BaseContainer)
688
689 const root = await hypervisor.createInstance('base')
690 let port = root.ports.create('base')
691 root.ports.bind(port, 'test')
692
693 t.equals(root.ports.getBoundName(port), 'test', 'should get the ports name')
694
695 try {
696 root.createMessage({
697 ports: [port]
698 })
699 } catch (e) {
700 t.pass('should thow if sending a port that is bound')
701 }
702
703 try {
704 root.ports.bind(port, 'test')
705 } catch (e) {
706 t.pass('should thow if binding an already bound port')
707 }
708
709 root.ports.unbind('test')
710 const message = root.createMessage({ports: [port]})
711 t.equals(message.ports[0], port, 'should create a message if the port is unbound')
712 })
713})
714

Built with git-ssb-web