git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 1ee5f08dcf25af27f0dce6fdc1eab39b185d202f

Files: 1ee5f08dcf25af27f0dce6fdc1eab39b185d202f / tests / index.js

14266 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('a5e1aaebec14b7f144d6a7e007b148aa7c56804c', '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('bc0af44b691ef57b362df8b11c274742147900cd', '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('86e066f60fe2f722befbc29f128948f6487a207a', '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('86e066f60fe2f722befbc29f128948f6487a207a', '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('bc0af44b691ef57b362df8b11c274742147900cd', '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('544ae05bc8831cc69c5524bc3a51c0d4806e9d60', '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: [this.actor.getFuncRef('main')]
285 })
286 this.actor.send(message)
287 }
288 main (data) {
289 t.equals(data, 'test', 'should recive a response message')
290 }
291 }
292
293 class testVMContainerB extends BaseContainer {
294 main (funcRef) {
295 this.actor.send(new Message({funcRef, funcArguments: ['test']}))
296 }
297
298 static get typeId () {
299 return 8
300 }
301 }
302
303 const hypervisor = new Hypervisor(tree)
304 hypervisor.registerContainer(testVMContainerA)
305 hypervisor.registerContainer(testVMContainerB)
306
307 const {module} = await hypervisor.createActor(testVMContainerA.typeId)
308 await hypervisor.send(new Message({funcRef: module.start}))
309
310 const stateRoot = await hypervisor.createStateRoot()
311 t.deepEquals(stateRoot, expectedState, 'expected root!')
312 t.end()
313})
314
315tape('simple message arbiter test', async t => {
316 t.plan(4)
317 const expectedState = {
318 '/': Buffer.from('bc0af44b691ef57b362df8b11c274742147900cd', 'hex')
319 }
320
321 const tree = new RadixTree({
322 db: db
323 })
324
325 class testVMContainerA extends BaseContainer {
326 main (funcRef) {
327 const message1 = new Message({
328 funcArguments: ['first'],
329 funcRef
330 })
331 const message2 = new Message({
332 funcArguments: ['second'],
333 funcRef
334 })
335 const message3 = new Message({
336 funcArguments: ['third'],
337 funcRef
338 })
339 this.actor.send(message1)
340 this.actor.incrementTicks(1)
341 this.actor.send(message2)
342 this.actor.incrementTicks(1)
343 this.actor.send(message3)
344 }
345 }
346
347 let recMsg = 0
348
349 class testVMContainerB extends BaseContainer {
350 main (data) {
351 this.actor.incrementTicks(1)
352 if (recMsg === 0) {
353 t.equal(data, 'first', 'should recive fist message')
354 } else if (recMsg === 1) {
355 t.equal(data, 'second', 'should recive second message')
356 } else {
357 t.equal(data, 'third', 'should recive third message')
358 }
359 recMsg++
360 }
361
362 static get typeId () {
363 return 8
364 }
365 }
366
367 const hypervisor = new Hypervisor(tree)
368 hypervisor.registerContainer(testVMContainerA)
369 hypervisor.registerContainer(testVMContainerB)
370
371 const {module: moduleB} = await hypervisor.createActor(testVMContainerB.typeId)
372 const {module: moduleA} = await hypervisor.createActor(testVMContainerA.typeId)
373 const message = new Message({
374 funcRef: moduleA.main,
375 funcArguments: [moduleB.main]
376 })
377 hypervisor.send(message)
378
379 const stateRoot = await hypervisor.createStateRoot()
380 t.deepEquals(stateRoot, expectedState, 'expected root!')
381})
382
383tape('arbiter test for id comparision', async t => {
384 t.plan(4)
385 let message
386 const expectedState = {
387 '/': Buffer.from('86e066f60fe2f722befbc29f128948f6487a207a', 'hex')
388 }
389
390 const tree = new RadixTree({
391 db: db
392 })
393
394 class testVMContainerA extends BaseContainer {
395 main (funcRef, funcArguments) {
396 this.actor.incrementTicks(1)
397 message = new Message({
398 funcRef,
399 funcArguments: [funcArguments]
400 })
401 this.actor.send(message)
402 }
403 }
404
405 let recMsg = 0
406
407 class testVMContainerB extends BaseContainer {
408 main (data) {
409 if (recMsg === 0) {
410 t.equal(data, 'first', 'should recive fist message')
411 } else if (recMsg === 1) {
412 t.equal(data, 'second', 'should recive second message')
413 } else {
414 t.equal(data, 'third', 'should recive third message')
415 }
416 recMsg++
417 }
418
419 static get typeId () {
420 return 8
421 }
422 }
423
424 const hypervisor = new Hypervisor(tree)
425 hypervisor.registerContainer(testVMContainerA)
426 hypervisor.registerContainer(testVMContainerB)
427
428 let {module: moduleB} = await hypervisor.createActor(testVMContainerB.typeId)
429 hypervisor.send(new Message({
430 funcRef: moduleB.main,
431 funcArguments: ['first']
432 }))
433
434 const {module: moduleA0} = await hypervisor.createActor(testVMContainerA.typeId)
435
436 hypervisor.send(new Message({
437 funcRef: moduleA0.main,
438 funcArguments: [moduleB.main, 'second']
439 }))
440
441 const {module: moduleA1} = await hypervisor.createActor(testVMContainerA.typeId)
442 hypervisor.send(new Message({
443 funcRef: moduleA1.main,
444 funcArguments: [moduleB.main, 'third']
445 }))
446
447 const stateRoot = await hypervisor.createStateRoot()
448 t.deepEquals(stateRoot, expectedState, 'expected root!')
449})
450
451tape('async work', async t => {
452 t.plan(3)
453 const expectedState = {
454 '/': Buffer.from('bc0af44b691ef57b362df8b11c274742147900cd', 'hex')
455 }
456
457 const tree = new RadixTree({
458 db: db
459 })
460
461 class testVMContainerA extends BaseContainer {
462 main (funcRef) {
463 const message = new Message({
464 funcRef: funcRef,
465 funcArguments: [2]
466 })
467 this.actor.send(message)
468
469 const message2 = new Message({
470 funcRef: funcRef,
471 funcArguments: [2]
472 })
473 this.actor.send(message2)
474 this.actor.incrementTicks(1)
475 return new Promise((resolve, reject) => {
476 setTimeout(() => {
477 resolve()
478 }, 10)
479 })
480 }
481 }
482
483 class testVMContainerB extends BaseContainer {
484 main (args) {
485 this.actor.incrementTicks(1)
486 t.equals(args, 2, 'should recive a message')
487 }
488
489 static get typeId () {
490 return 8
491 }
492 }
493
494 const hypervisor = new Hypervisor(tree)
495 hypervisor.registerContainer(testVMContainerA)
496 hypervisor.registerContainer(testVMContainerB)
497
498 const {module: moduleB} = await hypervisor.createActor(testVMContainerB.typeId)
499 const {module: moduleA} = await hypervisor.createActor(testVMContainerA.typeId)
500
501 const message = new Message({
502 funcRef: moduleA.main,
503 funcArguments: [moduleB.main]
504 })
505
506 hypervisor.send(message)
507
508 const stateRoot = await hypervisor.createStateRoot()
509 t.deepEquals(stateRoot, expectedState, 'expected root!')
510})
511
512tape('random', async t => {
513 const numOfActors = 10
514 const depth = 10
515 const messageOrder = {}
516 let numOfMsg = 0
517 const tree = new RadixTree({
518 db: db
519 })
520
521 class BenchmarkContainer extends BaseContainer {
522 main () {
523 const refs = [...arguments]
524 const ref = refs.pop()
525 const last = messageOrder[this.actor.id.toString('hex')]
526 const message = this.actor.currentMessage
527 if (last) {
528 t.ok(last <= message._fromTicks)
529 }
530 messageOrder[this.actor.id.toString('hex')] = message._fromTicks
531 numOfMsg++
532 this.actor.incrementTicks(10)
533 if (ref) {
534 this.actor.send(new Message({
535 funcRef: ref,
536 funcArguments: refs
537 }))
538 }
539 }
540 }
541
542 const hypervisor = new Hypervisor(tree)
543 hypervisor.registerContainer(BenchmarkContainer)
544
545 const refernces = []
546 let _numOfActors = numOfActors
547 while (_numOfActors--) {
548 const {module} = await hypervisor.createActor(BenchmarkContainer.typeId)
549 refernces.push(module.main)
550 }
551 _numOfActors = numOfActors
552 let msgs = []
553 while (_numOfActors--) {
554 let _depth = depth
555 const funcArguments = []
556 while (_depth--) {
557 const r = Math.floor(Math.random() * numOfActors)
558 const ref = refernces[r]
559 funcArguments.push(ref)
560 }
561 const message = new Message({
562 funcArguments,
563 funcRef: refernces[_numOfActors]
564 })
565 msgs.push(message)
566 }
567
568 hypervisor.send(msgs)
569 await hypervisor.scheduler.on('idle', () => {
570 t.equals(numOfMsg, 110)
571 t.end()
572 })
573})
574

Built with git-ssb-web