This repository has been archived by the owner on Aug 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
/
dsl.js
135 lines (120 loc) · 4.19 KB
/
dsl.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Bit of test cases for testing stuff with a internal DSL rather than imperative code
const assert = require('assert')
const DaemonFactory = require('ipfsd-ctl')
// This is what an actual test case looks like
const combinations = ['go', 'js']
test('send and receive pubsub message', combinations, (done, nodes) => {
const nodeA = nodes[0]
const nodeB = nodes[0]
const msg = createMessage()
nodeA.subscribe(done)
nodeB.publish(msg)
}, assertRightMessage)
// End of test case
// Code below here wouldn't actually be written in the tests like this, but
// put away in it's own file
// Assertion function for making sure we're getting the right message
function assertRightMessage (nodes, msg) {
assert.strictEqual(msg.data.toString(), 'hello world')
assert.strictEqual(msg.topicIDs.length, 1)
assert.strictEqual(msg.topicIDs[0], nodes[0].getPubsubTopic())
console.log('Made assertions')
}
// Abstracted data structure for pubsub messages
function createMessage () {
return Buffer.from('hello world')
}
// Creates a node of a specific type
function createNode (type) {
return new Promise((resolve, reject) => {
DaemonFactory.create({
type: type,
disposable: true
}).spawn({
args: ['--enable-pubsub-experiment']
}, (err, res) => {
if (err) return reject(err)
resolve(res)
})
})
}
// creates a testing api for a node
// here we can do things like generate a special pubsub topic per node
function makeNodeInterface (node) {
const isolatedPubsubTopic = 'randomtest'
let publishInterval
return {
// This could be used by other nodes to make sure we're getting the right topic
getPubsubTopic: function () {
return isolatedPubsubTopic
},
subscribe: function (assertion) {
return node.api.pubsub.subscribe(isolatedPubsubTopic, function () {
clearInterval(publishInterval)
assertion(...arguments)
})
},
publish: function (msg) {
// We put this under a loop because we might have sent the message before
// the subscription was really setup. We should do this with functions
// that might be called before a condition is what we want it to be
publishInterval = setInterval(() => {
console.log('publishing message')
node.api.pubsub.publish(isolatedPubsubTopic, msg)
}, 500)
},
stop: function () {
return node.stop()
}
}
}
// Creates a node, adds the testing interface and returns it
async function getNode (type) {
return makeNodeInterface(await createNode(type))
}
// test(testName, combinations, arrangeFunc, assertFunc)
//
// testName is just visual, prints the title + current combination
//
// combinations is a array of implementations to test
//
// arrangeFunc sets up the test and does everything needed to get the data which
// we can assert on
//
// assertFunc gets called after tests to make assertions on the data from the
// arrangeFunc. Should be able to handle arrays as well
async function test (title, combs, arrangeFunc, assertFunc) {
const cases = []
// This is a horrible way of generating the cases, but is what I could come
// up with quickly
cases.push([combs[0], combs[0]])
cases.push([combs[1], combs[1]])
cases.push([combs[0], combs[1]])
cases.push([combs[1], combs[0]])
for (const c of cases) {
const wantedNodeA = c[0]
const wantedNodeB = c[1]
console.log(`## ${title} - ${wantedNodeA} <> ${wantedNodeB}`)
const nodeA = await getNode(wantedNodeA)
const nodeB = await getNode(wantedNodeB)
const nodes = [nodeA, nodeB]
// Wrap the test in a promise, because tests are not always finished when
// we've run all the top level statements. For example, pubsub tests are
// finished when we received a message. DHT tests are finished once we've
// got a reply to a query
const done = new Promise((resolve) => {
// Call the arrangeFunc to "arrange" the test
arrangeFunc((res) => {
// When test is signaling it's done, run assert function
assertFunc(nodes, res)
// Once assertions are done, tests are done
resolve()
}, nodes)
})
// Wait for tests to finish
await done
// Good'ol cleanup
await nodeA.stop()
await nodeB.stop()
}
}