Skip to content

Commit 4fdbf6c

Browse files
committed
Add performance testing harness for use with d8
1 parent 674eb7b commit 4fdbf6c

File tree

4 files changed

+150
-5
lines changed

4 files changed

+150
-5
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"build:preact": "cd src/integrations/preact && npm run build",
1212
"build:babel": "cd packages/babel-plugin-htm && npm run build",
1313
"test": "eslint src/**/*.mjs test/**/*.mjs && npm run build && jest test",
14+
"test:perf": "v8 test/__perftest.mjs",
1415
"release": "npm t && git commit -am \"$npm_package_version\" && git tag $npm_package_version && git push && git push --tags && npm publish"
1516
},
1617
"files": [

test/__d8.mjs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*global globalThis*/
2+
3+
const queue = [];
4+
let stack = [];
5+
let index = 0;
6+
// let currentName;
7+
// let prefix = '';
8+
9+
async function process() {
10+
const id = index++;
11+
if (id === queue.length) {
12+
queue.length = index = 0;
13+
return;
14+
}
15+
const [op, name, fn, extra] = queue[id];
16+
queue[id] = undefined;
17+
await processors[op](name, fn, extra);
18+
await process();
19+
}
20+
21+
const processors = {
22+
async describe(name, fn, path) {
23+
// stack.push(Array.from({ length: stack.length + 1 }).join(' ') + name);
24+
stack.push(name);
25+
// log('INFO', Array.from(path).fill(' ').join('') + name);
26+
log('INFO', name);
27+
await fn();
28+
stack.pop();
29+
},
30+
async test(name, fn, path) {
31+
let stackBefore = stack;
32+
stack = path.concat(name);
33+
logBuffer = [];
34+
await new Promise(resolve => {
35+
let calls = 0;
36+
const done = () => {
37+
if (calls++) throw Error(`Callback called multiple times\n\t${name}`);
38+
log('INFO', `✅ ${name}`);
39+
resolve();
40+
};
41+
Promise.resolve(done)
42+
.then(fn)
43+
.then(() => calls || done())
44+
.catch(err => {
45+
// setTimeout(process);
46+
// throw new Error(`\t${err.stack || err.message}`);
47+
log('ERROR', `🚨 ${name}`);
48+
log('ERROR', '\t' + String(err.stack || err.message || err));
49+
// setTimeout(process);
50+
resolve();
51+
});
52+
});
53+
for (let i=0; i<logBuffer.length; i++) log(...logBuffer[i]);
54+
logBuffer = undefined;
55+
stack = stackBefore;
56+
// process();
57+
}
58+
};
59+
60+
61+
let logBuffer;
62+
63+
function wrap(obj, method) {
64+
obj[method] = function() {
65+
let out = ' ';
66+
for (let i=0; i<arguments.length; i++) {
67+
let val = arguments[i];
68+
if (typeof val === 'object' && val) {
69+
val = JSON.stringify(val);
70+
}
71+
if (out) out += ' ';
72+
out += val;
73+
}
74+
if (method!=='error') out = `\u001b[37m${out}\u001b[0m`;
75+
if (logBuffer) {
76+
logBuffer.push([method.toUpperCase(), out]);
77+
}
78+
else {
79+
log(method.toUpperCase(), out);
80+
}
81+
};
82+
}
83+
wrap(console, 'log');
84+
wrap(console, 'info');
85+
wrap(console, 'warn');
86+
wrap(console, 'error');
87+
88+
function log(type, msg) {
89+
if (type === 'ERROR') {
90+
msg = `\u001b[31m${msg}\u001b[39m`;
91+
}
92+
if (type === 'SUCCESS') {
93+
msg = `\u001b[32m${msg}\u001b[39m`;
94+
}
95+
print(Array.from({ length: stack.length }).fill(' ').join('') + msg);
96+
}
97+
98+
function push(op, name, fn, extra) {
99+
if (queue.push([op, name, fn, extra]) === 1) {
100+
setTimeout(process);
101+
}
102+
}
103+
104+
globalThis.describe = (name, fn) => {
105+
push('describe', name, fn, stack.slice());
106+
};
107+
108+
globalThis.test = (name, fn) => {
109+
push('test', name, fn, stack.slice());
110+
};
111+
112+
globalThis.expect = (subject) => new Expect(subject);
113+
114+
const SUBJECT = Symbol.for('subject');
115+
const NEGATED = Symbol.for('negated');
116+
class Expect {
117+
constructor(subject) {
118+
this[SUBJECT] = subject;
119+
}
120+
get not() {
121+
this[NEGATED] = true;
122+
return this;
123+
}
124+
toBeGreaterThan(value) {
125+
const subject = this[SUBJECT];
126+
const negated = this[NEGATED];
127+
128+
const isOver = subject > value;
129+
let msg = `Expected ${subject}${negated?' not':''} to be greater than ${value}`;
130+
if (logBuffer) {
131+
for (let i=logBuffer.length; i-- > -1; ) {
132+
if (i<0 || logBuffer[i][2] === 1) {
133+
logBuffer.splice(i+1, 0, [isOver !== negated ? 'SUCCESS' : 'ERROR', ' ' + msg, 1]);
134+
break;
135+
}
136+
}
137+
}
138+
else {
139+
log(isOver !== negated ? 'SUCCESS' : 'ERROR', ' ' + msg);
140+
}
141+
}
142+
}

test/__perftest.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import './__d8.mjs';
2+
import './perf.test.mjs';

test/perf.test.mjs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ describe('performance', () => {
2020
test('creation', () => {
2121
const results = [];
2222
const Foo = ({ name }) => html`<div class="foo">${name}</div>`;
23-
const statics = [
24-
'\n<div id=app data-loading="true">\n\t<h1>Hello World</h1>\n\t<ul class="items" id=', '>\n\t',
25-
'\n\t</ul>\n\t\n\t<', ' name="foo" />\n\t<', ' name="other">content</', '>\n\n</div>'
26-
];
2723
let count = 0;
2824
function go(count) {
25+
const statics = [
26+
'\n<div id=app'+(++count)+' data-loading="true">\n\t<h1>Hello World</h1>\n\t<ul class="items" id=', '>\n\t',
27+
'\n\t</ul>\n\t\n\t<', ' name="foo" />\n\t<', ' name="other">content</', '>\n\n</div>'
28+
];
2929
return html(
30-
statics.concat(['count:', count]),
30+
statics,
3131
`id${count}`,
3232
html(['<li data-id="','">', '</li>'], 'i'+count, 'some text #'+count),
3333
Foo, Foo, Foo

0 commit comments

Comments
 (0)