Skip to content

Commit c747374

Browse files
BFergersonMrMineO5
andauthored
test: simple primitives (#4)
* test: simple primitives * test: dynamic line numbers * test * already impl'd * refactor * Restructure tests * refactor * Fix TestUtils.getFilename * test: collections Co-authored-by: UltraDev <petzmagnus@gmail.com>
1 parent dfbe4fe commit c747374

File tree

6 files changed

+298
-430
lines changed

6 files changed

+298
-430
lines changed

src/control/ContextReceiver.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ namespace ContextReceiver {
6060
val: JSON.stringify(VariableUtil.encodeVariable(value))
6161
});
6262
}
63-
for (let value of fieldVars) {
64-
activeSpan.tag({
65-
key: `spp.field:${breakpointId}:${value.name}`,
66-
overridable: false,
67-
val: JSON.stringify(VariableUtil.encodeVariable(value))
68-
});
69-
}
63+
// for (let value of fieldVars) {
64+
// if (value.name == undefined) {
65+
// console.log(`Warning: field variable has no name: ${JSON.stringify(value)}`);
66+
// return;
67+
// }
68+
// console.log("got field variable: " + value.name);
69+
//
70+
// activeSpan.tag({
71+
// key: `spp.field:${breakpointId}:${value.name}`,
72+
// overridable: false,
73+
// val: JSON.stringify(VariableUtil.encodeVariable(value))
74+
// });
75+
// }
7076

