Skip to content

Commit d21054d

Browse files
committed
feat: implement benchmark.js compatibility
1 parent 3a3f637 commit d21054d

File tree

12 files changed

+264
-255
lines changed

12 files changed

+264
-255
lines changed

.eslintrc.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
"plugin:import/recommended",
77
"plugin:import/typescript"
88
],
9-
"ignorePatterns": ["**/dist/**", "**/node_modules/**", "**/rollup.config.ts"],
9+
"ignorePatterns": [
10+
"**/dist/**",
11+
"**/node_modules/**",
12+
"**/rollup.config.ts",
13+
"**/jest.config.js"
14+
],
1015
"settings": {
1116
"import/parsers": {
1217
"@typescript-eslint/parser": [".ts", ".tsx"]

.moon/project.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,23 @@ tasks:
5555
outputs:
5656
- "dist/"
5757
deps:
58-
- "clean"
5958
- "typecheck"
6059
- "^:build"
6160
env:
6261
NODE_NO_WARNINGS: "1"
6362

63+
test:
64+
command: "jest --passWithNoTests"
65+
inputs:
66+
- "@globs(sources)"
67+
- "@globs(tests)"
68+
- "@globs(configs)"
69+
- "tsconfig.json"
70+
- "/tsconfig.json"
71+
- "/tsconfig.base.json"
72+
deps:
73+
- "build"
74+
6475
clean:
6576
command: "rm -rf"
6677
args:

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"@rollup/plugin-json": "^6.0.0",
1010
"@rollup/plugin-node-resolve": "^15.0.1",
1111
"@rollup/plugin-typescript": "^11.0.0",
12-
"@types/jest": "^23.3.14",
12+
"@types/jest": "^29.2.5",
1313
"@types/node": "^18.11.18",
1414
"@typescript-eslint/eslint-plugin": "^5.37.0",
1515
"@typescript-eslint/parser": "^5.48.1",
@@ -18,13 +18,14 @@
1818
"eslint-import-resolver-typescript": "^3.5.1",
1919
"eslint-plugin-import": "^2.26.0",
2020
"husky": "^7.0.4",
21-
"jest": "^23.6.0",
22-
"jest-config": "^23.6.0",
21+
"jest": "^29.3.1",
22+
"jest-config": "^29.3.1",
2323
"prettier": "^2.7.1",
2424
"prettier-plugin-organize-imports": "^2.3.4",
2525
"rollup": "^3.10.0",
2626
"rollup-plugin-dts": "^5.1.1",
2727
"rollup-plugin-esbuild": "^5.0.0",
28+
"ts-jest": "^29.0.5",
2829
"ts-node": "^7.0.1",
2930
"tslib": "^2.4.1",
3031
"typescript": "4.9.4"

packages/benchmark.js/jest.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/** @type {import('ts-jest').JestConfigWithTsJest} */
2+
module.exports = {
3+
preset: "ts-jest",
4+
testEnvironment: "node",
5+
transform: {
6+
"^.+\\.tsx?$": [
7+
"ts-jest",
8+
{
9+
tsconfig: "tsconfig.test.json",
10+
},
11+
],
12+
},
13+
};

packages/benchmark.js/package.json

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,16 @@
1515
"url": ""
1616
},
1717
"license": "MIT",
18-
"jest": {
19-
"transform": {
20-
".(ts|tsx)": "ts-jest"
21-
},
22-
"testEnvironment": "node",
23-
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
24-
"moduleFileExtensions": [
25-
"ts",
26-
"tsx",
27-
"js"
28-
]
29-
},
3018
"devDependencies": {
31-
"@types/benchmark": "^2.1.2"
19+
"@types/benchmark": "^2.1.2",
20+
"@types/find-up": "^4.0.0",
21+
"@types/stack-trace": "^0.0.30",
22+
"jest-mock-extended": "^3.0.1"
3223
},
3324
"dependencies": {
3425
"@codspeed/core": "workspace:*",
35-
"benchmark": "^2.1.4"
26+
"benchmark": "^2.1.4",
27+
"find-up": "^6.3.0",
28+
"stack-trace": "1.0.0-pre1"
3629
}
3730
}

