git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 600f990b0583a4766c0311209cbe69cad38d2459

Files: 600f990b0583a4766c0311209cbe69cad38d2459 / tests / index.js

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

Built with git-ssb-web