From 683412cb016b935f4211c13ab6de95187a6d1490 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 26 Apr 2022 12:39:37 -0500 Subject: [PATCH] refactor: add timeout for race condition in heart test (#5131) * refactor: add timeout for race condition in heart test * fixup!: set mtime to 0 and check for update * fixup!: use utimes directly instead of file open * fixup!: remove import --- test/unit/node/heart.test.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/unit/node/heart.test.ts b/test/unit/node/heart.test.ts index 7996fdab5..5360c865e 100644 --- a/test/unit/node/heart.test.ts +++ b/test/unit/node/heart.test.ts @@ -1,5 +1,5 @@ import { logger } from "@coder/logger" -import { readFile, writeFile, stat } from "fs/promises" +import { readFile, writeFile, stat, utimes } from "fs/promises" import { Heart, heartbeatTimer } from "../../../src/node/heart" import { clean, mockLogger, tmpdir } from "../../utils/helpers" @@ -33,17 +33,26 @@ describe("Heart", () => { const pathToFile = `${testDir}/file.txt` await writeFile(pathToFile, text) const fileContents = await readFile(pathToFile, { encoding: "utf8" }) - const fileStatusBeforeEdit = await stat(pathToFile) + // Explicitly set the modified time to 0 so that we can check + // that the file was indeed modified after calling heart.beat(). + // This works around any potential race conditions. + // Docs: https://nodejs.org/api/fs.html#fspromisesutimespath-atime-mtime + await utimes(pathToFile, 0, 0) + expect(fileContents).toBe(text) heart = new Heart(pathToFile, mockIsActive(true)) heart.beat() + // HACK@jsjoeio - beat has some async logic but is not an async method + // Therefore, we have to create an artificial wait in order to make sure + // all async code has completed before asserting + await new Promise((r) => setTimeout(r, 100)) // Check that the heart wrote to the heartbeatFilePath and overwrote our text const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" }) expect(fileContentsAfterBeat).not.toBe(text) // Make sure the modified timestamp was updated. const fileStatusAfterEdit = await stat(pathToFile) - expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(fileStatusBeforeEdit.mtimeMs) + expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0) }) it("should log a warning when given an invalid file path", async () => { heart = new Heart(`fakeDir/fake.txt`, mockIsActive(false)) @@ -52,7 +61,6 @@ describe("Heart", () => { // Therefore, we have to create an artificial wait in order to make sure // all async code has completed before asserting await new Promise((r) => setTimeout(r, 100)) - // expect(logger.trace).toHaveBeenCalled() expect(logger.warn).toHaveBeenCalled() }) it("should be active after calling beat", () => {