git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 1ffd915b15f2f2a528bc6e5329be0be2c9cab33b

Files: 1ffd915b15f2f2a528bc6e5329be0be2c9cab33b / tests / index.js

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

Built with git-ssb-web