packages/benchmark.js/rollup.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export default defineConfig([
1515
},
1616
],
1717
plugins: declarationsPlugin,
18-
external: ["@codspeed/core"],
1918
},
2019
{
2120
input: entrypoint,

packages/benchmark.js/src/index.ts

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,74 @@
11
import Benchmark from "benchmark";
2+
import measurement from "@codspeed/core";
3+
import { get as getStackTrace } from "stack-trace";
4+
import path, { dirname } from "path";
5+
import { findUpSync, Options } from "find-up";
26

3-
export function withCodSpeed(suite: Benchmark.Suite): Benchmark.Suite {
4-
suite.on("cycle", function (event: Benchmark.Event) {
5-
console.log(String(event.target));
6-
});
7+
export function withCodSpeed(suite: Benchmark): Benchmark;
8+
export function withCodSpeed(suite: Benchmark.Suite): Benchmark.Suite;
9+
export function withCodSpeed(item: unknown): unknown {
10+
if ((item as { length?: number }).length === undefined) {
11+
return withCodSpeedBenchmark(item as Benchmark);
12+
} else {
13+
return withCodSpeedSuite(item as Benchmark.Suite);
14+
}
15+
}
16+
17+
function withCodSpeedBenchmark(bench: Benchmark): Benchmark {
18+
if (!measurement.isInstrumented()) {
19+
return bench;
20+
}
21+
const callingFile = getCallingFile();
22+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
23+
bench.run = function (options?: Benchmark.Options): Benchmark {
24+
const uri = callingFile + "::" + (bench.name ?? "unknown");
25+
measurement.startMeasurement();
26+
(bench.fn as CallableFunction)();
27+
measurement.stopMeasurement(uri);
28+
return bench;
29+
};
30+
return bench;
31+
}
32+
33+
function withCodSpeedSuite(suite: Benchmark.Suite): Benchmark.Suite {
34+
if (!measurement.isInstrumented()) {
35+
return suite;
36+
}
37+
const callingFile = getCallingFile();
38+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
39+
suite.run = function (options?: Benchmark.Options): Benchmark.Suite {
40+
const suiteName = suite.name;
41+
const benches = this as unknown as Benchmark[];
42+
let baseUri = callingFile;
43+
if (suiteName !== undefined) {
44+
baseUri += `::${suiteName}`;
45+
}
46+
for (let i = 0; i < benches.length; i++) {
47+
const bench = benches[i];
48+
const uri = baseUri + "::" + (bench.name ?? `unknown_${i}`);
49+
measurement.startMeasurement();
50+
(bench.fn as CallableFunction)();
51+
measurement.stopMeasurement(uri);
52+
}
53+
return suite;
54+
};
755
return suite;
856
}
57+
58+
function getCallingFile(): string {
59+
const stack = getStackTrace();
60+
const callingFile = stack[3].getFileName(); // [here, withCodSpeed, withCodSpeedX, actual caller]
61+
const gitDir = getGitDir(callingFile);
62+
if (gitDir === undefined) {
63+
throw new Error("Could not find a git repository");
64+
}
65+
return path.relative(gitDir, callingFile);
66+
}
67+
68+
function getGitDir(path: string): string | undefined {
69+
const dotGitPath = findUpSync(".git", {
70+
cwd: path,
71+
type: "directory",
72+
} as Options);
73+
return dotGitPath ? dirname(dotGitPath) : undefined;
74+
}
Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,87 @@
1-
// import DummyClass from "../src/--libraryname--"
2-
3-
/**
4-
* Dummy test
5-
*/
6-
describe("Dummy test", () => {
7-
it("works if true is truthy", () => {
8-
expect(true).toBeTruthy();
1+
import { mockDeep, mockReset } from "jest-mock-extended";
2+
const mockCore = mockDeep<Measurement>();
3+
4+
import Benchmark from "benchmark";
5+
import { withCodSpeed } from "..";
6+
import type { Measurement } from "@codspeed/core";
7+
8+
jest.mock("@codspeed/core", () => mockCore);
9+
10+
beforeEach(() => {
11+
mockReset(mockCore);
12+
});
13+
14+
describe("Benchmark", () => {
15+
it("simple benchmark", () => {
16+
mockCore.isInstrumented.mockReturnValue(false);
17+
const bench = withCodSpeed(
18+
new Benchmark("RegExp", function () {
19+
/o/.test("Hello World!");
20+
})
21+
);
22+
const onComplete = jest.fn();
23+
bench.on("complete", onComplete);
24+
bench.run({ maxTime: 0.1, initCount: 1 });
25+
expect(onComplete).toHaveBeenCalled();
26+
expect(mockCore.startMeasurement).not.toHaveBeenCalled();
27+
expect(mockCore.stopMeasurement).not.toHaveBeenCalled();
28+
});
29+
it("check core methods are called", () => {
30+
mockCore.isInstrumented.mockReturnValue(true);
31+
expect(mockCore.isInstrumented()).toBe(true);
32+
withCodSpeed(
33+
new Benchmark("RegExpSingle", function () {
34+
/o/.test("Hello World!");
35+
})
36+
).run();
37+
expect(mockCore.startMeasurement).toHaveBeenCalled();
38+
expect(mockCore.stopMeasurement).toHaveBeenCalledWith(
39+
"packages/benchmark.js/test/library.test.ts::RegExpSingle"
40+
);
41+
});
42+
});
43+
44+
describe("Benchmark.Suite", () => {
45+
it("simple suite", () => {
46+
mockCore.isInstrumented.mockReturnValue(false);
47+
const suite = withCodSpeed(new Benchmark.Suite());
48+
suite.add("RegExp", function () {
49+
/o/.test("Hello World!");
50+
});
51+
const onComplete = jest.fn();
52+
suite.on("complete", onComplete);
53+
suite.run({ maxTime: 0.1, initCount: 1 });
54+
expect(onComplete).toHaveBeenCalled();
55+
expect(mockCore.startMeasurement).not.toHaveBeenCalled();
56+
expect(mockCore.stopMeasurement).not.toHaveBeenCalled();
57+
});
58+
it("check core methods are called", () => {
59+
mockCore.isInstrumented.mockReturnValue(true);
60+
withCodSpeed(new Benchmark.Suite())
61+
.add("RegExp", function () {
62+
/o/.test("Hello World!");
63+
})
64+
.run();
65+
expect(mockCore.startMeasurement).toHaveBeenCalled();
66+
expect(mockCore.stopMeasurement).toHaveBeenCalledWith(
67+
"packages/benchmark.js/test/library.test.ts::RegExp"
68+
);
69+
});
70+
it("check suite name is in the uri", () => {
71+
mockCore.isInstrumented.mockReturnValue(true);
72+
withCodSpeed(new Benchmark.Suite("thesuite"))
73+
.add("RegExp", function () {
74+
/o/.test("Hello World!");
75+
})
76+
.add(() => {
77+
/o/.test("Hello World!");
78+
})
79+
.run();
80+
expect(mockCore.stopMeasurement).toHaveBeenCalledWith(
81+
"packages/benchmark.js/test/library.test.ts::thesuite::RegExp"
82+
);
83+
expect(mockCore.stopMeasurement).toHaveBeenCalledWith(
84+
"packages/benchmark.js/test/library.test.ts::thesuite::unknown_1"
85+
);
986
});
1087
});

packages/benchmark.js/tsconfig.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
"extends": "../../tsconfig.base.json",
33
"compilerOptions": {
44
"outDir": "dist",
5-
"rootDir": "src"
5+
"rootDir": "src",
6+
"typeRoots": [
7+
"node_modules/@types",
8+
"../../node_modules/@types"
9+
]
610
},
711
"include": [
812
"src/**/*.ts"
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"extends": "./tsconfig.json",
33
"compilerOptions": {
4-
"rootDir": "."
4+
"types": ["jest", "node"]
55
},
6-
"include": ["test/**/*.ts", "benches/**/*.ts"]
6+
"include": ["test/**/*.ts", "benches/**/*.ts", "jest.config.ts"]
77
}

0 commit comments

Comments
 (0)