git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 4f8ba9e911f6ad620fc6cd59cc15fbfaa1fe384c

cleanup reverts and added tests for reverts

wanderer committed on 5/9/2017, 7:53:19 PM
Parent: 99abd38a5b872b13ce3d020a5947a5325c6c13f4

Files changed

kernel.jschanged
package.jsonchanged
portManager.jschanged
tests/index.jschanged
kernel.jsView
@@ -1,7 +1,9 @@
11 const PriorityQueue = require('fastpriorityqueue')
2+const clearObject = require('object-clear')
3+const clone = require('clone')
4+const BN = require('bn.js')
25 const EventEmitter = require('events')
3-const BN = require('bn.js')
46 const PortManager = require('./portManager.js')
57
68 module.exports = class Kernel extends EventEmitter {
79 constructor (opts) {
@@ -53,58 +55,37 @@
5355 this.emit(vmState, message)
5456 }
5557
5658 async _runNextMessage () {
57- await this.hypervisor.graph.get(this.entryPort, 'id')
5859 const message = await this.ports.getNextMessage()
59- // if the vm is paused and it gets a message; save that message for use when the VM is resumed
60- if (message && this.vmState === 'paused') {
61- this.ports._portMap(message._fromPort).unshfit(message)
62- } else if (!message && this.vmState !== 'paused') {
60+ if (message) {
61+ // run the next message
62+ this.run(message)
63+ } else {
6364 // if no more messages then shut down
6465 this._updateVmState('idle')
65- } else {
66- // run the next message
67- this._run(message)
6866 }
6967 }
7068
71- _updateEntryPort (entryPort) {
72- // reset waits, update parent port
73- }
74-
75- destroy () {
76- // destory waits
77- }
78-
79- pause () {
80- this._setState('paused')
81- }
82-
83- resume () {
84- this._setState('running')
85- this._runNextMessage()
86- }
87-
8869 /**
8970 * run the kernels code with a given enviroment
9071 * The Kernel Stores all of its state in the Environment. The Interface is used
9172 * to by the VM to retrive infromation from the Environment.
9273 */
93- async _run (message) {
94- // shallow copy
95- const oldState = Object.assign({}, this.state)
74+ async run (message) {
75+ const oldState = clone(this.state, false, 3)
9676 let result
9777 try {
9878 result = await this.vm.run(message) || {}
9979 } catch (e) {
80+ // revert the state
81+ clearObject(this.state)
82+ Object.assign(this.state, oldState)
83+
10084 result = {
10185 exception: true,
10286 exceptionError: e
10387 }
104- clearObject(this.state)
105- Object.assign(this.state, oldState)
106- console.log(e)
10788 }
10889
10990 this.emit('result', result)
11091 return result
@@ -139,12 +120,13 @@
139120 }
140121 }
141122 }
142123
143- async createPort (type, name) {
124+ createPort (type, name) {
144125 const VM = this.hypervisor._VMs[type]
145126 const parentId = this.entryPort ? this.entryPort.id : null
146- let nonce = await this.hypervisor.graph.get(this.state, 'nonce')
127+ let nonce = this.state['/'].nonce
128+
147129 const portRef = {
148130 'messages': [],
149131 'id': {
150132 '/': {
@@ -172,13 +154,7 @@
172154 message._ticks = this.ticks
173155
174156 const receiverEntryPort = portRef === this.entryPort ? this.parentPort : portRef
175157 const vm = await this.hypervisor.getInstance(receiverEntryPort)
176- return vm.queue(message)
158+ vm.queue(message)
177159 }
178160 }
179-
180-function clearObject (myObject) {
181- for (var member in myObject) {
182- delete myObject[member]
183- }
184-}
package.jsonView
@@ -26,11 +26,13 @@
2626 "contributors": "Alex Beregszaszi <alex@rtfs.hu>",
2727 "license": "MPL-2.0",
2828 "dependencies": {
2929 "bn.js": "^4.11.6",
30+ "clone": "^2.1.1",
3031 "fastpriorityqueue": "^0.2.4",
3132 "ipld-graph-builder": "1.1.5",
3233 "multibase": "^0.3.4",
34+ "object-clear": "^0.1.0",
3335 "primea-message": "0.0.0"
3436 },
3537 "devDependencies": {
3638 "coveralls": "^2.13.1",
portManager.jsView
@@ -56,20 +56,12 @@
5656 this.ports[name] = port
5757 return this._mapPort(name, port)
5858 }
5959
60- get (port) {
61- return this._portMap.get(port)
60+ get (key) {
61+ return this.ports[key]
6262 }
6363
64- getRef (key) {
65- if (key === ENTRY) {
66- return this.entryPort
67- } else {
68- return this.ports[key]
69- }
70- }
71-
7264 // waits till all ports have reached a threshold tick count
7365 wait (threshold, fromPort) {
7466 // find the ports that have a smaller tick count then the threshold tick count
7567 const unkownPorts = [...this._portMap].filter(([portRef, port]) => {
@@ -85,9 +77,8 @@
8577
8678 async getNextMessage () {
8779 await this.wait(this.kernel.ticks, this.entryPort)
8880 const portMap = [...this._portMap].reduce(messageArbiter)
89- if (portMap) {
90- return portMap[1].shift()
91- }
81+ // console.log('here!!!!', portMap)
82+ return portMap[1].shift()
9283 }
9384 }
tests/index.jsView
@@ -90,48 +90,41 @@
9090
9191 // test reviving the state
9292 class testVMContainer3 extends BaseContainer {
9393 async run (m) {
94- const port = this.kernel.ports.getRef('child')
94+ const port = this.kernel.ports.get('child')
9595 await this.kernel.send(port, m)
9696 this.kernel.incrementTicks(1)
9797 }
9898 }
9999
100100 hypervisor.registerContainer('test', testVMContainer3)
101101 root = await hypervisor.createInstance('test', stateRoot)
102- port = await root.ports.getRef('first')
102+ port = await root.ports.get('first')
103103
104104 await root.send(port, message)
105105 await hypervisor.createStateRoot(root, Infinity)
106106
107107 t.end()
108-
109- node.stop(() => {
110- process.exit()
111- })
112108 })
113109
114- tape.skip('ping pong', async t => {
110+ tape('ping pong', async t => {
115111 class Ping extends BaseContainer {
116112 async run (m) {
117- console.log('ping')
118- let port = this.kernel.ports.getRef('child')
113+ let port = this.kernel.ports.get('child')
119114 if (!port) {
120115 port = await this.kernel.createPort('pong', 'child')
121116 }
122117
123118 if (this.kernel.ticks < 100) {
124119 this.kernel.incrementTicks(1)
125- console.log('here')
126120 return this.kernel.send(port, new Message())
127121 }
128122 }
129123 }
130124
131125 class Pong extends BaseContainer {
132126 run (m) {
133- console.log('pong')
134127 const port = m.fromPort
135128 return this.kernel.send(port, new Message())
136129 }
137130 }
@@ -139,16 +132,100 @@
139132 const hypervisor = new Hypervisor({
140133 dag: node.dag
141134 })
142135
143- try {
144- hypervisor.registerContainer('ping', Ping)
145- hypervisor.registerContainer('pong', Pong)
146- const root = await hypervisor.createInstance('pong')
147- const port = await root.createPort('ping', 'child')
136+ hypervisor.registerContainer('ping', Ping)
137+ hypervisor.registerContainer('pong', Pong)
138+ const root = await hypervisor.createInstance('pong')
139+ const port = await root.createPort('ping', 'child')
148140
149- await root.send(port, new Message())
150- } catch (e) {
151- console.log(e)
141+ await root.send(port, new Message())
142+ await hypervisor.createStateRoot(root, Infinity)
143+
144+ t.end()
145+ })
146+
147+ tape('queing multiple messages', async t => {
148+ let runs = 0
149+
150+ class Root extends BaseContainer {
151+ async run (m) {
152+ const one = this.kernel.createPort('child', 'one')
153+ const two = this.kernel.createPort('child', 'two')
154+ const three = this.kernel.createPort('child', 'three')
155+
156+ await Promise.all([
157+ this.kernel.send(one, new Message()),
158+ this.kernel.send(two, new Message()),
159+ this.kernel.send(three, new Message())
160+ ])
161+
162+ this.kernel.incrementTicks(1)
163+ }
152164 }
165+
166+ class Child extends BaseContainer {
167+ run (m) {
168+ return new Promise((resolve, reject) => {
169+ setTimeout(() => {
170+ runs++
171+ this.kernel.incrementTicks(2)
172+ resolve()
173+ }, 200)
174+ })
175+ }
176+ }
177+
178+ const hypervisor = new Hypervisor({
179+ dag: node.dag
180+ })
181+
182+ hypervisor.registerContainer('root', Root)
183+ hypervisor.registerContainer('child', Child)
184+
185+ const root = await hypervisor.createInstance('root')
186+ const port = await root.createPort('root', 'first')
187+ await root.send(port, new Message())
188+ await root.wait(Infinity)
189+
190+ t.equals(runs, 3, 'the number of run should be 3')
191+ const nonce = await hypervisor.graph.get(root.state, 'ports/first/link/nonce/0')
192+ t.equals(nonce, 3, 'should have the correct nonce')
193+
194+ t.end()
153195 })
196+
197+ tape('traps', async t => {
198+ class Root extends BaseContainer {
199+ async run (m) {
200+ await Promise.all([
201+ this.kernel.createPort('root', 'one'),
202+ this.kernel.createPort('root', 'two'),
203+ this.kernel.createPort('root', 'three')
204+ ])
205+
206+ throw new Error('it is a trap!!!')
207+ }
208+ }
209+
210+ const hypervisor = new Hypervisor({
211+ dag: node.dag
212+ })
213+
214+ hypervisor.registerContainer('root', Root)
215+ const root = await hypervisor.createInstance('root')
216+ await root.run()
217+
218+ t.deepEquals(root.state, {
219+ '/': {
220+ nonce: [0],
221+ ports: {}
222+ }
223+ }, 'should revert the state')
224+
225+ t.end()
226+
227+ node.stop(() => {
228+ process.exit()
229+ })
230+ })
154231 })

Built with git-ssb-web