Skip to content

Commit

Permalink
Merge 34ec668 into 387738d
Browse files Browse the repository at this point in the history
  • Loading branch information
wanderer committed Aug 8, 2017
2 parents 387738d + 34ec668 commit 4c11e10
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 52 deletions.
8 changes: 2 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
language: node_js
node_js:
- "7"
env:
global:
- CXX=g++-4.8
matrix:
- TEST_SUITE=test
addons:
apt:
sources:
Expand All @@ -16,9 +12,9 @@ matrix:
fast_finish: true
include:
- os: linux
node_js: "7"
node_js: "8"
env: TEST_SUITE=coveralls
- os: linux
node_js: "7"
node_js: "8"
env: TEST_SUITE=lint
script: npm run $TEST_SUITE
4 changes: 2 additions & 2 deletions dfsChecker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @param {string} root - the root id
* @param {Set} nodes - a set of nodes to start searching from
*/
module.exports = async function DFSchecker (graph, state, root, nodes) {
module.exports = async function DFSchecker (tree, root, nodes) {
const checkedNodesSet = new Set()
let hasRootSet = new Set()
const promises = []
Expand Down Expand Up @@ -59,7 +59,7 @@ module.exports = async function DFSchecker (graph, state, root, nodes) {
return
}

const node = state[id]['/']
const node = await tree.get(id)
const promises = []
// iterate through the nodes ports and recursivly check them
for (const name in node.ports) {
Expand Down
22 changes: 14 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const Tree = require('merkle-radix-tree')
const Graph = require('ipld-graph-builder')
const chunk = require('chunk')
const Message = require('primea-message')
const Kernel = require('./kernel.js')
const Scheduler = require('./scheduler.js')
const DFSchecker = require('./dfsChecker.js')
const chunk = require('chunk')

module.exports = class Hypervisor {
/**
Expand All @@ -12,8 +13,12 @@ module.exports = class Hypervisor {
* @param {Graph} dag an instance of [ipfs.dag](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dag-api)
* @param {object} state - the starting state
*/
constructor (dag, state = {}) {
constructor (dag, state = {'/': Tree.emptyTreeState}) {
this.graph = new Graph(dag)
this.tree = new Tree({
graph: this.graph,
root: state
})
this.scheduler = new Scheduler()
this.state = state
this._containerTypes = {}
Expand All @@ -36,11 +41,12 @@ module.exports = class Hypervisor {
* @param {object} port
* @returns {Promise}
*/
getDestPort (port) {
async getDestPort (port) {
if (port.destPort) {
return port.destPort
} else {
return this.graph.get(this.state, `${port.destId}/ports/${port.destName}`)
const containerState = await this.tree.get(port.destId)
return this.graph.get(containerState, `ports/${port.destName}`)
}
}

Expand All @@ -57,7 +63,7 @@ module.exports = class Hypervisor {

// loads an instance of a container from the state
async _loadInstance (id) {
const state = await this.graph.get(this.state, id)
const state = await this.tree.get(id)
const container = this._containerTypes[state.type]
let code

Expand Down Expand Up @@ -134,7 +140,7 @@ module.exports = class Hypervisor {
}

// save the container in the state
await this.graph.set(this.state, idHash, state)
await this.tree.set(idHash, state)
// create the container instance
const instance = await this._loadInstance(idHash)
resolve(instance)
Expand All @@ -160,9 +166,9 @@ module.exports = class Hypervisor {
*/
async createStateRoot (ticks) {
await this.scheduler.wait(ticks)
const unlinked = await DFSchecker(this.graph, this.state, this.ROOT_ID, this._nodesToCheck)
const unlinked = await DFSchecker(this.tree, this.ROOT_ID, this._nodesToCheck)
unlinked.forEach(id => {
delete this.state[id]
this.tree.delete(id)
})
return this.graph.flush(this.state)
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"bn.js": "^4.11.6",
"chunk": "0.0.2",
"ipld-graph-builder": "1.3.0",
"merkle-radix-tree": "0.0.4",
"primea-message": "0.0.2"
},
"devDependencies": {
Expand Down
104 changes: 68 additions & 36 deletions tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const IPFS = require('ipfs')
const AbstractContainer = require('primea-abstract-container')
const Message = require('primea-message')
const Hypervisor = require('../')
console.log(test())

// start ipfs
const node = new IPFS({
Expand All @@ -27,7 +28,7 @@ node.on('ready', () => {
t.plan(3)
let message
const expectedState = {
'/': 'zdpuAmN9VSrvNbArWkAEhEYaKhhCT3rk8xMhUam6eUfQmr6aZ'
'/': 'zdpuAsvLUNKxnxpKxuipCJz7sH4kmHuu3gVEUEmJ1QuWnikht'
}

class testVMContainer extends BaseContainer {
Expand All @@ -36,58 +37,69 @@ node.on('ready', () => {
}
}

const hypervisor = new Hypervisor(node.dag)
hypervisor.registerContainer(testVMContainer)
try {
const hypervisor = new Hypervisor(node.dag)
hypervisor.registerContainer(testVMContainer)

const rootContainer = await hypervisor.createInstance(testVMContainer.typeId)
const rootContainer = await hypervisor.createInstance(testVMContainer.typeId)

const [portRef1, portRef2] = rootContainer.ports.createChannel()
const initMessage = rootContainer.createMessage({
data: Buffer.from('test code'),
ports: [portRef2]
})
const [portRef1, portRef2] = rootContainer.ports.createChannel()
const initMessage = rootContainer.createMessage({
data: Buffer.from('test code'),
ports: [portRef2]
})

rootContainer.createInstance(testVMContainer.typeId, initMessage)
rootContainer.createInstance(testVMContainer.typeId, initMessage)

rootContainer.ports.bind('first', portRef1)
message = rootContainer.createMessage()
rootContainer.send(portRef1, message)
rootContainer.ports.bind('first', portRef1)
message = rootContainer.createMessage()
rootContainer.send(portRef1, message)

const stateRoot = await hypervisor.createStateRoot(Infinity)
t.deepEquals(stateRoot, expectedState, 'expected root!')
t.equals(hypervisor.scheduler.oldest(), 0)
const stateRoot = await hypervisor.createStateRoot(Infinity)
t.deepEquals(stateRoot, expectedState, 'expected root!')
t.equals(hypervisor.scheduler.oldest(), 0)
} catch (e) {
console.log(e)
}
})

tape('basic - do not store containers with no ports bound', async t => {
t.plan(1)
const expectedState = {
'/': 'zdpuAxGvPHM4DRbq7GeyGjwuPA8NT7DZLszcDDX9R5iwHWnTo'
'/': 'zdpuAop4nt8pqzg7duciSYbZmWfDaBiz87RCtGCbb35ewUrbW'
}

class testVMContainer extends BaseContainer {
onCreation () {}
}

const hypervisor = new Hypervisor(node.dag)
hypervisor.registerContainer(testVMContainer)
try {
const hypervisor = new Hypervisor(node.dag)
hypervisor.registerContainer(testVMContainer)

const root = await hypervisor.createInstance(testVMContainer.typeId)
const [portRef1, portRef2] = root.ports.createChannel()
const root = await hypervisor.createInstance(testVMContainer.typeId)
const [portRef1, portRef2] = root.ports.createChannel()

root.ports.bind('one', portRef1)
root.createInstance(testVMContainer.typeId, root.createMessage({
ports: [portRef2]
}))
root.ports.bind('one', portRef1)
root.createInstance(testVMContainer.typeId, root.createMessage({
ports: [portRef2]
}))

const stateRoot = await hypervisor.createStateRoot(Infinity)
t.deepEquals(stateRoot, expectedState, 'expected root!')
const stateRoot = await hypervisor.createStateRoot(Infinity)

// await hypervisor.graph.tree(stateRoot, Infinity, true)
// console.log(JSON.stringify(stateRoot, null, 2))
t.deepEquals(stateRoot, expectedState, 'expected root!')
} catch (e) {
console.log(e)
}
})

tape('one child contract with saturated ports', async t => {
t.plan(2)
let message
const expectedState = {
'/': 'zdpuAvWT2E1Hg6cvFNLTDbmjGRLSDbMnRtrA6s17oSdBX5EWs'
'/': 'zdpuAnfZ1fGUSzNwAovfArzcTfEVbXjVYABprgtjUKMtGb8k5'
}

class testVMContainer2 extends BaseContainer {
Expand Down Expand Up @@ -128,14 +140,15 @@ node.on('ready', () => {

root.send(portRef1, message)
const stateRoot = await hypervisor.createStateRoot(Infinity)

t.deepEquals(stateRoot, expectedState, 'expected state')
})

tape('one child contract', async t => {
t.plan(4)
let message
const expectedState = {
'/': 'zdpuAvWT2E1Hg6cvFNLTDbmjGRLSDbMnRtrA6s17oSdBX5EWs'
'/': 'zdpuArCqpDZtEqjrXrRhMiYLE7QQ1szVr1qLVkiwtDLincGWU'
}
let hasResolved = false

Expand Down Expand Up @@ -185,6 +198,9 @@ node.on('ready', () => {
root.send(portRef1, message)
const stateRoot = await hypervisor.createStateRoot(Infinity)
t.true(hasResolved, 'should resolve before generating the state root')

// await hypervisor.graph.tree(stateRoot, Infinity, true)
// console.log(JSON.stringify(stateRoot, null, 2))
t.deepEquals(stateRoot, expectedState, 'expected state')

// test reviving the state
Expand All @@ -203,7 +219,6 @@ node.on('ready', () => {
})

tape('traps', async t => {
t.plan(1)
class Root extends BaseContainer {
async onMessage (m) {
const [portRef1, portRef2] = this.kernel.ports.createChannel()
Expand Down Expand Up @@ -240,8 +255,13 @@ node.on('ready', () => {
const stateRoot = await hypervisor.createStateRoot()

t.deepEquals(stateRoot, {
'/': 'zdpuAwxK8kAM3SkxSyALurpFHTobp6sFJef9gZJ8ZDQRww1LN'
'/': 'zdpuAtChoDT1Er7c9Ndv6ov4m46wibCNY1HKthoVLUn5n4Rg5'
}, 'should revert the state')

await hypervisor.graph.tree(stateRoot, Infinity, true)
console.log(JSON.stringify(stateRoot, null, 2))

t.end()
})

tape('message should arrive in the correct oder if sent in order', async t => {
Expand Down Expand Up @@ -846,7 +866,7 @@ node.on('ready', () => {

tape('port deletion', async t => {
const expectedSr = {
'/': 'zdpuAqFMWKsATaU1gJwMTegcw18GFQ7szZix3QNgMN2sYm2vh'
'/': 'zdpuAopMy53q2uvL2a4fhVEAvwXjSDW28fh8zhQUj598tb5md'
}
class Root extends BaseContainer {
onMessage (m) {
Expand Down Expand Up @@ -889,13 +909,14 @@ node.on('ready', () => {

const sr = await hypervisor.createStateRoot()
t.deepEquals(sr, expectedSr, 'should produce the corret state root')
await hypervisor.graph.tree(sr, Infinity, true)

t.end()
})

tape('clear unbounded ports', async t => {
const expectedSr = {
'/': 'zdpuAqFMWKsATaU1gJwMTegcw18GFQ7szZix3QNgMN2sYm2vh'
'/': 'zdpuAxVzUQRWaAeFWXq5TgDpZqPaNgNp1ZuEfxbxg7h4qnXmC'
}
class Root extends BaseContainer {
onMessage (m) {
Expand Down Expand Up @@ -924,7 +945,7 @@ node.on('ready', () => {

tape('should remove subgraphs', async t => {
const expectedSr = {
'/': 'zdpuAqFMWKsATaU1gJwMTegcw18GFQ7szZix3QNgMN2sYm2vh'
'/': 'zdpuAopMy53q2uvL2a4fhVEAvwXjSDW28fh8zhQUj598tb5md'
}
class Root extends BaseContainer {
onMessage (m) {
Expand Down Expand Up @@ -970,7 +991,7 @@ node.on('ready', () => {

tape('should not remove connected nodes', async t => {
const expectedSr = {
'/': 'zdpuAppPTaXwHnfU2yjtTyT9XsY7SJAkDwQWUZnkHU7myRzaj'
'/': 'zdpuApKrsvsWknDML2Mme9FyZfRnVZ1hTCoKzkooYAWT3dUDV'
}
class Root extends BaseContainer {
onMessage (m) {
Expand Down Expand Up @@ -1037,7 +1058,7 @@ node.on('ready', () => {

tape('should remove multiple subgraphs', async t => {
const expectedSr = {
'/': 'zdpuAvQqoEnojZHaw6dMDy8ACRVqfarfD2RCKTwFBYsj8suRC'
'/': 'zdpuAo1qZHhS6obxbGbtvnUxkbAxA6VSbcjYiiTVNWTm37xQv'
}
class Root extends BaseContainer {
onMessage (m) {
Expand Down Expand Up @@ -1173,3 +1194,14 @@ node.on('ready', () => {
t.equals(content.length, instance.code.length)
})
})

function test () {
var arrayBuffer = new ArrayBuffer(2);
var uint8Array = new Uint8Array(arrayBuffer);
var uint16array = new Uint16Array(arrayBuffer);
uint8Array[0] = 0xAA; // set first byte
uint8Array[1] = 0xBB; // set second byte
if(uint16array[0] === 0xBBAA) return "little endian";
if(uint16array[0] === 0xAABB) return "big endian";
else throw new Error("Something crazy just happened");
}

0 comments on commit 4c11e10

Please sign in to comment.