1- import { setupCore , writeWalltimeResults } from "@codspeed/core" ;
2- import { type RunnerTestSuite } from "vitest" ;
1+ import {
2+ InstrumentHooks ,
3+ setupCore ,
4+ writeWalltimeResults ,
5+ } from "@codspeed/core" ;
6+ import { Fn } from "tinybench" ;
7+ import {
8+ RunnerTaskEventPack ,
9+ RunnerTaskResultPack ,
10+ type RunnerTestSuite ,
11+ } from "vitest" ;
312import { NodeBenchmarkRunner } from "vitest/runners" ;
413import { patchRootSuiteWithFullFilePath } from "../common" ;
514import { extractBenchmarkResults } from "./utils" ;
@@ -10,10 +19,13 @@ import { extractBenchmarkResults } from "./utils";
1019 */
1120export class WalltimeRunner extends NodeBenchmarkRunner {
1221 private isTinybenchHookedWithCodspeed = false ;
13- private benchmarkUris = new Map < string , string > ( ) ;
22+ private suiteUris = new Map < string , string > ( ) ;
23+ /// Suite ID of the currently running suite, to allow constructing the URI in the context of tinybench tasks
24+ private currentSuiteId : string | null = null ;
1425
1526 async runSuite ( suite : RunnerTestSuite ) : Promise < void > {
1627 patchRootSuiteWithFullFilePath ( suite ) ;
28+ this . populateBenchmarkUris ( suite ) ;
1729
1830 setupCore ( ) ;
1931
@@ -32,6 +44,72 @@ export class WalltimeRunner extends NodeBenchmarkRunner {
3244 ) ;
3345 }
3446 }
47+
48+ private populateBenchmarkUris ( suite : RunnerTestSuite , parentPath = "" ) : void {
49+ const currentPath =
50+ parentPath !== "" ? `${ parentPath } ::${ suite . name } ` : suite . name ;
51+
52+ for ( const task of suite . tasks ) {
53+ if ( task . type === "suite" ) {
54+ this . suiteUris . set ( task . id , `${ currentPath } ::${ task . name } ` ) ;
55+ this . populateBenchmarkUris ( task , currentPath ) ;
56+ }
57+ }
58+ }
59+
60+ async importTinybench ( ) : Promise < typeof import ( "tinybench" ) > {
61+ const tinybench = await super . importTinybench ( ) ;
62+
63+ if ( this . isTinybenchHookedWithCodspeed ) {
64+ return tinybench ;
65+ }
66+ this . isTinybenchHookedWithCodspeed = true ;
67+
68+ const originalRun = tinybench . Task . prototype . run ;
69+
70+ const getSuiteUri = ( ) : string => {
71+ if ( this . currentSuiteId === null ) {
72+ throw new Error ( "currentSuiteId is null - something went wrong" ) ;
73+ }
74+ return this . suiteUris . get ( this . currentSuiteId ) || "" ;
75+ } ;
76+
77+ tinybench . Task . prototype . run = async function ( ) {
78+ const { fn } = this as { fn : Fn } ;
79+ const suiteUri = getSuiteUri ( ) ;
80+
81+ function __codspeed_root_frame__ ( ) {
82+ return fn ( ) ;
83+ }
84+ ( this as { fn : Fn } ) . fn = __codspeed_root_frame__ ;
85+
86+ InstrumentHooks . startBenchmark ( ) ;
87+ await originalRun . call ( this ) ;
88+ InstrumentHooks . stopBenchmark ( ) ;
89+
90+ // Look up the URI by task name
91+ const uri = `${ suiteUri } ::${ this . name } ` ;
92+ InstrumentHooks . setExecutedBenchmark ( process . pid , uri ) ;
93+
94+ return this ;
95+ } ;
96+
97+ return tinybench ;
98+ }
99+
100+ // Allow tinybench to retrieve the path to the currently running suite
101+ async onTaskUpdate (
102+ _ : RunnerTaskResultPack [ ] ,
103+ events : RunnerTaskEventPack [ ]
104+ ) : Promise < void > {
105+ events . map ( ( event ) => {
106+ const [ id , eventName ] = event ;
107+
108+ if ( eventName === "suite-prepare" ) {
109+ this . currentSuiteId = id ;
110+ }
111+ } ) ;
112+ }
35113}
36114
37115export default WalltimeRunner ;
0 commit comments