git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 5a33099559b3af6b0c5c0e444a8d537471853b77

Files: 5a33099559b3af6b0c5c0e444a8d537471853b77 / tests / index.js

15798 bytesRaw
1const tape = require('tape')
2const Message = require('../message.js')
3const Hypervisor = require('../')
4
5const level = require('level-browserify')
6const RadixTree = require('dfinity-radix-tree')
7const db = level('./testdb')
8
9class BaseContainer {
10 static validate () {}
11 static get typeId () {
12 return 9
13 }
14
15 static exports (m, id) {
16 return Object.keys(this.functions()).map(name => {
17 return {
18 name,
19 destId: id
20 }
21 })
22 }
23 static instance (actor) {
24 return {
25 exports: this.functions(actor)
26 }
27 }
28}
29
30tape('basic', async t => {
31 t.plan(2)
32 const expectedState = {
33 '/': Buffer.from('926de6b7eb39cfa8d7f8a44d1ef191d3bcb765a7', 'hex')
34 }
35
36 const tree = new RadixTree({
37 db: db
38 })
39
40 class testVMContainer extends BaseContainer {
41 static functions () {
42 return {
43 onMessage: (m) => {
44 t.true(m === 1, 'should recive a message')
45 }
46 }
47 }
48 }
49
50 const hypervisor = new Hypervisor(tree)
51 hypervisor.registerContainer(testVMContainer)
52
53 let {exports} = await hypervisor.createActor(testVMContainer.typeId)
54
55 const message = new Message({
56 funcRef: exports[0],
57 funcArguments: [1]
58 })
59 hypervisor.send(message)
60
61 const stateRoot = await hypervisor.createStateRoot()
62 t.deepEquals(stateRoot, expectedState, 'expected root!')
63})
64
65tape('two communicating actors', async t => {
66 t.plan(2)
67 const expectedState = {
68 '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex')
69 }
70
71 const tree = new RadixTree({
72 db: db
73 })
74
75 class testVMContainerA extends BaseContainer {
76 static functions (actor) {
77 return {
78 onMessage: (funcRef) => {
79 const message = new Message({
80 funcRef: funcRef,
81 funcArguments: [2]
82 })
83 return actor.send(message)
84 }
85 }
86 }
87 }
88
89 class testVMContainerB extends BaseContainer {
90 static functions () {
91 return {
92 onMessage: (args) => {
93 t.equals(args, 2, 'should recive a message')
94 }
95 }
96 }
97
98 static get typeId () {
99 return 8
100 }
101 }
102
103 const hypervisor = new Hypervisor(tree)
104 hypervisor.registerContainer(testVMContainerA)
105 hypervisor.registerContainer(testVMContainerB)
106
107 const {exports: exportsB} = await hypervisor.createActor(testVMContainerB.typeId)
108 const {exports: exportsA} = await hypervisor.createActor(testVMContainerA.typeId)
109
110 const message = new Message({
111 funcRef: exportsA[0],
112 funcArguments: exportsB
113 })
114
115 hypervisor.send(message)
116
117 const stateRoot = await hypervisor.createStateRoot()
118 t.deepEquals(stateRoot, expectedState, 'expected root!')
119})
120
121tape('three communicating actors', async t => {
122 t.plan(3)
123 const expectedState = {
124 '/': Buffer.from('4633ac4b9f8212e501b6c56906039ec081fbe5a3', 'hex')
125 }
126
127 const tree = new RadixTree({
128 db: db
129 })
130
131 class testVMContainerA extends BaseContainer {
132 static functions (actor) {
133 return {
134 onMessage: (funcRef) => {
135 const message = new Message({
136 funcRef: funcRef,
137 funcArguments: [2]
138 })
139 actor.send(message)
140 }
141 }
142 }
143 }
144
145 class testVMContainerB extends BaseContainer {
146 static functions () {
147 return {
148 onMessage: (arg) => {
149 t.equals(arg, 2, 'should recive a message')
150 }
151 }
152 }
153
154 static get typeId () {
155 return 8
156 }
157 }
158
159 const hypervisor = new Hypervisor(tree)
160 hypervisor.registerContainer(testVMContainerA)
161 hypervisor.registerContainer(testVMContainerB)
162
163 let {exports: exportsB} = await hypervisor.createActor(testVMContainerB.typeId)
164 let {exports: exportsA0} = await hypervisor.createActor(testVMContainerA.typeId)
165 let {exports: exportsA1} = await hypervisor.createActor(testVMContainerA.typeId)
166
167 const message0 = new Message({
168 funcRef: exportsA0[0],
169 funcArguments: [exportsB[0]]
170 })
171
172 const message1 = new Message({
173 funcRef: exportsA1[0],
174 funcArguments: [exportsB[0]]
175 })
176
177 await hypervisor.send(message0)
178 await hypervisor.send(message1)
179
180 const stateRoot = await hypervisor.createStateRoot()
181 t.deepEquals(stateRoot, expectedState, 'expected root!')
182})
183
184tape('three communicating actors, with tick counting', async t => {
185 t.plan(3)
186 const expectedState = {
187 '/': Buffer.from('4633ac4b9f8212e501b6c56906039ec081fbe5a3', 'hex')
188 }
189
190 const tree = new RadixTree({
191 db: db
192 })
193
194 class testVMContainerA extends BaseContainer {
195 static functions (actor) {
196 return {
197 onMessage: funcRef => {
198 actor.incrementTicks(1)
199 const message = new Message({
200 funcRef: funcRef,
201 funcArguments: [2]
202 })
203 actor.send(message)
204 }
205 }
206 }
207 }
208
209 class testVMContainerB extends BaseContainer {
210 static functions (actor) {
211 return {
212 onMessage: arg => {
213 t.equals(arg, 2, 'should recive a message')
214 }
215 }
216 }
217
218 static get typeId () {
219 return 8
220 }
221 }
222
223 const hypervisor = new Hypervisor(tree)
224 hypervisor.registerContainer(testVMContainerA)
225 hypervisor.registerContainer(testVMContainerB)
226
227 let actorB = await hypervisor.createActor(testVMContainerB.typeId)
228 let actorA0 = await hypervisor.createActor(testVMContainerA.typeId)
229 let actorA1 = await hypervisor.createActor(testVMContainerA.typeId)
230
231 const message0 = new Message({
232 funcRef: actorA0.exports[0],
233 funcArguments: [actorB.exports[0]]
234 })
235 const message1 = new Message({
236 funcRef: actorA1.exports[0],
237 funcArguments: actorB.exports
238 })
239
240 hypervisor.send(message0)
241 hypervisor.send(message1)
242
243 const stateRoot = await hypervisor.createStateRoot()
244 t.deepEquals(stateRoot, expectedState, 'expected root!')
245})
246
247tape('errors', async t => {
248 t.plan(3)
249 const expectedState = {
250 '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex')
251 }
252
253 const tree = new RadixTree({
254 db: db
255 })
256
257 class testVMContainerA extends BaseContainer {
258 static functions (actor) {
259 return {
260 onMessage: funcRef => {
261 const message = new Message({
262 funcRef
263 })
264 message.on('execution:error', () => {
265 t.pass('should recive a exeption')
266 })
267 actor.send(message)
268 }
269 }
270 }
271 }
272
273 class testVMContainerB extends BaseContainer {
274 static functions (actor) {
275 return {
276 onMessage: funcRef => {
277 t.true(true, 'should recive a message')
278 throw new Error('test error')
279 }
280 }
281 }
282
283 static get typeId () {
284 return 8
285 }
286 }
287
288 const hypervisor = new Hypervisor(tree)
289 hypervisor.registerContainer(testVMContainerA)
290 hypervisor.registerContainer(testVMContainerB)
291
292 let {exports: exportsB} = await hypervisor.createActor(testVMContainerB.typeId)
293 let {exports: exportsA} = await hypervisor.createActor(testVMContainerA.typeId)
294 const message = new Message({
295 funcRef: exportsA[0],
296 funcArguments: exportsB
297 })
298 hypervisor.send(message)
299 const stateRoot = await hypervisor.createStateRoot()
300 t.deepEquals(stateRoot, expectedState, 'expected root!')
301})
302
303tape('actor creation', async t => {
304 t.plan(2)
305 const expectedState = {
306 '/': Buffer.from('f47377a763c91247e62138408d706a09bccaaf36', 'hex')
307 }
308
309 const tree = new RadixTree({
310 db: db
311 })
312
313 class testVMContainerA extends BaseContainer {
314 static functions (actor) {
315 return {
316 onCreation: async funcRef => {
317 const {exports} = await actor.createActor(testVMContainerB.typeId)
318 const message = new Message({
319 funcRef: exports[0],
320 funcArguments: [actor.getFuncRef('onMessage')]
321 })
322 actor.send(message)
323 },
324 onMessage: data => {
325 t.equals(data, 'test', 'should recive a response message')
326 }
327 }
328 }
329 }
330
331 class testVMContainerB extends BaseContainer {
332 static functions (actor) {
333 return {
334 onCreation: funcRef => {
335 actor.send(new Message({funcRef, funcArguments: ['test']}))
336 }
337 }
338 }
339
340 static get typeId () {
341 return 8
342 }
343 }
344
345 const hypervisor = new Hypervisor(tree)
346 hypervisor.registerContainer(testVMContainerA)
347 hypervisor.registerContainer(testVMContainerB)
348
349 const {exports} = await hypervisor.createActor(testVMContainerA.typeId)
350 await hypervisor.send(new Message({funcRef: exports[0]}))
351
352 const stateRoot = await hypervisor.createStateRoot()
353 t.deepEquals(stateRoot, expectedState, 'expected root!')
354})
355
356tape('simple message arbiter test', async t => {
357 t.plan(4)
358 const expectedState = {
359 '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex')
360 }
361
362 const tree = new RadixTree({
363 db: db
364 })
365
366 class testVMContainerA extends BaseContainer {
367 static functions (actor) {
368 return {
369 onCreation: funcRef => {
370 const message1 = new Message({
371 funcArguments: ['first'],
372 funcRef
373 })
374 const message2 = new Message({
375 funcArguments: ['second'],
376 funcRef
377 })
378 const message3 = new Message({
379 funcArguments: ['third'],
380 funcRef
381 })
382 actor.send(message1)
383 actor.incrementTicks(1)
384 actor.send(message2)
385 actor.incrementTicks(1)
386 actor.send(message3)
387 }
388 }
389 }
390 }
391
392 let recMsg = 0
393
394 class testVMContainerB extends BaseContainer {
395 static functions (actor) {
396 return {
397 onMessage: data => {
398 actor.incrementTicks(1)
399 if (recMsg === 0) {
400 t.equal(data, 'first', 'should recive fist message')
401 } else if (recMsg === 1) {
402 t.equal(data, 'second', 'should recive second message')
403 } else {
404 t.equal(data, 'third', 'should recive third message')
405 }
406 recMsg++
407 }
408 }
409 }
410
411 static get typeId () {
412 return 8
413 }
414 }
415
416 const hypervisor = new Hypervisor(tree)
417 hypervisor.registerContainer(testVMContainerA)
418 hypervisor.registerContainer(testVMContainerB)
419
420 const {exports: exportsB} = await hypervisor.createActor(testVMContainerB.typeId)
421 const {exports: exportsA} = await hypervisor.createActor(testVMContainerA.typeId)
422 const message = new Message({
423 funcRef: exportsA[0],
424 funcArguments: exportsB
425 })
426 hypervisor.send(message)
427
428 const stateRoot = await hypervisor.createStateRoot()
429 t.deepEquals(stateRoot, expectedState, 'expected root!')
430})
431
432tape('arbiter test for id comparision', async t => {
433 t.plan(4)
434 let message
435 const expectedState = {
436 '/': Buffer.from('4633ac4b9f8212e501b6c56906039ec081fbe5a3', 'hex')
437 }
438
439 const tree = new RadixTree({
440 db: db
441 })
442
443 class testVMContainerA extends BaseContainer {
444 static functions (actor) {
445 return {
446 onCreation: (funcRef, funcArguments) => {
447 actor.incrementTicks(1)
448 message = new Message({
449 funcRef,
450 funcArguments: [funcArguments]
451 })
452 return actor.send(message)
453 }
454 }
455 }
456 }
457
458 let recMsg = 0
459
460 class testVMContainerB extends BaseContainer {
461 static functions (actor) {
462 return {
463 onMessage: data => {
464 if (recMsg === 0) {
465 t.equal(data, 'first', 'should recive fist message')
466 } else if (recMsg === 1) {
467 t.equal(data, 'second', 'should recive second message')
468 } else {
469 t.equal(data, 'third', 'should recive third message')
470 }
471 recMsg++
472 }
473 }
474 }
475
476 static get typeId () {
477 return 8
478 }
479 }
480
481 const hypervisor = new Hypervisor(tree)
482 hypervisor.registerContainer(testVMContainerA)
483 hypervisor.registerContainer(testVMContainerB)
484
485 let {exports: exportsB} = await hypervisor.createActor(testVMContainerB.typeId)
486 hypervisor.send(new Message({
487 funcRef: exportsB[0],
488 funcArguments: ['first']
489 }))
490
491 const {exports: exportsA0} = await hypervisor.createActor(testVMContainerA.typeId)
492
493 hypervisor.send(new Message({
494 funcRef: exportsA0[0],
495 funcArguments: [exportsB[0], 'second']
496 }))
497
498 const {exports: exportsA1} = await hypervisor.createActor(testVMContainerA.typeId)
499 hypervisor.send(new Message({
500 funcRef: exportsA1[0],
501 funcArguments: [exportsB[0], 'third']
502 }))
503
504 const stateRoot = await hypervisor.createStateRoot()
505 t.deepEquals(stateRoot, expectedState, 'expected root!')
506})
507
508tape('async work', async t => {
509 t.plan(3)
510 const expectedState = {
511 '/': Buffer.from('a4c7ceacd8c867ae1d0b472d8bffa3cb10048331', 'hex')
512 }
513
514 const tree = new RadixTree({
515 db: db
516 })
517
518 class testVMContainerA extends BaseContainer {
519 static functions (actor) {
520 return {
521 onMessage: (funcRef) => {
522 const message = new Message({
523 funcRef: funcRef,
524 funcArguments: [2]
525 })
526 actor.send(message)
527
528 const message2 = new Message({
529 funcRef: funcRef,
530 funcArguments: [2]
531 })
532 actor.send(message2)
533 actor.incrementTicks(1)
534 return new Promise((resolve, reject) => {
535 setTimeout(() => {
536 resolve()
537 }, 10)
538 })
539 }
540 }
541 }
542 }
543
544 class testVMContainerB extends BaseContainer {
545 static functions (actor) {
546 return {
547 onMessage: (args) => {
548 actor.incrementTicks(1)
549 t.equals(args, 2, 'should recive a message')
550 }
551 }
552 }
553
554 static get typeId () {
555 return 8
556 }
557 }
558
559 const hypervisor = new Hypervisor(tree)
560 hypervisor.registerContainer(testVMContainerA)
561 hypervisor.registerContainer(testVMContainerB)
562
563 const {exports: exportsB} = await hypervisor.createActor(testVMContainerB.typeId)
564 const {exports: exportsA} = await hypervisor.createActor(testVMContainerA.typeId)
565
566 const message = new Message({
567 funcRef: exportsA[0],
568 funcArguments: exportsB
569 })
570
571 hypervisor.send(message)
572
573 const stateRoot = await hypervisor.createStateRoot()
574 t.deepEquals(stateRoot, expectedState, 'expected root!')
575})
576
577tape('random', async t => {
578 const numOfActors = 10
579 const depth = 10
580 const messageOrder = {}
581 let numOfMsg = 0
582 const tree = new RadixTree({
583 db: db
584 })
585
586 class BenchmarkContainer extends BaseContainer {
587 static functions (actor) {
588 return {
589 onMessage: function () {
590 const refs = [...arguments]
591 const ref = refs.pop()
592 const last = messageOrder[actor.id.toString('hex')]
593 const message = actor.currentMessage
594 if (last) {
595 t.ok(last <= message._fromTicks)
596 }
597 messageOrder[actor.id.toString('hex')] = message._fromTicks
598 numOfMsg++
599 actor.incrementTicks(10)
600 if (ref) {
601 actor.send(new Message({
602 funcRef: ref,
603 funcArguments: refs
604 }))
605 }
606 }
607 }
608 }
609 }
610
611 const hypervisor = new Hypervisor(tree)
612 hypervisor.registerContainer(BenchmarkContainer)
613
614 const refernces = []
615 let _numOfActors = numOfActors
616 while (_numOfActors--) {
617 const {exports} = await hypervisor.createActor(BenchmarkContainer.typeId)
618 refernces.push(exports[0])
619 }
620 _numOfActors = numOfActors
621 let msgs = []
622 while (_numOfActors--) {
623 let _depth = depth
624 const funcArguments = []
625 while (_depth--) {
626 const r = Math.floor(Math.random() * numOfActors)
627 const ref = refernces[r]
628 funcArguments.push(ref)
629 }
630 const message = new Message({
631 funcArguments,
632 funcRef: refernces[_numOfActors]
633 })
634 msgs.push(message)
635 }
636
637 hypervisor.send(msgs)
638 await hypervisor.scheduler.on('idle', () => {
639 t.equals(numOfMsg, 110)
640 t.end()
641 })
642})
643

Built with git-ssb-web