git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 42bb5a2f36de56726c4bd6ede09c95352d5b545d

Files: 42bb5a2f36de56726c4bd6ede09c95352d5b545d / tests / index.js

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

Built with git-ssb-web