7177
activeSpan.tag({
7278
key: `spp.stack-trace:${breakpointId}`,

test/LiveInstrumentTest.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
// Keep running this method, so we can test breakpoints, logs, etc.
2-
let intervalId;
3-
4-
function test() {
5-
let i = 0;
6-
7-
for (let j = 0; j < 10; j++) {
8-
if (j % 2 === 0) {
9-
i++;
10-
}
11-
}
12-
}
13-
14-
intervalId = setInterval(test, 1000);
15-
16-
module.exports = {
17-
stop: () => clearInterval(intervalId)
18-
}
1+
// // Keep running this method, so we can test breakpoints, logs, etc.
2+
// let intervalId;
3+
//
4+
// function test() {
5+
// let i = 0;
6+
//
7+
// for (let j = 0; j < 10; j++) {
8+
// if (j % 2 === 0) {
9+
// i++;
10+
// }
11+
// }
12+
// }
13+
//
14+
// intervalId = setInterval(test, 1000);
15+
//
16+
// module.exports = {
17+
// stop: () => clearInterval(intervalId)
18+
// }
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const assert = require('assert');
2+
const TestUtils = require("./TestUtils.js");
3+
4+
module.exports = function () {
5+
function simpleCollections() {
6+
let ints = [1, -1]
7+
let strings = ['h', 'i']
8+
let doubles = [-1.0, 1.0]
9+
let booleans = [true, false]
10+
// let objects = [{}, {}]
11+
// let arrays = [[], []]
12+
// let maps = [new Map(), new Map()]
13+
// let sets = [new Set(), new Set()]
14+
TestUtils.addLineLabel("done", () => TestUtils.getLineNumber())
15+
}
16+
17+
it('add live breakpoint', async function () {
18+
simpleCollections() //setup labels
19+
20+
await TestUtils.addLiveBreakpoint({
21+
"source": TestUtils.getFilename()(),
22+
"line": TestUtils.getLineLabelNumber("done")
23+
}, null, 1).then(function (res) {
24+
assert.equal(res.status, 200);
25+
simpleCollections(); //trigger breakpoint
26+
}).catch(function (err) {
27+
assert.fail(err)
28+
});
29+
});
30+
31+
it('verify breakpoint data', async function () {
32+
this.timeout(2000)
33+
let event = await TestUtils.awaitMarkerEvent("BREAKPOINT_HIT");
34+
let variables = event.stackTrace.elements[0].variables;
35+
36+
let intsVar = TestUtils.locateVariable("ints", variables);
37+
// assert.equal(intsVar.liveClazz, "number");
38+
assert.deepEqual(
39+
[1, -1],
40+
[intsVar.value[0].value[0].value, intsVar.value[1].value[0].value]
41+
);
42+
43+
let strings = TestUtils.locateVariable("strings", variables);
44+
// assert.equal(cVar.liveClazz, "string");
45+
assert.deepEqual(
46+
['h', 'i'],
47+
[strings.value[0].value[0].value, strings.value[1].value[0].value]
48+
);
49+
50+
let doubles = TestUtils.locateVariable("doubles", variables);
51+
// assert.equal(cVar.liveClazz, "string");
52+
assert.deepEqual(
53+
[-1.0, 1.0],
54+
[doubles.value[0].value[0].value, doubles.value[1].value[0].value]
55+
);
56+
57+
let booleans = TestUtils.locateVariable("booleans", variables);
58+
// assert.equal(cVar.liveClazz, "string");
59+
// assert.deepEqual(
60+
// [true, false],
61+
// [booleans.value[0].value[0].value, booleans.value[1].value[0].value]
62+
// ); //todo: false shows up as "null"
63+
});
64+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const assert = require('assert');
2+
const TestUtils = require("./TestUtils.js");
3+
4+
module.exports = function () {
5+
function simplePrimitives() {
6+
let i = 1
7+
let c = 'h'
8+
let s = "hi"
9+
let f = 1.0
10+
let bool = true
11+
TestUtils.addLineLabel("done", () => TestUtils.getLineNumber())
12+
}
13+
14+
it('add live breakpoint', async function () {
15+
simplePrimitives() //setup labels
16+
17+
await TestUtils.addLiveBreakpoint({
18+
"source": TestUtils.getFilename()(),
19+
"line": TestUtils.getLineLabelNumber("done")
20+
}, null, 1).then(function (res) {
21+
assert.equal(res.status, 200);
22+
simplePrimitives(); //trigger breakpoint
23+
}).catch(function (err) {
24+
assert.fail(err)
25+
});
26+
});
27+
28+
it('verify breakpoint data', async function () {
29+
this.timeout(2000)
30+
let event = await TestUtils.awaitMarkerEvent("BREAKPOINT_HIT");
31+
assert.equal(event.stackTrace.elements[0].method, 'simplePrimitives');
32+
let variables = event.stackTrace.elements[0].variables;
33+
34+
let iVar = TestUtils.locateVariable("i", variables);
35+
assert.equal(iVar.liveClazz, "number");
36+
assert.equal(iVar.value, 1);
37+
38+
let cVar = TestUtils.locateVariable("c", variables);
39+
assert.equal(cVar.liveClazz, "string");
40+
assert.equal(cVar.value, "h");
41+
42+
let sVar = TestUtils.locateVariable("s", variables);
43+
assert.equal(sVar.liveClazz, "string");
44+
assert.equal(sVar.value, "hi");
45+
46+
let fVar = TestUtils.locateVariable("f", variables);
47+
assert.equal(fVar.liveClazz, "number");
48+
assert.equal(fVar.value, 1.0);
49+
50+
let boolVar = TestUtils.locateVariable("bool", variables);
51+
assert.equal(boolVar.liveClazz, "boolean");
52+
assert.equal(boolVar.value, true);
53+
});
54+
};

test/TestUtils.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
const host = "http://localhost:12800";
2+
const assert = require('assert');
3+
const {default: axios} = require("axios");
4+
const SourcePlusPlus = require("../dist/SourcePlusPlus");
5+
const EventBus = require("@vertx/eventbus-bridge-client.js");
6+
const path = require("path");
7+
8+
const tokenPromise = axios.get(`${host}/api/new-token?access_token=change-me`)
9+
.then(response => response.data);
10+
11+
class TestUtils {
12+
13+
static lineLabels = {}
14+
static markerListeners = {}
15+
static markerEventBus;
16+
17+
static async setupProbe() {
18+
this.timeout(15000);
19+
20+
await SourcePlusPlus.start().then(function () {
21+
console.log("SourcePlusPlus started");
22+
}).catch(function (err) {
23+
assert.fail(err);
24+
});
25+
26+
TestUtils.markerEventBus = new EventBus(host + "/marker/eventbus");
27+
TestUtils.markerEventBus.enableReconnect(true);
28+
await new Promise((resolve, reject) => {
29+
TestUtils.markerEventBus.onopen = async function () {
30+
//send marker connected
31+
TestUtils.markerEventBus.send("spp.platform.status.marker-connected", {
32+
instanceId: "test-marker-id",
33+
connectionTime: Date.now(),
34+
meta: {}
35+
}, {
36+
"auth-token": await tokenPromise
37+
}, async (err) => {
38+
if (err) {
39+
reject(err);
40+
} else {
41+
//listen for breakpoint events
42+
TestUtils.markerEventBus.registerHandler("spp.service.live-instrument.subscriber:system", {
43+
"auth-token": await tokenPromise
44+
}, function (err, message) {
45+
if (!err) {
46+
if (TestUtils.markerListeners[message.body.eventType]) {
47+
TestUtils.markerListeners[message.body.eventType]
48+
.forEach(listener => listener(JSON.parse(message.body.data)));
49+
}
50+
}
51+
});
52+
resolve();
53+
}
54+
});
55+
}
56+
});
57+
58+
// Without waiting long enough, the spp.probe.command.live-instrument-remote counter isn't incremented
59+
await new Promise(resolve => setTimeout(resolve, 10000));
60+
}
61+
62+
static async teardownProbe() {
63+
await SourcePlusPlus.stop();
64+
TestUtils.markerEventBus.close();
65+
}
66+
67+
static addLineLabel(label, lineNumberFunc) {
68+
TestUtils.lineLabels[label] = lineNumberFunc.call();
69+
}
70+
71+
static getLineLabelNumber(label) {
72+
return TestUtils.lineLabels[label];
73+
}
74+
75+
static awaitMarkerEvent(eventName) {
76+
if (!TestUtils.markerListeners[eventName]) {
77+
TestUtils.markerListeners[eventName] = [];
78+
}
79+
return new Promise(resolve => TestUtils.markerListeners[eventName].push(data => resolve(data)));
80+
}
81+
82+
static locateVariable(name, variables) {
83+
for (let variable of variables) {
84+
if (variable.name === name) {
85+
return variable;
86+
}
87+
}
88+
}
89+
90+
static async addLiveBreakpoint(location, condition, hitLimit) {
91+
const options = {
92+
method: 'POST',
93+
url: `${host}/graphql/spp`,
94+
headers: {
95+
'Content-Type': 'application/json',
96+
Authorization: 'Bearer ' + await tokenPromise
97+
},
98+
data: {
99+
"query": "mutation ($input: LiveBreakpointInput!) { addLiveBreakpoint(input: $input) { id location { source line } condition expiresAt hitLimit applyImmediately applied pending throttle { limit step } } }",
100+
"variables": {
101+
"input": {
102+
"location": location,
103+
"condition": condition,
104+
"hitLimit": hitLimit,
105+
"applyImmediately": true
106+
}
107+
}
108+
}
109+
};
110+
return axios.request(options);
111+
}
112+
113+
static getLineNumber() {
114+
var e = new Error();
115+
if (!e.stack) try {
116+
// IE requires the Error to actually be thrown or else the Error's 'stack'
117+
// property is undefined.
118+
throw e;
119+
} catch (e) {
120+
if (!e.stack) {
121+
return 0; // IE < 10, likely
122+
}
123+
}
124+
var stack = e.stack.toString().split(/\r\n|\n/);
125+
// We want our caller's frame. It's index into |stack| depends on the
126+
// browser and browser version, so we need to search for the second frame:
127+
var frameRE = /:(\d+):(?:\d+)[^\d]*$/;
128+
do {
129+
var frame = stack.shift();
130+
} while (!frameRE.exec(frame) && stack.length);
131+
return frameRE.exec(stack.shift())[1];
132+
}
133+
134+
static getFilename = () => {
135+
return () => {
136+
let basePath = process.cwd();
137+
let str = /at .* \(([a-z0-9\/\\\s\-:]*\.js):\d+:\d+\)/ig.exec(new Error().stack)[1];
138+
let relative = path.relative(basePath, str);
139+
return relative.replaceAll('\\', '/');
140+
}
141+
}
142+
}
143+
144+
module.exports = TestUtils;

0 commit comments

Comments
 (0)