git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 2275e7c92d36229646a81cd7ee76f25234fc2a87

Files: 2275e7c92d36229646a81cd7ee76f25234fc2a87 / tests / index.js

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

Built with git-ssb-web