git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: a378a2df93c85f8e6fe2dbfe58627b085c7bc7d3

Files: a378a2df93c85f8e6fe2dbfe58627b085c7bc7d3 / tests / index.js

18256 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({dag: 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({dag: 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({
143 dag: node.dag
144 })
145
146 hypervisor.registerContainer('ping', Ping)
147 hypervisor.registerContainer('pong', Pong)
148 const root = await hypervisor.createInstance('pong')
149 const port = root.ports.create('ping')
150 root.ports.bind(port, 'child')
151
152 await root.send(port, new Message())
153 await hypervisor.createStateRoot(root, Infinity)
154
155 t.end()
156 })
157
158 tape('queing multiple messages', async t => {
159 t.plan(2)
160 let runs = 0
161
162 class Root extends BaseContainer {
163 async run (m) {
164 const one = this.kernel.ports.create('child')
165 const two = this.kernel.ports.create('child')
166 const three = this.kernel.ports.create('child')
167
168 this.kernel.ports.bind(one, 'one')
169 this.kernel.ports.bind(two, 'two')
170 this.kernel.ports.bind(three, 'three')
171
172 await Promise.all([
173 this.kernel.send(one, new Message()),
174 this.kernel.send(two, new Message()),
175 this.kernel.send(three, new Message())
176 ])
177
178 return new Promise((resolve, reject) => {
179 setTimeout(() => {
180 this.kernel.incrementTicks(6)
181 resolve()
182 }, 200)
183 })
184 }
185 }
186
187 class Child extends BaseContainer {
188 run (m) {
189 runs++
190 this.kernel.incrementTicks(2)
191 }
192 }
193
194 const hypervisor = new Hypervisor({
195 dag: node.dag
196 })
197
198 hypervisor.registerContainer('root', Root)
199 hypervisor.registerContainer('child', Child)
200
201 const root = await hypervisor.createInstance('root')
202 const port = root.ports.create('root')
203 root.ports.bind(port, 'first')
204
205 await root.send(port, new Message())
206 await root.wait(Infinity)
207
208 t.equals(runs, 3, 'the number of run should be 3')
209 const nonce = await hypervisor.graph.get(root.state, 'ports/first/link/nonce/0')
210 t.equals(nonce, 3, 'should have the correct nonce')
211 })
212
213 tape('traps', async t => {
214 t.plan(1)
215 class Root extends BaseContainer {
216 async run (m) {
217 const one = this.kernel.ports.create('child')
218 const two = this.kernel.ports.create('child')
219 const three = this.kernel.ports.create('child')
220
221 this.kernel.ports.bind(one, 'one')
222 this.kernel.ports.bind(two, 'two')
223 this.kernel.ports.bind(three, 'three')
224
225 throw new Error('it is a trap!!!')
226 }
227 }
228
229 const hypervisor = new Hypervisor({
230 dag: node.dag
231 })
232
233 hypervisor.registerContainer('root', Root)
234 const root = await hypervisor.createInstance('root')
235 await root.run()
236
237 t.deepEquals(root.state, {
238 '/': {
239 nonce: [0],
240 ports: {}
241 }
242 }, 'should revert the state')
243 })
244
245 tape('invalid port referances', async t => {
246 t.plan(2)
247 class Root extends BaseContainer {
248 async run (m) {
249 const port = this.kernel.ports.create('root')
250 this.kernel.ports.bind(port, 'three')
251 this.kernel.ports.delete('three')
252 try {
253 await this.kernel.send(port, new Message())
254 } catch (e) {
255 t.pass()
256 }
257 }
258 }
259
260 const hypervisor = new Hypervisor({
261 dag: node.dag
262 })
263
264 hypervisor.registerContainer('root', Root)
265 const root = await hypervisor.createInstance('root')
266 await root.run()
267
268 t.deepEquals(root.state, {
269 '/': {
270 nonce: [1],
271 ports: {}
272 }
273 })
274 })
275
276 tape('message should arrive in the correct oder if sent in order', async t => {
277 t.plan(2)
278
279 class Root extends BaseContainer {
280 async run (m) {
281 if (!this.runs) {
282 this.runs = 1
283 const one = this.kernel.ports.create('first')
284 const two = this.kernel.ports.create('second')
285
286 this.kernel.ports.bind(one, 'one')
287 this.kernel.ports.bind(two, 'two')
288
289 await Promise.all([
290 this.kernel.send(one, new Message()),
291 this.kernel.send(two, new Message())
292 ])
293
294 this.kernel.incrementTicks(6)
295 } else if (this.runs === 1) {
296 this.runs++
297 t.equals(m.data, 'first', 'should recive the first message')
298 } else if (this.runs === 2) {
299 t.equals(m.data, 'second', 'should recived the second message')
300 }
301 }
302 }
303
304 class First extends BaseContainer {
305 async run (m) {
306 this.kernel.incrementTicks(1)
307 await this.kernel.send(m.fromPort, new Message({data: 'first'}))
308 }
309 }
310
311 class Second extends BaseContainer {
312 async run (m) {
313 this.kernel.incrementTicks(2)
314 await this.kernel.send(m.fromPort, new Message({data: 'second'}))
315 }
316 }
317
318 const hypervisor = new Hypervisor({
319 dag: node.dag
320 })
321
322 hypervisor.registerContainer('root', Root)
323 hypervisor.registerContainer('first', First)
324 hypervisor.registerContainer('second', Second)
325
326 const root = await hypervisor.createInstance('root')
327 const port = root.ports.create('root')
328 root.ports.bind(port, 'first')
329
330 root.send(port, new Message())
331 })
332
333 tape('message should arrive in the correct order, even if sent out of order', async t => {
334 t.plan(2)
335
336 class Root extends BaseContainer {
337 run (m) {
338 if (!this.runs) {
339 this.runs = 1
340 const one = this.kernel.ports.create('first')
341 const two = this.kernel.ports.create('second')
342
343 this.kernel.ports.bind(one, 'one')
344 this.kernel.ports.bind(two, 'two')
345
346 return Promise.all([
347 this.kernel.send(one, new Message()),
348 this.kernel.send(two, new Message())
349 ])
350 } else if (this.runs === 1) {
351 this.runs++
352 t.equals(m.data, 'second', 'should recive the first message')
353 } else if (this.runs === 2) {
354 t.equals(m.data, 'first', 'should recived the second message')
355 }
356 }
357 }
358
359 class First extends BaseContainer {
360 run (m) {
361 this.kernel.incrementTicks(2)
362 return this.kernel.send(m.fromPort, new Message({data: 'first'}))
363 }
364 }
365
366 class Second extends BaseContainer {
367 run (m) {
368 this.kernel.incrementTicks(1)
369 this.kernel.send(m.fromPort, new Message({data: 'second'}))
370 }
371 }
372
373 const hypervisor = new Hypervisor({
374 dag: node.dag
375 })
376
377 hypervisor.registerContainer('root', Root)
378 hypervisor.registerContainer('first', First)
379 hypervisor.registerContainer('second', Second)
380
381 const root = await hypervisor.createInstance('root')
382 const port = root.ports.create('root')
383 root.ports.bind(port, 'first')
384
385 root.send(port, new Message())
386 })
387
388 tape('message should arrive in the correct order, even in a tie of ticks', async t => {
389 t.plan(2)
390
391 class Root extends BaseContainer {
392 async run (m) {
393 if (!this.runs) {
394 this.runs = 1
395 const one = this.kernel.ports.create('first')
396 const two = this.kernel.ports.create('second')
397
398 this.kernel.ports.bind(one, 'one')
399 this.kernel.ports.bind(two, 'two')
400
401 await Promise.all([
402 this.kernel.send(one, new Message()),
403 this.kernel.send(two, new Message())
404 ])
405
406 this.kernel.incrementTicks(6)
407 } else if (this.runs === 1) {
408 this.runs++
409 t.equals(m.data, 'first', 'should recived the second message')
410 } else if (this.runs === 2) {
411 t.equals(m.data, 'second', 'should recive the first message')
412 }
413 }
414 }
415
416 class First extends BaseContainer {
417 run (m) {
418 this.kernel.incrementTicks(2)
419 return this.kernel.send(m.fromPort, new Message({
420 data: 'first'
421 }))
422 }
423 }
424
425 class Second extends BaseContainer {
426 run (m) {
427 this.kernel.incrementTicks(2)
428 return this.kernel.send(m.fromPort, new Message({
429 data: 'second'
430 }))
431 }
432 }
433
434 const hypervisor = new Hypervisor({
435 dag: node.dag
436 })
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 port = await root.ports.create('root')
444 root.ports.bind(port, 'first')
445 root.send(port, new Message())
446 })
447
448 tape('message should arrive in the correct order, even in a tie of ticks', async t => {
449 t.plan(2)
450
451 class Root extends BaseContainer {
452 run (m) {
453 if (!this.runs) {
454 this.runs = 1
455 const two = this.kernel.ports.create('second')
456 const one = this.kernel.ports.create('first')
457
458 this.kernel.ports.bind(two, 'two')
459 this.kernel.ports.bind(one, 'one')
460
461 return Promise.all([
462 this.kernel.send(two, new Message()),
463 this.kernel.send(one, new Message())
464 ])
465 } else if (this.runs === 1) {
466 this.runs++
467 t.equals(m.data, 'first', 'should recived the second message')
468 } else if (this.runs === 2) {
469 t.equals(m.data, 'second', 'should recive the first message')
470 }
471 }
472 }
473
474 class First extends BaseContainer {
475 run (m) {
476 this.kernel.incrementTicks(2)
477 return this.kernel.send(m.fromPort, new Message({
478 data: 'first'
479 }))
480 }
481 }
482
483 class Second extends BaseContainer {
484 run (m) {
485 this.kernel.incrementTicks(2)
486 return this.kernel.send(m.fromPort, new Message({
487 data: 'second'
488 }))
489 }
490 }
491
492 const hypervisor = new Hypervisor({
493 dag: node.dag
494 })
495
496 hypervisor.registerContainer('root', Root)
497 hypervisor.registerContainer('first', First)
498 hypervisor.registerContainer('second', Second)
499
500 const root = await hypervisor.createInstance('root')
501
502 const port = root.ports.create('root')
503 root.ports.bind(port, 'first')
504
505 root.send(port, new Message())
506 })
507
508 tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => {
509 t.plan(2)
510
511 class Root extends BaseContainer {
512 run (m) {
513 if (!this.runs) {
514 this.runs = 1
515 const one = this.kernel.ports.create('first')
516 const two = this.kernel.ports.create('second')
517
518 this.kernel.ports.bind(one, 'one')
519 this.kernel.ports.bind(two, 'two')
520
521 return Promise.all([
522 this.kernel.send(two, new Message()),
523 this.kernel.send(one, new Message())
524 ])
525 } else if (this.runs === 1) {
526 this.runs++
527 t.equals(m.data, 'first', 'should recive the first message')
528 } else if (this.runs === 2) {
529 t.equals(m.data, 'second', 'should recived the second message')
530 }
531 }
532 }
533
534 class First extends BaseContainer {
535 run (m) {
536 this.kernel.incrementTicks(2)
537 return this.kernel.send(m.fromPort, new Message({
538 resources: {
539 priority: 100
540 },
541 data: 'first'
542 }))
543 }
544 }
545
546 class Second extends BaseContainer {
547 run (m) {
548 this.kernel.incrementTicks(2)
549 return this.kernel.send(m.fromPort, new Message({
550 data: 'second'
551 }))
552 }
553 }
554
555 const hypervisor = new Hypervisor({
556 dag: node.dag
557 })
558
559 hypervisor.registerContainer('root', Root)
560 hypervisor.registerContainer('first', First)
561 hypervisor.registerContainer('second', Second)
562
563 const root = await hypervisor.createInstance('root')
564 const port = root.ports.create('root')
565 root.ports.bind(port, 'first')
566 root.send(port, new Message())
567 })
568
569 tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => {
570 t.plan(2)
571
572 class Root extends BaseContainer {
573 run (m) {
574 if (!this.runs) {
575 this.runs = 1
576
577 const one = this.kernel.ports.create('first')
578 const two = this.kernel.ports.create('second')
579
580 this.kernel.ports.bind(one, 'one')
581 this.kernel.ports.bind(two, 'two')
582
583 return Promise.all([
584 this.kernel.send(two, new Message()),
585 this.kernel.send(one, new Message())
586 ])
587 } else if (this.runs === 1) {
588 this.runs++
589 t.equals(m.data, 'second', 'should recive the first message')
590 } else if (this.runs === 2) {
591 t.equals(m.data, 'first', 'should recived the second message')
592 }
593 }
594 }
595
596 class First extends BaseContainer {
597 run (m) {
598 this.kernel.incrementTicks(2)
599 return this.kernel.send(m.fromPort, new Message({
600 data: 'first'
601 }))
602 }
603 }
604
605 class Second extends BaseContainer {
606 run (m) {
607 this.kernel.incrementTicks(2)
608 return this.kernel.send(m.fromPort, new Message({
609 resources: {
610 priority: 100
611 },
612 data: 'second'
613 }))
614 }
615 }
616
617 const hypervisor = new Hypervisor({
618 dag: node.dag
619 })
620
621 hypervisor.registerContainer('root', Root)
622 hypervisor.registerContainer('first', First)
623 hypervisor.registerContainer('second', Second)
624
625 const root = await hypervisor.createInstance('root')
626 const port = root.ports.create('root')
627 root.ports.bind(port, 'first')
628 root.send(port, new Message())
629 })
630
631 tape('should order parent messages correctly', async t => {
632 t.plan(1)
633 class Middle extends BaseContainer {
634 run (m) {
635 if (!this.runs) {
636 this.runs = 1
637 this.kernel.incrementTicks(1)
638
639 const leaf = this.kernel.ports.create('leaf')
640 this.kernel.ports.bind(leaf, 'leaf')
641
642 return this.kernel.send(leaf, new Message())
643 } else {
644 ++this.runs
645 if (this.runs === 3) {
646 t.equals(m.data, 'first')
647 }
648 }
649 }
650 }
651
652 class Leaf extends BaseContainer {
653 run (m) {
654 this.kernel.incrementTicks(2)
655 return this.kernel.send(m.fromPort, new Message({
656 data: 'first'
657 }))
658 }
659 }
660
661 const hypervisor = new Hypervisor({
662 dag: node.dag
663 })
664
665 hypervisor.registerContainer('root', BaseContainer)
666 hypervisor.registerContainer('middle', Middle)
667 hypervisor.registerContainer('leaf', Leaf)
668
669 const root = await hypervisor.createInstance('root')
670 root.incrementTicks(2)
671
672 const port = root.ports.create('middle')
673 root.ports.bind(port, 'first')
674
675 await root.send(port, new Message())
676 root.send(port, new Message())
677 })
678})
679

Built with git-ssb-web