git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: acd65bd28b852ab061aad493bc85901d386b2b9b

Files: acd65bd28b852ab061aad493bc85901d386b2b9b / tests / index.js

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

Built with git-ssb-web