git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 3f8c23e36f6d90d0c86b778fb27c24c5aa57c8a1

Files: 3f8c23e36f6d90d0c86b778fb27c24c5aa57c8a1 / tests / index.js

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

Built with git-ssb-web