git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit d9b6113bb6b82443c2fb8a9a9b1afa58b1206f67

passing all tests

wanderer committed on 5/13/2017, 6:49:54 PM
Parent: f53952e52386255d9558c848de3deb7c976779cd

Files changed

kernel.jschanged
package.jsonchanged
port.jschanged
portManager.jschanged
tests/index.jschanged
kernel.jsView
@@ -1,8 +1,7 @@
1-const PriorityQueue = require('fastpriorityqueue')
1+const BN = require('bn.js')
22 const clearObject = require('object-clear')
33 const clone = require('clone')
4-const BN = require('bn.js')
54 const EventEmitter = require('events')
65 const PortManager = require('./portManager.js')
76
87 module.exports = class Kernel extends EventEmitter {
@@ -39,8 +38,9 @@
3938 return this.ports.start()
4039 }
4140
4241 queue (message) {
42+ message._hops++
4343 this.ports.queue(message)
4444 if (this.vmState !== 'running') {
4545 this._updateVmState('running')
4646 this._runNextMessage()
@@ -107,9 +107,9 @@
107107 }
108108
109109 incrementTicks (count) {
110110 this.ticks += count
111- for (const [fromPort, waiter] in this._waitingMap) {
111+ for (const [fromPort, waiter] of this._waitingMap) {
112112 if (waiter.threshold < this.ticks) {
113113 this._waitingMap.delete(fromPort)
114114 waiter.resolve(this.ticks)
115115 }
@@ -145,12 +145,11 @@
145145 }
146146
147147 async send (portRef, message) {
148148 message._fromPort = this.entryPort
149- message._ticks = this.ticks
149+ message._fromPortTicks = this.ticks
150150
151- const receiverEntryPort = portRef === this.entryPort ? this.parentPort : portRef
152- const vm = await this.hypervisor.getInstance(receiverEntryPort)
151+ const vm = await this.hypervisor.getInstance(portRef)
153152 vm.queue(message)
154153
155154 const waiter = this._waitingMap.get(portRef)
156155 if (waiter) {
package.jsonView
@@ -5,9 +5,9 @@
55 "scripts": {
66 "coverage": "node ./node_modules/istanbul/lib/cli.js cover ./tests/index.js",
77 "coveralls": "npm run coverage && coveralls <coverage/lcov.info",
88 "lint": "standard",
9- "test": "node ./tests/index.js",
9+ "test": "tape ./tests/index.js",
1010 "build": "node ./tests/buildTests.js && ./tools/wabt/out/wast2wasm ./wasm/interface.wast -o ./wasm/interface.wasm"
1111 },
1212 "repository": {
1313 "type": "git",
port.jsView
@@ -5,37 +5,16 @@
55 this.ticks = 0
66 }
77
88 queue (message) {
9- this.ticks = message._ticks
10- if (this._resolve) {
11- return this._resolve(message)
12- } else {
13- this._queue.push(message)
14- }
9+ this.ticks = message._fromPortTicks
10+ this._queue.push(message)
1511 }
1612
17- // this only workls for one Promise
18- nextMessage () {
19- const message = this.queue.shift()
20-
21- return new Promise((resolve, reject) => {
22- if (message) {
23- resolve(message)
24- } else {
25- this._resolve = resolve
26- }
27- })
28- }
29-
3013 peek () {
3114 return this._queue[0]
3215 }
3316
3417 shift () {
3518 return this._queue.shift()
3619 }
37-
38- unshift (message) {
39- return this._queue.unshift(message)
40- }
4120 }
portManager.jsView
@@ -1,26 +1,29 @@
11 const Port = require('./port.js')
22 const ENTRY = Symbol('entry')
33
4-// decides which message to go firts
4+// decides which message to go first
55 function messageArbiter (pairA, pairB) {
6- const a = pairA[1].peek()
7- const b = pairB[1].peek()
6+ const portA = pairA[1]
7+ const portB = pairB[1]
8+ const a = portA.peek()
9+ const b = portB.peek()
810
911 if (!a) {
1012 return pairB
1113 } else if (!b) {
1214 return pairA
1315 }
1416
15- const aGasPrice = a.resources.gasPrice
16- const bGasPrice = b.resources.gasPrice
17- if (a.ticks !== b.ticks) {
18- return a.ticks < b.ticks ? pairA : pairB
19- } else if (aGasPrice === bGasPrice) {
20- return a.hash() > b.hash() ? pairA : pairB
17+ if (a._fromPortTicks !== b._fromPortTicks) {
18+ return a._fromPortTicks < b._fromPortTicks ? pairA : pairB
19+ } else if (a.priority !== b.priority) {
20+ // decide by priority
21+ return a.priority > b.priority ? pairA : pairB
22+ } else if (portA.name === ENTRY) {
23+ return pairA
2124 } else {
22- return aGasPrice > bGasPrice ? pairA : pairB
25+ return portA.name < portB.name ? pairA : pairB
2326 }
2427 }
2528
2629 module.exports = class PortManager {
@@ -29,19 +32,18 @@
2932 this._portMap = new Map()
3033 }
3134
3235 async start () {
36+ // skip the root, since it doesn't have a parent
37+ if (this.parentPort !== undefined) {
38+ this._portMap.set(this.parentPort, new Port(ENTRY))
39+ }
3340 // map ports to thier id's
3441 this.ports = await this.hypervisor.graph.get(this.state, 'ports')
3542 Object.keys(this.ports).map(name => {
3643 const port = this.ports[name]
3744 this._mapPort(name, port)
3845 })
39-
40- // skip the root, since it doesn't have a parent
41- if (this.parentPort !== undefined) {
42- this._portMap.set(this.parentPort, new Port(ENTRY))
43- }
4446 }
4547
4648 _mapPort (name, portRef) {
4749 const port = new Port(name)
@@ -77,8 +79,7 @@
7779
7880 async getNextMessage () {
7981 await this.wait(this.kernel.ticks, this.entryPort)
8082 const portMap = [...this._portMap].reduce(messageArbiter)
81- // console.log('here!!!!', portMap)
8283 return portMap[1].shift()
8384 }
8485 }
tests/index.jsView
@@ -124,8 +124,9 @@
124124
125125 class Pong extends BaseContainer {
126126 run (m) {
127127 const port = m.fromPort
128+ this.kernel.incrementTicks(2)
128129 return this.kernel.send(port, new Message())
129130 }
130131 }
131132
@@ -160,9 +161,9 @@
160161 ])
161162
162163 return new Promise((resolve, reject) => {
163164 setTimeout(() => {
164- this.kernel.incrementTicks(2)
165+ this.kernel.incrementTicks(6)
165166 resolve()
166167 }, 200)
167168 })
168169 }
@@ -222,9 +223,378 @@
222223 }
223224 }, 'should revert the state')
224225
225226 t.end()
227+ })
226228
229+ tape('message should arrive in the correct oder if sent in order', async t => {
230+ t.plan(2)
231+
232+ class Root extends BaseContainer {
233+ async run (m) {
234+ if (!this.runs) {
235+ this.runs = 1
236+ const one = this.kernel.createPort('first', 'one')
237+ const two = this.kernel.createPort('second', 'two')
238+
239+ await Promise.all([
240+ this.kernel.send(one, new Message()),
241+ this.kernel.send(two, new Message())
242+ ])
243+
244+ this.kernel.incrementTicks(6)
245+ } else if (this.runs === 1) {
246+ this.runs++
247+ t.equals(m.data, 'first', 'should recive the first message')
248+ } else if (this.runs === 2) {
249+ t.equals(m.data, 'second', 'should recived the second message')
250+ }
251+ }
252+ }
253+
254+ class First extends BaseContainer {
255+ async run (m) {
256+ this.kernel.incrementTicks(1)
257+ await this.kernel.send(m.fromPort, new Message({data: 'first'}))
258+ }
259+ }
260+
261+ class Second extends BaseContainer {
262+ async run (m) {
263+ this.kernel.incrementTicks(2)
264+ await this.kernel.send(m.fromPort, new Message({data: 'second'}))
265+ }
266+ }
267+
268+ const hypervisor = new Hypervisor({
269+ dag: node.dag
270+ })
271+
272+ hypervisor.registerContainer('root', Root)
273+ hypervisor.registerContainer('first', First)
274+ hypervisor.registerContainer('second', Second)
275+
276+ const root = await hypervisor.createInstance('root')
277+ const port = await root.createPort('root', 'first')
278+ await root.send(port, new Message())
279+ })
280+
281+ tape('message should arrive in the correct order, even if sent out of order', async t => {
282+ t.plan(2)
283+
284+ class Root extends BaseContainer {
285+ async run (m) {
286+ if (!this.runs) {
287+ this.runs = 1
288+ const one = this.kernel.createPort('first', 'one')
289+ const two = this.kernel.createPort('second', 'two')
290+
291+ await Promise.all([
292+ this.kernel.send(one, new Message()),
293+ this.kernel.send(two, new Message())
294+ ])
295+
296+ this.kernel.incrementTicks(6)
297+ } else if (this.runs === 1) {
298+ this.runs++
299+ t.equals(m.data, 'second', 'should recive the first message')
300+ } else if (this.runs === 2) {
301+ t.equals(m.data, 'first', 'should recived the second message')
302+ }
303+ }
304+ }
305+
306+ class First extends BaseContainer {
307+ async run (m) {
308+ this.kernel.incrementTicks(2)
309+ await this.kernel.send(m.fromPort, new Message({data: 'first'}))
310+ }
311+ }
312+
313+ class Second extends BaseContainer {
314+ async run (m) {
315+ this.kernel.incrementTicks(1)
316+ await this.kernel.send(m.fromPort, new Message({data: 'second'}))
317+ }
318+ }
319+
320+ const hypervisor = new Hypervisor({
321+ dag: node.dag
322+ })
323+
324+ hypervisor.registerContainer('root', Root)
325+ hypervisor.registerContainer('first', First)
326+ hypervisor.registerContainer('second', Second)
327+
328+ const root = await hypervisor.createInstance('root')
329+ const port = await root.createPort('root', 'first')
330+ await root.send(port, new Message())
331+ })
332+
333+ tape('message should arrive in the correct order, even in a tie of ticks', async t => {
334+ t.plan(2)
335+
336+ class Root extends BaseContainer {
337+ async run (m) {
338+ if (!this.runs) {
339+ this.runs = 1
340+ const one = this.kernel.createPort('first', 'one')
341+ const two = this.kernel.createPort('second', 'two')
342+
343+ await Promise.all([
344+ this.kernel.send(one, new Message()),
345+ this.kernel.send(two, new Message())
346+ ])
347+
348+ this.kernel.incrementTicks(6)
349+ } else if (this.runs === 1) {
350+ this.runs++
351+ t.equals(m.data, 'first', 'should recived the second message')
352+ } else if (this.runs === 2) {
353+ t.equals(m.data, 'second', 'should recive the first message')
354+ }
355+ }
356+ }
357+
358+ class First extends BaseContainer {
359+ async run (m) {
360+ this.kernel.incrementTicks(2)
361+ await this.kernel.send(m.fromPort, new Message({data: 'first'}))
362+ }
363+ }
364+
365+ class Second extends BaseContainer {
366+ async run (m) {
367+ this.kernel.incrementTicks(2)
368+ await this.kernel.send(m.fromPort, new Message({data: 'second'}))
369+ }
370+ }
371+
372+ const hypervisor = new Hypervisor({
373+ dag: node.dag
374+ })
375+
376+ hypervisor.registerContainer('root', Root)
377+ hypervisor.registerContainer('first', First)
378+ hypervisor.registerContainer('second', Second)
379+
380+ const root = await hypervisor.createInstance('root')
381+ const port = await root.createPort('root', 'first')
382+ await root.send(port, new Message())
383+ })
384+
385+ tape('message should arrive in the correct order, even in a tie of ticks', async t => {
386+ t.plan(2)
387+
388+ class Root extends BaseContainer {
389+ async run (m) {
390+ if (!this.runs) {
391+ this.runs = 1
392+ const two = this.kernel.createPort('second', 'two')
393+ const one = this.kernel.createPort('first', 'one')
394+
395+ await Promise.all([
396+ this.kernel.send(two, new Message()),
397+ this.kernel.send(one, new Message())
398+ ])
399+
400+ this.kernel.incrementTicks(6)
401+ } else if (this.runs === 1) {
402+ this.runs++
403+ t.equals(m.data, 'first', 'should recived the second message')
404+ } else if (this.runs === 2) {
405+ t.equals(m.data, 'second', 'should recive the first message')
406+ }
407+ }
408+ }
409+
410+ class First extends BaseContainer {
411+ async run (m) {
412+ this.kernel.incrementTicks(2)
413+ await this.kernel.send(m.fromPort, new Message({data: 'first'}))
414+ }
415+ }
416+
417+ class Second extends BaseContainer {
418+ async run (m) {
419+ this.kernel.incrementTicks(2)
420+ await this.kernel.send(m.fromPort, new Message({data: 'second'}))
421+ }
422+ }
423+
424+ const hypervisor = new Hypervisor({
425+ dag: node.dag
426+ })
427+
428+ hypervisor.registerContainer('root', Root)
429+ hypervisor.registerContainer('first', First)
430+ hypervisor.registerContainer('second', Second)
431+
432+ const root = await hypervisor.createInstance('root')
433+ const port = await root.createPort('root', 'first')
434+ await root.send(port, new Message())
435+ })
436+
437+ tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => {
438+ t.plan(2)
439+
440+ class Root extends BaseContainer {
441+ async run (m) {
442+ if (!this.runs) {
443+ this.runs = 1
444+ const one = this.kernel.createPort('first', 'one')
445+ const two = this.kernel.createPort('second', 'two')
446+
447+ await Promise.all([
448+ this.kernel.send(two, new Message()),
449+ this.kernel.send(one, new Message())
450+ ])
451+
452+ this.kernel.incrementTicks(6)
453+ } else if (this.runs === 1) {
454+ this.runs++
455+ t.equals(m.data, 'first', 'should recive the first message')
456+ } else if (this.runs === 2) {
457+ t.equals(m.data, 'second', 'should recived the second message')
458+ }
459+ }
460+ }
461+
462+ class First extends BaseContainer {
463+ async run (m) {
464+ this.kernel.incrementTicks(2)
465+ await this.kernel.send(m.fromPort, new Message({
466+ resources: {
467+ priority: 100
468+ },
469+ data: 'first'
470+ }))
471+ }
472+ }
473+
474+ class Second extends BaseContainer {
475+ async run (m) {
476+ this.kernel.incrementTicks(2)
477+ await this.kernel.send(m.fromPort, new Message({data: 'second'}))
478+ }
479+ }
480+
481+ const hypervisor = new Hypervisor({
482+ dag: node.dag
483+ })
484+
485+ hypervisor.registerContainer('root', Root)
486+ hypervisor.registerContainer('first', First)
487+ hypervisor.registerContainer('second', Second)
488+
489+ const root = await hypervisor.createInstance('root')
490+ const port = await root.createPort('root', 'first')
491+ await root.send(port, new Message())
492+ })
493+
494+ tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => {
495+ t.plan(2)
496+
497+ class Root extends BaseContainer {
498+ async run (m) {
499+ if (!this.runs) {
500+ this.runs = 1
501+ const one = this.kernel.createPort('first', 'one')
502+ const two = this.kernel.createPort('second', 'two')
503+
504+ await Promise.all([
505+ this.kernel.send(two, new Message()),
506+ this.kernel.send(one, new Message())
507+ ])
508+
509+ this.kernel.incrementTicks(6)
510+ } else if (this.runs === 1) {
511+ this.runs++
512+ t.equals(m.data, 'second', 'should recive the first message')
513+ } else if (this.runs === 2) {
514+ t.equals(m.data, 'first', 'should recived the second message')
515+ }
516+ }
517+ }
518+
519+ class First extends BaseContainer {
520+ async run (m) {
521+ this.kernel.incrementTicks(2)
522+ await this.kernel.send(m.fromPort, new Message({
523+ data: 'first'
524+ }))
525+ }
526+ }
527+
528+ class Second extends BaseContainer {
529+ async run (m) {
530+ this.kernel.incrementTicks(2)
531+ await this.kernel.send(m.fromPort, new Message({
532+ resources: {
533+ priority: 100
534+ },
535+ data: 'second'
536+ }))
537+ }
538+ }
539+
540+ const hypervisor = new Hypervisor({
541+ dag: node.dag
542+ })
543+
544+ hypervisor.registerContainer('root', Root)
545+ hypervisor.registerContainer('first', First)
546+ hypervisor.registerContainer('second', Second)
547+
548+ const root = await hypervisor.createInstance('root')
549+ const port = await root.createPort('root', 'first')
550+ await root.send(port, new Message())
551+ })
552+
553+ tape('should order parent messages correctly', async t => {
554+ class Middle extends BaseContainer {
555+ async run (m) {
556+ if (!this.runs) {
557+ this.runs = 1
558+ this.kernel.incrementTicks(1)
559+ const leaf = this.kernel.createPort('leaf', 'leaf')
560+ await this.kernel.send(leaf, new Message())
561+ } else {
562+ ++this.runs
563+ if (this.runs === 3) {
564+ t.equals(m.data, 'first')
565+ }
566+ }
567+ }
568+ }
569+
570+ class Leaf extends BaseContainer {
571+ async run (m) {
572+ this.kernel.incrementTicks(2)
573+ await this.kernel.send(m.fromPort, new Message({
574+ data: 'first'
575+ }))
576+ }
577+ }
578+
579+ const hypervisor = new Hypervisor({
580+ dag: node.dag
581+ })
582+
583+ hypervisor.registerContainer('root', BaseContainer)
584+ hypervisor.registerContainer('middle', Middle)
585+ hypervisor.registerContainer('leaf', Leaf)
586+
587+ const root = await hypervisor.createInstance('root')
588+ root.incrementTicks(2)
589+ const port = await root.createPort('middle', 'first')
590+
591+ await root.send(port, new Message())
592+ await root.send(port, new Message())
593+
594+ await root.wait(Infinity)
595+
596+ t.end()
227597 node.stop(() => {
228598 process.exit()
229599 })
230600 })

Built with git-ssb-web