git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 0de9abab60ad6c7b9852a3219889dc1a080484d5

Files: 0de9abab60ad6c7b9852a3219889dc1a080484d5 / tests / index.js

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

Built with git-ssb-web