git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 7feb7c9fd152c9b122c6ee9ec57387c444a89541

Files: 7feb7c9fd152c9b122c6ee9ec57387c444a89541 / tests / index.js

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

Built with git-ssb-web