git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 2f1d81adf2eec8e0c13058fae79efee1a6af4a58

Files: 2f1d81adf2eec8e0c13058fae79efee1a6af4a58 / tests / index.js

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

Built with git-ssb-web