git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: e0e219228a47a0ba7de5d933251a480f1bacf2ae

Files: e0e219228a47a0ba7de5d933251a480f1bacf2ae / tests / index.js

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

Built with git-ssb-web