test: execute the HTTP scenario catalog
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
rm,
|
||||
writeFile,
|
||||
} from "node:fs/promises";
|
||||
import { constants } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
@@ -41,6 +42,67 @@ afterEach(async () => {
|
||||
});
|
||||
|
||||
describe("validated JSON artifact writer", () => {
|
||||
it("syncs an O_NOFOLLOW exclusive temp and its directory around rename", async () => {
|
||||
const events: string[] = [];
|
||||
let openFlags = 0;
|
||||
let openMode = 0;
|
||||
const writer = createValidatedJsonArtifactWriter({
|
||||
createNonce: () => "durable",
|
||||
fileSystem: {
|
||||
open: async (_target, flags, mode) => {
|
||||
openFlags = flags;
|
||||
openMode = mode;
|
||||
events.push(`open:${flags}`);
|
||||
return {
|
||||
writeFile: async () => {
|
||||
events.push("write");
|
||||
},
|
||||
sync: async () => {
|
||||
events.push("file-sync");
|
||||
},
|
||||
close: async () => {
|
||||
events.push("file-close");
|
||||
},
|
||||
};
|
||||
},
|
||||
openDirectory: async () => ({
|
||||
sync: async () => {
|
||||
events.push("directory-sync");
|
||||
},
|
||||
close: async () => {
|
||||
events.push("directory-close");
|
||||
},
|
||||
}),
|
||||
rename: async () => {
|
||||
events.push("rename");
|
||||
},
|
||||
rm: async () => {},
|
||||
},
|
||||
});
|
||||
|
||||
await writer({
|
||||
path: "/tmp/report.json",
|
||||
schema: artifactSchema,
|
||||
value: { schemaVersion: 1, name: "valid" },
|
||||
});
|
||||
|
||||
expect(events).toHaveLength(7);
|
||||
expect(events[0]).toMatch(/^open:\d+$/);
|
||||
expect(openFlags & constants.O_WRONLY).toBe(constants.O_WRONLY);
|
||||
expect(openFlags & constants.O_CREAT).toBe(constants.O_CREAT);
|
||||
expect(openFlags & constants.O_EXCL).toBe(constants.O_EXCL);
|
||||
expect(openFlags & constants.O_NOFOLLOW).toBe(constants.O_NOFOLLOW);
|
||||
expect(openMode).toBe(0o600);
|
||||
expect(events.slice(1)).toEqual([
|
||||
"write",
|
||||
"file-sync",
|
||||
"file-close",
|
||||
"rename",
|
||||
"directory-sync",
|
||||
"directory-close",
|
||||
]);
|
||||
});
|
||||
|
||||
it.each(["existing", "missing"] as const)(
|
||||
"rejects invalid %s artifacts before changing destination state",
|
||||
async (destinationState) => {
|
||||
@@ -123,12 +185,20 @@ describe("validated JSON artifact writer", () => {
|
||||
return {
|
||||
writeFile: async (data, encoding) =>
|
||||
handle.writeFile(data, encoding),
|
||||
sync: async () => handle.sync(),
|
||||
close: async () => {
|
||||
await handle.close();
|
||||
throw closeError;
|
||||
},
|
||||
};
|
||||
},
|
||||
openDirectory: async (target) => {
|
||||
const handle = await open(target, constants.O_RDONLY);
|
||||
return {
|
||||
sync: async () => handle.sync(),
|
||||
close: async () => handle.close(),
|
||||
};
|
||||
},
|
||||
rename,
|
||||
rm,
|
||||
},
|
||||
@@ -165,12 +235,20 @@ describe("validated JSON artifact writer", () => {
|
||||
await handle.writeFile(data, encoding);
|
||||
throw writeError;
|
||||
},
|
||||
sync: async () => handle.sync(),
|
||||
close: async () => {
|
||||
await handle.close();
|
||||
throw closeError;
|
||||
},
|
||||
};
|
||||
},
|
||||
openDirectory: async (target) => {
|
||||
const handle = await open(target, constants.O_RDONLY);
|
||||
return {
|
||||
sync: async () => handle.sync(),
|
||||
close: async () => handle.close(),
|
||||
};
|
||||
},
|
||||
rename,
|
||||
rm,
|
||||
},
|
||||
@@ -244,6 +322,14 @@ describe("validated JSON artifact writer", () => {
|
||||
throw new Error("injected write failure");
|
||||
}
|
||||
},
|
||||
sync: async () => handle.sync(),
|
||||
close: async () => handle.close(),
|
||||
};
|
||||
},
|
||||
openDirectory: async (target) => {
|
||||
const handle = await open(target, constants.O_RDONLY);
|
||||
return {
|
||||
sync: async () => handle.sync(),
|
||||
close: async () => handle.close(),
|
||||
};
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user