diff --git a/test/cache.test.js b/test/cache.test.js new file mode 100644 index 0000000..7ba2c96 --- /dev/null +++ b/test/cache.test.js @@ -0,0 +1,307 @@ +// Import Node.js Dependencies +import assert from "node:assert/strict"; +import { before, describe, it } from "node:test"; +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; + +// Import Third-party Dependencies +import cacache from "cacache"; + +// Import Internal Dependencies +import { appCache } from "../src/http-server/cache.js"; + +// CONSTANTS +const kPayloadsPath = path.join(os.homedir(), ".nsecure", "payloads"); + +describe("appCache", () => { + before(() => { + appCache.prefix = "test_runner"; + }); + + it("should update and get config", async() => { + await appCache.updateConfig({ foo: "bar" }); + + const updated = await appCache.getConfig(); + assert.deepEqual(updated, { foo: "bar" }); + }); + + it("should write payload into ~/.nsecure/payloads", (t) => { + let writePath; + let writeValue; + t.mock.method(fs, "writeFileSync", (path, value) => { + writePath = path; + writeValue = value; + }); + + appCache.updatePayload("foo/bar", { foo: "bar" }); + + assert.equal(writePath, path.join(kPayloadsPath, "foo-bar")); + assert.equal(writeValue, JSON.stringify({ foo: "bar" })); + }); + + it("getPayload should return the payload", async(t) => { + t.mock.method(fs, "readFileSync", () => JSON.stringify({ foo: "bar" })); + + const payload = await appCache.getPayload("foo/bar"); + + assert.deepEqual(payload, { foo: "bar" }); + }); + + it("getPayload should throw", async(t) => { + t.mock.method(fs, "readFileSync", () => { + throw new Error("boo"); + }); + + await assert.rejects(async() => appCache.getPayload("foo/bar"), { + message: "boo" + }); + }); + + it("getPayloadOrNull should return payload", async(t) => { + t.mock.method(fs, "readFileSync", () => JSON.stringify({ foo: "bar" })); + + const payload = await appCache.getPayloadOrNull("foo/bar"); + + assert.deepEqual(payload, { foo: "bar" }); + }); + + it("getPayloadOrNull should return null", async(t) => { + t.mock.method(fs, "readFileSync", () => { + throw new Error("boo"); + }); + + const payload = await appCache.getPayloadOrNull("foo/bar"); + + assert.equal(payload, null); + }); + + it("should update and get payloadsList", async() => { + await appCache.updatePayloadsList({ foo: "bar" }); + + const updated = await appCache.payloadsList(); + assert.deepEqual(updated, { foo: "bar" }); + }); + + it("payloadList should throw", async(t) => { + t.mock.method(cacache, "get", () => { + throw new Error("boo"); + }); + + await assert.rejects(async() => appCache.payloadsList(), { + message: "boo" + }); + }); + + it("should init payloadsList when starting from zero", async(t) => { + appCache.startFromZero = true; + t.mock.method(fs, "readdirSync", () => []); + t.mock.method(cacache, "get", () => { + throw new Error("boo"); + }); + + await appCache.initPayloadsList(); + + t.mock.reset(); + + const payloadsList = await appCache.payloadsList(); + + assert.deepEqual(payloadsList, { + lru: [], + current: null, + older: [], + lastUsed: {}, + root: null + }); + }); + + it("should init payloadsList with the root payload json", async(t) => { + appCache.startFromZero = false; + t.mock.method(fs, "readdirSync", () => []); + t.mock.method(fs, "readFileSync", () => JSON.stringify({ + rootDependencyName: "test_runner", + dependencies: { + test_runner: { + versions: { + "1.0.0": {} + } + } + } + })); + t.mock.method(fs, "writeFileSync", () => void 0); + t.mock.method(cacache, "get", () => { + throw new Error("boo"); + }); + t.mock.method(Date, "now", () => 1234567890); + + await appCache.initPayloadsList(); + + t.mock.reset(); + + const payloadsList = await appCache.payloadsList(); + + assert.deepEqual(payloadsList, { + lru: ["test_runner@1.0.0"], + current: "test_runner@1.0.0", + older: [], + lastUsed: { "test_runner@1.0.0": 1234567890 }, + root: "test_runner@1.0.0" + }); + }); + + it("should init payloadsList.older with already scanned payloads", async(t) => { + t.mock.method(fs, "readdirSync", () => ["test_runner@1.0.0", "test_runner@2.0.0"]); + t.mock.method(cacache, "get", () => { + throw new Error("boo"); + }); + + await appCache.initPayloadsList(); + + t.mock.reset(); + + const payloadsList = await appCache.payloadsList(); + + assert.deepEqual(payloadsList, { + older: ["test_runner@1.0.0", "test_runner@2.0.0"], + current: null, + lru: [] + }); + }); + + it("should remove payload from disk", (t) => { + let removedPath; + t.mock.method(fs, "rmSync", (path) => { + removedPath = path; + }); + + appCache.removePayload("foo/bar"); + + assert.equal(removedPath, path.join(kPayloadsPath, "foo-bar")); + }); + + it("should not remove the last LRU when LRU is not full", async(t) => { + t.mock.method(cacache, "get", () => { + return { + data: { + toString: () => JSON.stringify({ + lru: ["foo"], + older: ["bar"], + lastUsed: { foo: 1234567890 }, + foo: "bar" + }) + } + }; + }); + + const result = await appCache.removeLastLRU(); + + assert.deepEqual(result, { + lru: ["foo"], + older: ["bar"], + lastUsed: { foo: 1234567890 }, + foo: "bar" + }); + }); + + it("should remove the last LRU when LRU is full", async(t) => { + t.mock.method(cacache, "get", () => { + return { + data: { + toString: () => JSON.stringify({ + lru: ["foo", "foz", "bar"], + older: ["boz"], + lastUsed: { + foo: 123, + foz: 1234, + bar: 12345 + }, + foo: "bar" + }) + } + }; + }); + + const result = await appCache.removeLastLRU(); + + assert.deepEqual(result, { + lru: ["foz", "bar"], + older: ["boz", "foo"], + lastUsed: { + foo: 123, + foz: 1234, + bar: 12345 + }, + foo: "bar" + }); + }); + + it("should set local root payload", async(t) => { + t.mock.method(fs, "writeFileSync", () => void 0); + t.mock.method(Date, "now", () => 1234567890); + await appCache.updatePayloadsList({ + lru: [], + current: null, + older: [], + lastUsed: {}, + root: null + }); + const payload = { + rootDependencyName: "test_runner-local", + dependencies: { + "test_runner-local": { + versions: { + "1.0.0": {} + } + } + } + }; + await appCache.setRootPayload(payload, { local: true }); + + const result = await appCache.payloadsList(); + + assert.deepEqual(result, { + lru: ["test_runner-local@1.0.0#local"], + current: "test_runner-local@1.0.0#local", + older: [], + lastUsed: { + "test_runner-local@1.0.0#local": 1234567890 + }, + root: "test_runner-local@1.0.0#local" + }); + }); + + it("should set normal root payload", async(t) => { + t.mock.method(fs, "writeFileSync", () => void 0); + t.mock.method(Date, "now", () => 1234567890); + await appCache.updatePayloadsList({ + lru: [], + current: null, + older: [], + lastUsed: {}, + root: null + }); + const payload = { + rootDependencyName: "test_runner-local", + dependencies: { + "test_runner-local": { + versions: { + "1.0.0": {} + } + } + } + }; + await appCache.setRootPayload(payload, {}); + + const result = await appCache.payloadsList(); + + assert.deepEqual(result, { + lru: ["test_runner-local@1.0.0"], + current: "test_runner-local@1.0.0", + older: [], + lastUsed: { + "test_runner-local@1.0.0": 1234567890 + }, + root: "test_runner-local@1.0.0" + }); + }); +});