Files: 6b20ce6345f5cf4e554a3d7b67876db977eb8070 / tests / index.js
12965 bytesRaw
1 | const tape = require('tape') |
2 | const IPFS = require('ipfs') |
3 | const Hypervisor = require('../') |
4 | |
5 | // start ipfs |
6 | const node = new IPFS({ |
7 | start: false |
8 | }) |
9 | |
10 | class BaseContainer { |
11 | constructor (exInterface) { |
12 | this.exInterface = exInterface |
13 | } |
14 | |
15 | initailize (message) { |
16 | const port = message.ports[0] |
17 | if (port) { |
18 | this.exInterface.ports.bind('root', port) |
19 | } |
20 | } |
21 | } |
22 | |
23 | node.on('ready', () => { |
24 | tape('basic', async t => { |
25 | t.plan(2) |
26 | let message |
27 | const expectedState = { |
28 | '/': 'zdpuAyGKaZ3nbBQdgESbEgVYr81TcAFB6LE2MQQPWLZaYxuF3' |
29 | } |
30 | |
31 | class testVMContainer extends BaseContainer { |
32 | run (m) { |
33 | t.true(m === message, 'should recive a message') |
34 | } |
35 | } |
36 | |
37 | const hypervisor = new Hypervisor(node.dag) |
38 | hypervisor.registerContainer('test', testVMContainer) |
39 | |
40 | const rootContainer = await hypervisor.createInstance('test') |
41 | const port = rootContainer.ports.create('test') |
42 | message = rootContainer.createMessage() |
43 | rootContainer.ports.bind('first', port) |
44 | rootContainer.send(port, message) |
45 | |
46 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
47 | t.deepEquals(stateRoot, expectedState, 'expected root!') |
48 | }) |
49 | |
50 | tape('one child contract', async t => { |
51 | t.plan(4) |
52 | let message |
53 | const expectedState = { |
54 | '/': 'zdpuAtVcH6MUnvt2RXnLsDXyLB3CBSQ7aydfh2ogSKGCejJCQ' |
55 | } |
56 | let hasResolved = false |
57 | |
58 | class testVMContainer2 extends BaseContainer { |
59 | run (m) { |
60 | t.true(m === message, 'should recive a message') |
61 | return new Promise((resolve, reject) => { |
62 | setTimeout(() => { |
63 | this.exInterface.incrementTicks(1) |
64 | hasResolved = true |
65 | resolve() |
66 | }, 200) |
67 | }) |
68 | } |
69 | } |
70 | |
71 | class testVMContainer extends BaseContainer { |
72 | run (m) { |
73 | const port = this.exInterface.ports.create('test2') |
74 | this.exInterface.ports.bind('child', port) |
75 | this.exInterface.send(port, m) |
76 | this.exInterface.incrementTicks(1) |
77 | } |
78 | } |
79 | |
80 | const hypervisor = new Hypervisor(node.dag) |
81 | hypervisor.registerContainer('test', testVMContainer) |
82 | hypervisor.registerContainer('test2', testVMContainer2) |
83 | |
84 | let root = await hypervisor.createInstance('test') |
85 | const rootId = root.id |
86 | let port = root.ports.create('test') |
87 | |
88 | root.ports.bind('first', port) |
89 | message = root.createMessage() |
90 | |
91 | root.send(port, message) |
92 | const stateRoot = await hypervisor.createStateRoot(Infinity) |
93 | t.true(hasResolved, 'should resolve before generating the state root') |
94 | t.deepEquals(stateRoot, expectedState, 'expected state') |
95 | // await hypervisor.graph.tree(hypervisor._state, Infinity) |
96 | // console.log(JSON.stringify(hypervisor._state, null, 2)) |
97 | // test reviving the state |
98 | class testVMContainer3 extends BaseContainer { |
99 | run (m) { |
100 | const port = this.exInterface.ports.get('child') |
101 | this.exInterface.send(port, m) |
102 | this.exInterface.incrementTicks(1) |
103 | } |
104 | } |
105 | |
106 | hypervisor.registerContainer('test', testVMContainer3) |
107 | root = await hypervisor.getInstance(rootId) |
108 | port = root.ports.get('first') |
109 | root.send(port, message) |
110 | }) |
111 | |
112 | tape.skip('ping pong', async t => { |
113 | class Ping extends BaseContainer { |
114 | async run (m) { |
115 | let port = this.exInterface.ports.get('child') |
116 | if (!port) { |
117 | port = this.exInterface.ports.create('pong') |
118 | this.exInterface.ports.bind(port, 'child') |
119 | } |
120 | |
121 | if (this.exInterface.ticks < 100) { |
122 | this.exInterface.incrementTicks(1) |
123 | return this.exInterface.send(port, this.exInterface.createMessage()) |
124 | } |
125 | } |
126 | } |
127 | |
128 | class Pong extends BaseContainer { |
129 | run (m) { |
130 | const port = m.fromPort |
131 | this.exInterface.incrementTicks(2) |
132 | return this.exInterface.send(port, this.exInterface.createMessage()) |
133 | } |
134 | } |
135 | |
136 | const hypervisor = new Hypervisor(node.dag) |
137 | |
138 | hypervisor.registerContainer('ping', Ping) |
139 | hypervisor.registerContainer('pong', Pong) |
140 | const root = await hypervisor.createInstance('pong') |
141 | const port = root.ports.create('ping') |
142 | root.ports.bind(port, 'child') |
143 | |
144 | await root.send(port, root.createMessage()) |
145 | await hypervisor.createStateRoot(root, Infinity) |
146 | |
147 | t.end() |
148 | }) |
149 | |
150 | tape('traps', async t => { |
151 | t.plan(1) |
152 | class Root extends BaseContainer { |
153 | async run (m) { |
154 | const one = this.exInterface.ports.create('root') |
155 | const two = this.exInterface.ports.create('root') |
156 | const three = this.exInterface.ports.create('root') |
157 | |
158 | this.exInterface.ports.bind('one', one) |
159 | this.exInterface.ports.bind('two', two) |
160 | this.exInterface.ports.bind('three', three) |
161 | |
162 | throw new Error('it is a trap!!!') |
163 | } |
164 | } |
165 | |
166 | const hypervisor = new Hypervisor(node.dag) |
167 | |
168 | hypervisor.registerContainer('root', Root) |
169 | const root = await hypervisor.createInstance('root') |
170 | await root.run(root.createMessage()) |
171 | // console.log('here', hypervisor.scheduler) |
172 | const stateRoot = await hypervisor.createStateRoot() |
173 | |
174 | t.deepEquals(stateRoot, { |
175 | '/': 'zdpuAwrMmQXqFusve7zcRYxVUuji4NVzZR5GyjwyStsjteCoW' |
176 | }, 'should revert the state') |
177 | }) |
178 | |
179 | tape('message should arrive in the correct oder if sent in order', async t => { |
180 | t.plan(2) |
181 | let runs = 0 |
182 | |
183 | class Root extends BaseContainer { |
184 | run (m) { |
185 | if (!runs) { |
186 | runs++ |
187 | const one = this.exInterface.ports.create('first') |
188 | const two = this.exInterface.ports.create('second') |
189 | |
190 | this.exInterface.ports.bind('one', one) |
191 | this.exInterface.ports.bind('two', two) |
192 | |
193 | this.exInterface.send(one, this.exInterface.createMessage()) |
194 | this.exInterface.send(two, this.exInterface.createMessage()) |
195 | |
196 | } else if (runs === 1) { |
197 | runs++ |
198 | t.equals(m.data, 'second', 'should recived the second message') |
199 | } else if (runs === 2) { |
200 | t.equals(m.data, 'first', 'should recive the first message') |
201 | } |
202 | } |
203 | } |
204 | |
205 | class First extends BaseContainer { |
206 | run (m) { |
207 | this.exInterface.incrementTicks(2) |
208 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'first'})) |
209 | } |
210 | } |
211 | |
212 | class Second extends BaseContainer { |
213 | run (m) { |
214 | this.exInterface.incrementTicks(1) |
215 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'second'})) |
216 | } |
217 | } |
218 | |
219 | const hypervisor = new Hypervisor(node.dag) |
220 | |
221 | hypervisor.registerContainer('root', Root) |
222 | hypervisor.registerContainer('first', First) |
223 | hypervisor.registerContainer('second', Second) |
224 | |
225 | const root = await hypervisor.createInstance('root') |
226 | const port = root.ports.create('root') |
227 | root.ports.bind('first', port) |
228 | |
229 | root.send(port, root.createMessage()) |
230 | }) |
231 | |
232 | tape('message should arrive in the correct oder if sent in order', async t => { |
233 | t.plan(2) |
234 | let runs = 0 |
235 | |
236 | class Root extends BaseContainer { |
237 | run (m) { |
238 | if (!runs) { |
239 | runs++ |
240 | const one = this.exInterface.ports.create('first') |
241 | const two = this.exInterface.ports.create('second') |
242 | |
243 | this.exInterface.ports.bind('one', one) |
244 | this.exInterface.ports.bind('two', two) |
245 | |
246 | this.exInterface.send(one, this.exInterface.createMessage()) |
247 | this.exInterface.send(two, this.exInterface.createMessage()) |
248 | |
249 | this.exInterface.incrementTicks(6) |
250 | } else if (runs === 1) { |
251 | runs++ |
252 | t.equals(m.data, 'first', 'should recive the first message') |
253 | } else if (runs === 2) { |
254 | t.equals(m.data, 'second', 'should recived the second message') |
255 | } |
256 | } |
257 | } |
258 | |
259 | class First extends BaseContainer { |
260 | run (m) { |
261 | this.exInterface.incrementTicks(1) |
262 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'first'})) |
263 | } |
264 | } |
265 | |
266 | class Second extends BaseContainer { |
267 | run (m) { |
268 | this.exInterface.incrementTicks(2) |
269 | this.exInterface.send(m.fromPort, this.exInterface.createMessage({data: 'second'})) |
270 | } |
271 | } |
272 | |
273 | const hypervisor = new Hypervisor(node.dag) |
274 | |
275 | hypervisor.registerContainer('root', Root) |
276 | hypervisor.registerContainer('first', First) |
277 | hypervisor.registerContainer('second', Second) |
278 | |
279 | const root = await hypervisor.createInstance('root') |
280 | const port = root.ports.create('root') |
281 | root.ports.bind('first', port) |
282 | |
283 | root.send(port, root.createMessage()) |
284 | }) |
285 | |
286 | tape('message should arrive in the correct order, even in a tie of ticks', async t => { |
287 | t.plan(2) |
288 | |
289 | let runs = 0 |
290 | |
291 | class Root extends BaseContainer { |
292 | run (m) { |
293 | if (!runs) { |
294 | runs++ |
295 | const one = this.exInterface.ports.create('first') |
296 | const two = this.exInterface.ports.create('second') |
297 | |
298 | this.exInterface.ports.bind('two', two) |
299 | this.exInterface.ports.bind('one', one) |
300 | |
301 | this.exInterface.send(one, this.exInterface.createMessage()) |
302 | this.exInterface.send(two, this.exInterface.createMessage()) |
303 | |
304 | this.exInterface.incrementTicks(6) |
305 | } else if (runs === 1) { |
306 | runs++ |
307 | t.equals(m.data, 'second', 'should recived the second message') |
308 | } else if (runs === 2) { |
309 | t.equals(m.data, 'first', 'should recive the first message') |
310 | } |
311 | } |
312 | } |
313 | |
314 | class First extends BaseContainer { |
315 | run (m) { |
316 | this.exInterface.incrementTicks(2) |
317 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
318 | data: 'first' |
319 | })) |
320 | } |
321 | } |
322 | |
323 | class Second extends BaseContainer { |
324 | run (m) { |
325 | this.exInterface.incrementTicks(2) |
326 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
327 | data: 'second' |
328 | })) |
329 | } |
330 | } |
331 | |
332 | const hypervisor = new Hypervisor(node.dag) |
333 | |
334 | hypervisor.registerContainer('root', Root) |
335 | hypervisor.registerContainer('first', First) |
336 | hypervisor.registerContainer('second', Second) |
337 | |
338 | const root = await hypervisor.createInstance('root') |
339 | |
340 | const port = root.ports.create('root') |
341 | root.ports.bind('first', port) |
342 | |
343 | root.send(port, root.createMessage()) |
344 | }) |
345 | |
346 | tape('message should arrive in the correct order, with a tie in ticks but with differnt proity', async t => { |
347 | t.plan(2) |
348 | |
349 | let runs = 0 |
350 | |
351 | class Root extends BaseContainer { |
352 | run (m) { |
353 | if (!runs) { |
354 | runs++ |
355 | const one = this.exInterface.ports.create('first') |
356 | const two = this.exInterface.ports.create('second') |
357 | |
358 | this.exInterface.ports.bind('one', one) |
359 | this.exInterface.ports.bind('two', two) |
360 | |
361 | this.exInterface.send(two, this.exInterface.createMessage()) |
362 | this.exInterface.send(one, this.exInterface.createMessage()) |
363 | |
364 | this.exInterface.incrementTicks(6) |
365 | } else if (runs === 1) { |
366 | runs++ |
367 | t.equals(m.data, 'first', 'should recive the first message') |
368 | } else if (runs === 2) { |
369 | t.equals(m.data, 'second', 'should recived the second message') |
370 | } |
371 | } |
372 | } |
373 | |
374 | class First extends BaseContainer { |
375 | run (m) { |
376 | this.exInterface.incrementTicks(2) |
377 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
378 | resources: { |
379 | priority: 100 |
380 | }, |
381 | data: 'first' |
382 | })) |
383 | } |
384 | } |
385 | |
386 | class Second extends BaseContainer { |
387 | run (m) { |
388 | this.exInterface.incrementTicks(2) |
389 | return this.exInterface.send(m.fromPort, this.exInterface.createMessage({ |
390 | data: 'second' |
391 | })) |
392 | } |
393 | } |
394 | |
395 | const hypervisor = new Hypervisor(node.dag) |
396 | |
397 | hypervisor.registerContainer('root', Root) |
398 | hypervisor.registerContainer('first', First) |
399 | hypervisor.registerContainer('second', Second) |
400 | |
401 | const root = await hypervisor.createInstance('root') |
402 | const port = root.ports.create('root') |
403 | root.ports.bind('first', port) |
404 | root.send(port, root.createMessage()) |
405 | }) |
406 | |
407 | tape('checking ports', async t => { |
408 | t.plan(4) |
409 | const hypervisor = new Hypervisor(node.dag) |
410 | hypervisor.registerContainer('base', BaseContainer) |
411 | |
412 | const root = await hypervisor.createInstance('base') |
413 | let port = root.ports.create('base') |
414 | await root.ports.bind('test', port) |
415 | |
416 | try { |
417 | root.createMessage({ |
418 | ports: [port] |
419 | }) |
420 | } catch (e) { |
421 | t.pass('should thow if sending a port that is bound') |
422 | } |
423 | |
424 | try { |
425 | await root.ports.bind('test', port) |
426 | } catch (e) { |
427 | t.pass('should thow if binding an already bound port') |
428 | } |
429 | |
430 | try { |
431 | let port2 = root.ports.create('base') |
432 | await root.ports.bind('test', port2) |
433 | } catch (e) { |
434 | t.pass('should thow if binding an already bound name') |
435 | } |
436 | |
437 | await root.ports.unbind('test') |
438 | const message = root.createMessage({ports: [port]}) |
439 | t.equals(message.ports[0], port, 'should create a message if the port is unbound') |
440 | }) |
441 | }) |
442 |
Built with git-ssb-web