Skip to content

Commit f4fac82

Browse files
test: make two watch-timing cases robust to slow and lossy runners
hotspots-per-build bounded a 130 ms busy loop by wall clock, so a pause inside the loop under Bun --smol failed it; it now compares the report with the loop's own measured time, which still catches carried-over time. The watch harness could not re-send a deletion macOS dropped, since the retouch skipped files that no longer exist: it now deletes them again, and counts a deleted file a build resolved as missing as seen.
1 parent 00d6fbf commit f4fac82

5 files changed

Lines changed: 40 additions & 16 deletions

File tree

‎test/templates/WatchTestCases.js‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,14 @@ const describeCases = (config) => {
384384
// macOS can drop a change event entirely
385385
const now = new Date();
386386
for (const file of unseenChanges) {
387-
if (fs.existsSync(file)) fs.utimesSync(file, now, now);
387+
if (fs.existsSync(file)) {
388+
fs.utimesSync(file, now, now);
389+
} else if (fs.existsSync(path.dirname(file))) {
390+
// a dropped deletion is re-sent by deleting again; no build
391+
// runs between the two calls, so none sees the file
392+
fs.writeFileSync(file, "");
393+
fs.unlinkSync(file);
394+
}
388395
}
389396
retouchUnseenChanges(compilers, retries - 1);
390397
}, RETOUCH_DELAY);
@@ -447,7 +454,8 @@ const describeCases = (config) => {
447454
}
448455
}
449456
// a change this build no longer depends on cannot make it stale, and
450-
// nothing watches it any more to report it (e.g. a deleted import)
457+
// nothing watches it any more to report it (e.g. a deleted import);
458+
// a deleted file it resolved as missing is one it saw go
451459
const builds = /** @type {import("../../").Stats[]} */ (
452460
"stats" in stats ? stats.stats : [stats]
453461
);
@@ -456,7 +464,8 @@ const describeCases = (config) => {
456464
!builds.some(
457465
({ compilation }) =>
458466
compilation.fileDependencies.has(file) ||
459-
compilation.missingDependencies.has(file) ||
467+
(compilation.missingDependencies.has(file) &&
468+
fs.existsSync(file)) ||
460469
isWithin(file, compilation.contextDependencies)
461470
)
462471
) {

‎test/watchCases/performance/hotspots-per-build/0/index.js‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ it("should report only this build's time, step 0", () => {
88
expect(hint).toBeDefined();
99

1010
const ms = Number(/BurnPlugin \((\d+) ms/.exec(hint.message)[1]);
11+
const { burned } = COMPILER.options.plugins.find(
12+
(plugin) => "burned" in plugin
13+
);
1114

12-
// The plugin burns the same amount every build. Anything near a multiple of
13-
// it means the last build's time was carried into this one.
14-
expect(ms).toBeGreaterThanOrEqual(100);
15-
expect(ms).toBeLessThan(240);
15+
// Measured against this build's own burn, so a slow machine cancels out; a
16+
// carried-over build would add a whole earlier burn (130 ms or more).
17+
expect(ms).toBeGreaterThanOrEqual(Math.floor(burned));
18+
expect(ms - burned).toBeLessThan(100);
1619
});

‎test/watchCases/performance/hotspots-per-build/1/index.js‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ it("should report only this build's time, step 1", () => {
88
expect(hint).toBeDefined();
99

1010
const ms = Number(/BurnPlugin \((\d+) ms/.exec(hint.message)[1]);
11+
const { burned } = COMPILER.options.plugins.find(
12+
(plugin) => "burned" in plugin
13+
);
1114

12-
// The plugin burns the same amount every build. Anything near a multiple of
13-
// it means the last build's time was carried into this one.
14-
expect(ms).toBeGreaterThanOrEqual(100);
15-
expect(ms).toBeLessThan(240);
15+
// Measured against this build's own burn, so a slow machine cancels out; a
16+
// carried-over build would add a whole earlier burn (130 ms or more).
17+
expect(ms).toBeGreaterThanOrEqual(Math.floor(burned));
18+
expect(ms - burned).toBeLessThan(100);
1619
});

‎test/watchCases/performance/hotspots-per-build/2/index.js‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ it("should report only this build's time, step 2", () => {
88
expect(hint).toBeDefined();
99

1010
const ms = Number(/BurnPlugin \((\d+) ms/.exec(hint.message)[1]);
11+
const { burned } = COMPILER.options.plugins.find(
12+
(plugin) => "burned" in plugin
13+
);
1114

12-
// The plugin burns the same amount every build. Anything near a multiple of
13-
// it means the last build's time was carried into this one.
14-
expect(ms).toBeGreaterThanOrEqual(100);
15-
expect(ms).toBeLessThan(240);
15+
// Measured against this build's own burn, so a slow machine cancels out; a
16+
// carried-over build would add a whole earlier burn (130 ms or more).
17+
expect(ms).toBeGreaterThanOrEqual(Math.floor(burned));
18+
expect(ms - burned).toBeLessThan(100);
1619
});

‎test/watchCases/performance/hotspots-per-build/webpack.config.js‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
"use strict";
22

33
/**
4-
* Holds the main thread for the same stretch on every build.
4+
* Holds the main thread for the same stretch on every build, keeping how long it really took.
55
* @type {import("../../../../").WebpackPluginInstance}
66
*/
77
const burn = {
8+
burned: 0,
89
apply(compiler) {
910
compiler.hooks.compilation.tap("BurnPlugin", (compilation) => {
1011
compilation.hooks.afterSeal.tap("BurnPlugin", () => {
12+
const start = process.hrtime();
1113
const until = Date.now() + 130;
1214

1315
while (Date.now() < until) {
1416
// Spinning on purpose.
1517
}
18+
19+
const [seconds, nanoseconds] = process.hrtime(start);
20+
21+
burn.burned = seconds * 1000 + nanoseconds / 1e6;
1622
});
1723
});
1824
}

0 commit comments

Comments
 (0)