@streetjs/storage 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/drivers/local.d.ts +8 -0
- package/dist/drivers/local.d.ts.map +1 -1
- package/dist/drivers/local.js +18 -3
- package/dist/drivers/local.js.map +1 -1
- package/package.json +12 -6
- package/dist/tests/access.test.d.ts +0 -2
- package/dist/tests/access.test.d.ts.map +0 -1
- package/dist/tests/access.test.js +0 -270
- package/dist/tests/access.test.js.map +0 -1
- package/dist/tests/azure-driver.test.d.ts +0 -2
- package/dist/tests/azure-driver.test.d.ts.map +0 -1
- package/dist/tests/azure-driver.test.js +0 -183
- package/dist/tests/azure-driver.test.js.map +0 -1
- package/dist/tests/backblaze-driver.test.d.ts +0 -2
- package/dist/tests/backblaze-driver.test.d.ts.map +0 -1
- package/dist/tests/backblaze-driver.test.js +0 -185
- package/dist/tests/backblaze-driver.test.js.map +0 -1
- package/dist/tests/bridge-degradation.test.d.ts +0 -2
- package/dist/tests/bridge-degradation.test.d.ts.map +0 -1
- package/dist/tests/bridge-degradation.test.js +0 -138
- package/dist/tests/bridge-degradation.test.js.map +0 -1
- package/dist/tests/cli.test.d.ts +0 -2
- package/dist/tests/cli.test.d.ts.map +0 -1
- package/dist/tests/cli.test.js +0 -127
- package/dist/tests/cli.test.js.map +0 -1
- package/dist/tests/contract.d.ts +0 -131
- package/dist/tests/contract.d.ts.map +0 -1
- package/dist/tests/contract.js +0 -222
- package/dist/tests/contract.js.map +0 -1
- package/dist/tests/contract.test.d.ts +0 -2
- package/dist/tests/contract.test.d.ts.map +0 -1
- package/dist/tests/contract.test.js +0 -110
- package/dist/tests/contract.test.js.map +0 -1
- package/dist/tests/directory.test.d.ts +0 -2
- package/dist/tests/directory.test.d.ts.map +0 -1
- package/dist/tests/directory.test.js +0 -125
- package/dist/tests/directory.test.js.map +0 -1
- package/dist/tests/errors.test.d.ts +0 -2
- package/dist/tests/errors.test.d.ts.map +0 -1
- package/dist/tests/errors.test.js +0 -93
- package/dist/tests/errors.test.js.map +0 -1
- package/dist/tests/events-bridge.test.d.ts +0 -2
- package/dist/tests/events-bridge.test.d.ts.map +0 -1
- package/dist/tests/events-bridge.test.js +0 -228
- package/dist/tests/events-bridge.test.js.map +0 -1
- package/dist/tests/example-smoke.test.d.ts +0 -2
- package/dist/tests/example-smoke.test.d.ts.map +0 -1
- package/dist/tests/example-smoke.test.js +0 -34
- package/dist/tests/example-smoke.test.js.map +0 -1
- package/dist/tests/gcs-driver.test.d.ts +0 -2
- package/dist/tests/gcs-driver.test.d.ts.map +0 -1
- package/dist/tests/gcs-driver.test.js +0 -197
- package/dist/tests/gcs-driver.test.js.map +0 -1
- package/dist/tests/image.test.d.ts +0 -2
- package/dist/tests/image.test.d.ts.map +0 -1
- package/dist/tests/image.test.js +0 -102
- package/dist/tests/image.test.js.map +0 -1
- package/dist/tests/lifecycle.test.d.ts +0 -2
- package/dist/tests/lifecycle.test.d.ts.map +0 -1
- package/dist/tests/lifecycle.test.js +0 -171
- package/dist/tests/lifecycle.test.js.map +0 -1
- package/dist/tests/local-driver.test.d.ts +0 -2
- package/dist/tests/local-driver.test.d.ts.map +0 -1
- package/dist/tests/local-driver.test.js +0 -153
- package/dist/tests/local-driver.test.js.map +0 -1
- package/dist/tests/local-streaming.test.d.ts +0 -2
- package/dist/tests/local-streaming.test.d.ts.map +0 -1
- package/dist/tests/local-streaming.test.js +0 -121
- package/dist/tests/local-streaming.test.js.map +0 -1
- package/dist/tests/memory-driver.test.d.ts +0 -2
- package/dist/tests/memory-driver.test.d.ts.map +0 -1
- package/dist/tests/memory-driver.test.js +0 -180
- package/dist/tests/memory-driver.test.js.map +0 -1
- package/dist/tests/memory-streaming.test.d.ts +0 -2
- package/dist/tests/memory-streaming.test.d.ts.map +0 -1
- package/dist/tests/memory-streaming.test.js +0 -92
- package/dist/tests/memory-streaming.test.js.map +0 -1
- package/dist/tests/minio-driver.test.d.ts +0 -2
- package/dist/tests/minio-driver.test.d.ts.map +0 -1
- package/dist/tests/minio-driver.test.js +0 -146
- package/dist/tests/minio-driver.test.js.map +0 -1
- package/dist/tests/non-s3-integration.test.d.ts +0 -2
- package/dist/tests/non-s3-integration.test.d.ts.map +0 -1
- package/dist/tests/non-s3-integration.test.js +0 -201
- package/dist/tests/non-s3-integration.test.js.map +0 -1
- package/dist/tests/observability.registration.test.d.ts +0 -2
- package/dist/tests/observability.registration.test.d.ts.map +0 -1
- package/dist/tests/observability.registration.test.js +0 -103
- package/dist/tests/observability.registration.test.js.map +0 -1
- package/dist/tests/observability.test.d.ts +0 -2
- package/dist/tests/observability.test.d.ts.map +0 -1
- package/dist/tests/observability.test.js +0 -240
- package/dist/tests/observability.test.js.map +0 -1
- package/dist/tests/plugin.test.d.ts +0 -2
- package/dist/tests/plugin.test.d.ts.map +0 -1
- package/dist/tests/plugin.test.js +0 -112
- package/dist/tests/plugin.test.js.map +0 -1
- package/dist/tests/prop-concurrent.test.d.ts +0 -2
- package/dist/tests/prop-concurrent.test.d.ts.map +0 -1
- package/dist/tests/prop-concurrent.test.js +0 -59
- package/dist/tests/prop-concurrent.test.js.map +0 -1
- package/dist/tests/prop-copy.test.d.ts +0 -2
- package/dist/tests/prop-copy.test.d.ts.map +0 -1
- package/dist/tests/prop-copy.test.js +0 -63
- package/dist/tests/prop-copy.test.js.map +0 -1
- package/dist/tests/prop-delete.test.d.ts +0 -2
- package/dist/tests/prop-delete.test.d.ts.map +0 -1
- package/dist/tests/prop-delete.test.js +0 -35
- package/dist/tests/prop-delete.test.js.map +0 -1
- package/dist/tests/prop-directory.test.d.ts +0 -2
- package/dist/tests/prop-directory.test.d.ts.map +0 -1
- package/dist/tests/prop-directory.test.js +0 -118
- package/dist/tests/prop-directory.test.js.map +0 -1
- package/dist/tests/prop-driver-conformance.test.d.ts +0 -2
- package/dist/tests/prop-driver-conformance.test.d.ts.map +0 -1
- package/dist/tests/prop-driver-conformance.test.js +0 -110
- package/dist/tests/prop-driver-conformance.test.js.map +0 -1
- package/dist/tests/prop-driver-equivalence.test.d.ts +0 -2
- package/dist/tests/prop-driver-equivalence.test.d.ts.map +0 -1
- package/dist/tests/prop-driver-equivalence.test.js +0 -163
- package/dist/tests/prop-driver-equivalence.test.js.map +0 -1
- package/dist/tests/prop-lifecycle.test.d.ts +0 -2
- package/dist/tests/prop-lifecycle.test.d.ts.map +0 -1
- package/dist/tests/prop-lifecycle.test.js +0 -83
- package/dist/tests/prop-lifecycle.test.js.map +0 -1
- package/dist/tests/prop-list.test.d.ts +0 -2
- package/dist/tests/prop-list.test.d.ts.map +0 -1
- package/dist/tests/prop-list.test.js +0 -53
- package/dist/tests/prop-list.test.js.map +0 -1
- package/dist/tests/prop-metadata.test.d.ts +0 -2
- package/dist/tests/prop-metadata.test.d.ts.map +0 -1
- package/dist/tests/prop-metadata.test.js +0 -87
- package/dist/tests/prop-metadata.test.js.map +0 -1
- package/dist/tests/prop-move.test.d.ts +0 -2
- package/dist/tests/prop-move.test.d.ts.map +0 -1
- package/dist/tests/prop-move.test.js +0 -67
- package/dist/tests/prop-move.test.js.map +0 -1
- package/dist/tests/prop-multipart-abort.test.d.ts +0 -2
- package/dist/tests/prop-multipart-abort.test.d.ts.map +0 -1
- package/dist/tests/prop-multipart-abort.test.js +0 -48
- package/dist/tests/prop-multipart-abort.test.js.map +0 -1
- package/dist/tests/prop-multipart.test.d.ts +0 -2
- package/dist/tests/prop-multipart.test.d.ts.map +0 -1
- package/dist/tests/prop-multipart.test.js +0 -65
- package/dist/tests/prop-multipart.test.js.map +0 -1
- package/dist/tests/prop-resumable.test.d.ts +0 -2
- package/dist/tests/prop-resumable.test.d.ts.map +0 -1
- package/dist/tests/prop-resumable.test.js +0 -78
- package/dist/tests/prop-resumable.test.js.map +0 -1
- package/dist/tests/prop-search.test.d.ts +0 -2
- package/dist/tests/prop-search.test.d.ts.map +0 -1
- package/dist/tests/prop-search.test.js +0 -120
- package/dist/tests/prop-search.test.js.map +0 -1
- package/dist/tests/prop-signed-url.test.d.ts +0 -2
- package/dist/tests/prop-signed-url.test.d.ts.map +0 -1
- package/dist/tests/prop-signed-url.test.js +0 -74
- package/dist/tests/prop-signed-url.test.js.map +0 -1
- package/dist/tests/prop-streaming.test.d.ts +0 -2
- package/dist/tests/prop-streaming.test.d.ts.map +0 -1
- package/dist/tests/prop-streaming.test.js +0 -34
- package/dist/tests/prop-streaming.test.js.map +0 -1
- package/dist/tests/prop-upload-download.test.d.ts +0 -2
- package/dist/tests/prop-upload-download.test.d.ts.map +0 -1
- package/dist/tests/prop-upload-download.test.js +0 -30
- package/dist/tests/prop-upload-download.test.js.map +0 -1
- package/dist/tests/prop-validation.test.d.ts +0 -2
- package/dist/tests/prop-validation.test.d.ts.map +0 -1
- package/dist/tests/prop-validation.test.js +0 -50
- package/dist/tests/prop-validation.test.js.map +0 -1
- package/dist/tests/prop-versioning.test.d.ts +0 -2
- package/dist/tests/prop-versioning.test.d.ts.map +0 -1
- package/dist/tests/prop-versioning.test.js +0 -74
- package/dist/tests/prop-versioning.test.js.map +0 -1
- package/dist/tests/queue-bridge.test.d.ts +0 -2
- package/dist/tests/queue-bridge.test.d.ts.map +0 -1
- package/dist/tests/queue-bridge.test.js +0 -111
- package/dist/tests/queue-bridge.test.js.map +0 -1
- package/dist/tests/r2-driver.test.d.ts +0 -2
- package/dist/tests/r2-driver.test.d.ts.map +0 -1
- package/dist/tests/r2-driver.test.js +0 -143
- package/dist/tests/r2-driver.test.js.map +0 -1
- package/dist/tests/realtime-bridge.test.d.ts +0 -2
- package/dist/tests/realtime-bridge.test.d.ts.map +0 -1
- package/dist/tests/realtime-bridge.test.js +0 -106
- package/dist/tests/realtime-bridge.test.js.map +0 -1
- package/dist/tests/resumable.test.d.ts +0 -2
- package/dist/tests/resumable.test.d.ts.map +0 -1
- package/dist/tests/resumable.test.js +0 -104
- package/dist/tests/resumable.test.js.map +0 -1
- package/dist/tests/s3-base.test.d.ts +0 -2
- package/dist/tests/s3-base.test.d.ts.map +0 -1
- package/dist/tests/s3-base.test.js +0 -289
- package/dist/tests/s3-base.test.js.map +0 -1
- package/dist/tests/s3-integration.test.d.ts +0 -2
- package/dist/tests/s3-integration.test.d.ts.map +0 -1
- package/dist/tests/s3-integration.test.js +0 -270
- package/dist/tests/s3-integration.test.js.map +0 -1
- package/dist/tests/s3.test.d.ts +0 -2
- package/dist/tests/s3.test.d.ts.map +0 -1
- package/dist/tests/s3.test.js +0 -203
- package/dist/tests/s3.test.js.map +0 -1
- package/dist/tests/scaffold.test.d.ts +0 -2
- package/dist/tests/scaffold.test.d.ts.map +0 -1
- package/dist/tests/scaffold.test.js +0 -13
- package/dist/tests/scaffold.test.js.map +0 -1
- package/dist/tests/search.test.d.ts +0 -2
- package/dist/tests/search.test.d.ts.map +0 -1
- package/dist/tests/search.test.js +0 -106
- package/dist/tests/search.test.js.map +0 -1
- package/dist/tests/supabase-driver.test.d.ts +0 -2
- package/dist/tests/supabase-driver.test.d.ts.map +0 -1
- package/dist/tests/supabase-driver.test.js +0 -196
- package/dist/tests/supabase-driver.test.js.map +0 -1
- package/dist/tests/testing-utilities.test.d.ts +0 -2
- package/dist/tests/testing-utilities.test.d.ts.map +0 -1
- package/dist/tests/testing-utilities.test.js +0 -138
- package/dist/tests/testing-utilities.test.js.map +0 -1
- package/dist/tests/validation.test.d.ts +0 -2
- package/dist/tests/validation.test.d.ts.map +0 -1
- package/dist/tests/validation.test.js +0 -135
- package/dist/tests/validation.test.js.map +0 -1
- package/dist/tests/versioning.test.d.ts +0 -2
- package/dist/tests/versioning.test.d.ts.map +0 -1
- package/dist/tests/versioning.test.js +0 -128
- package/dist/tests/versioning.test.js.map +0 -1
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage Directory API over the flat key space.
|
|
2
|
-
//
|
|
3
|
-
// Feature: unified-storage-framework, Property 16 — Directory operations over a
|
|
4
|
-
// flat key space. For an arbitrary set of `/`-delimited keys put into storage,
|
|
5
|
-
// the directory operations are consistent over the flat key space:
|
|
6
|
-
//
|
|
7
|
-
// - walk(prefix) returns exactly the keys beneath the prefix (Req 15.4).
|
|
8
|
-
// - listDirectory(prefix) returns exactly the immediate children (files plus
|
|
9
|
-
// collapsed sub-directory entries) with no duplicates and nothing outside
|
|
10
|
-
// the prefix (Req 15.2).
|
|
11
|
-
// - removeDirectory(prefix) removes exactly the keys beneath the prefix, and
|
|
12
|
-
// returns { removed: false } for an empty/missing prefix (Req 15.3, 15.6).
|
|
13
|
-
//
|
|
14
|
-
// Each observation is asserted against a computed expectation derived directly
|
|
15
|
-
// from the generated key set.
|
|
16
|
-
//
|
|
17
|
-
// Uses the public facade via `createStorage({ provider: 'memory' })`, the
|
|
18
|
-
// Node.js built-in test runner (node:test), and fast-check configured with
|
|
19
|
-
// { numRuns: 100 }. Executed via `node --test dist/tests/*.test.js`.
|
|
20
|
-
//
|
|
21
|
-
// Validates: Requirements 15.2, 15.3, 15.4, 15.6
|
|
22
|
-
import test from "node:test";
|
|
23
|
-
import assert from "node:assert/strict";
|
|
24
|
-
import fc from "fast-check";
|
|
25
|
-
import { createStorage } from "../index.js";
|
|
26
|
-
// Segments are drawn from a tiny alphabet so shared prefixes arise frequently,
|
|
27
|
-
// exercising both matching and non-matching keys against a directory prefix.
|
|
28
|
-
const segArb = fc.constantFrom("a", "b", "c");
|
|
29
|
-
// A key is 1–3 `/`-delimited segments (no leading/trailing delimiter).
|
|
30
|
-
const keyArb = fc
|
|
31
|
-
.array(segArb, { minLength: 1, maxLength: 3 })
|
|
32
|
-
.map((segments) => segments.join("/"));
|
|
33
|
-
// A directory path is 0–2 segments; the empty path denotes the root.
|
|
34
|
-
const dirArb = fc
|
|
35
|
-
.array(segArb, { minLength: 0, maxLength: 2 })
|
|
36
|
-
.map((segments) => segments.join("/"));
|
|
37
|
-
/** Normalize a directory path the same way the Directory API does. */
|
|
38
|
-
function toPrefix(path) {
|
|
39
|
-
return path === "" ? "" : path + "/";
|
|
40
|
-
}
|
|
41
|
-
/** Keys strictly beneath `prefix` in the flat key set (no markers here). */
|
|
42
|
-
function expectedWalk(keys, prefix) {
|
|
43
|
-
return keys.filter((key) => key.startsWith(prefix) && key !== prefix);
|
|
44
|
-
}
|
|
45
|
-
/** Immediate children beneath `prefix`: file keys and collapsed sub-dir keys. */
|
|
46
|
-
function expectedImmediate(keys, prefix) {
|
|
47
|
-
const entries = new Set();
|
|
48
|
-
for (const key of keys) {
|
|
49
|
-
if (!key.startsWith(prefix))
|
|
50
|
-
continue;
|
|
51
|
-
const remainder = key.slice(prefix.length);
|
|
52
|
-
if (remainder === "")
|
|
53
|
-
continue; // the directory marker itself, if any
|
|
54
|
-
const slash = remainder.indexOf("/");
|
|
55
|
-
if (slash === -1) {
|
|
56
|
-
entries.add(key); // immediate file child
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
entries.add(prefix + remainder.slice(0, slash) + "/"); // sub-directory
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return entries;
|
|
63
|
-
}
|
|
64
|
-
test("Feature: unified-storage-framework, Property 16 — directory operations are consistent over the flat key space", async () => {
|
|
65
|
-
await fc.assert(fc.asyncProperty(
|
|
66
|
-
// A set of unique keys, each paired with arbitrary string content.
|
|
67
|
-
fc.uniqueArray(fc.tuple(keyArb, fc.string()), {
|
|
68
|
-
selector: ([key]) => key,
|
|
69
|
-
minLength: 0,
|
|
70
|
-
maxLength: 15,
|
|
71
|
-
}),
|
|
72
|
-
// An arbitrary directory path, possibly the root, possibly unrelated.
|
|
73
|
-
dirArb, async (entries, dirPath) => {
|
|
74
|
-
const storage = createStorage({ provider: "memory" });
|
|
75
|
-
const keys = entries.map(([key]) => key);
|
|
76
|
-
for (const [key, content] of entries) {
|
|
77
|
-
await storage.put(key, content, {});
|
|
78
|
-
}
|
|
79
|
-
const prefix = toPrefix(dirPath);
|
|
80
|
-
const under = expectedWalk(keys, prefix);
|
|
81
|
-
// --- walk: exactly the keys beneath the prefix (15.4) -------------
|
|
82
|
-
const walked = await storage.directory.walk(dirPath);
|
|
83
|
-
const walkedSet = new Set(walked);
|
|
84
|
-
assert.equal(walkedSet.size, walked.length, "walk returned duplicate keys");
|
|
85
|
-
assert.equal(walkedSet.size, under.length, "walk cardinality");
|
|
86
|
-
for (const key of under) {
|
|
87
|
-
assert.ok(walkedSet.has(key), `walk missing key: ${key}`);
|
|
88
|
-
}
|
|
89
|
-
for (const key of walked) {
|
|
90
|
-
assert.ok(key.startsWith(prefix), `walk leaked key outside prefix: ${key}`);
|
|
91
|
-
}
|
|
92
|
-
// --- listDirectory: exactly the immediate children (15.2) --------
|
|
93
|
-
const listing = await storage.directory.listDirectory(dirPath);
|
|
94
|
-
const listedKeys = listing.map((item) => item.key);
|
|
95
|
-
const listedSet = new Set(listedKeys);
|
|
96
|
-
assert.equal(listedSet.size, listedKeys.length, "listDirectory returned duplicate entries");
|
|
97
|
-
const expectedChildren = expectedImmediate(keys, prefix);
|
|
98
|
-
assert.equal(listedSet.size, expectedChildren.size, "listDirectory cardinality");
|
|
99
|
-
for (const key of expectedChildren) {
|
|
100
|
-
assert.ok(listedSet.has(key), `listDirectory missing child: ${key}`);
|
|
101
|
-
}
|
|
102
|
-
for (const key of listedKeys) {
|
|
103
|
-
assert.ok(key.startsWith(prefix) && key !== prefix, `listDirectory leaked entry outside prefix: ${key}`);
|
|
104
|
-
}
|
|
105
|
-
// --- removeDirectory: removes exactly the keys beneath (15.3/15.6)
|
|
106
|
-
const result = await storage.directory.removeDirectory(dirPath);
|
|
107
|
-
assert.deepEqual(result, { removed: under.length > 0 }, "removeDirectory removed flag");
|
|
108
|
-
// Nothing beneath the prefix survives; everything else is intact.
|
|
109
|
-
assert.deepEqual(await storage.directory.walk(dirPath), [], "removeDirectory left keys beneath the prefix");
|
|
110
|
-
const remaining = new Set(await storage.directory.walk(""));
|
|
111
|
-
const expectedRemaining = keys.filter((key) => !key.startsWith(prefix));
|
|
112
|
-
assert.equal(remaining.size, expectedRemaining.length);
|
|
113
|
-
for (const key of expectedRemaining) {
|
|
114
|
-
assert.ok(remaining.has(key), `removeDirectory wrongly removed sibling: ${key}`);
|
|
115
|
-
}
|
|
116
|
-
}), { numRuns: 100 });
|
|
117
|
-
});
|
|
118
|
-
//# sourceMappingURL=prop-directory.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-directory.test.js","sourceRoot":"","sources":["../../src/tests/prop-directory.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-driver-conformance.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-driver-conformance.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
// Property-based test: every available driver conforms to the StorageDriver contract.
|
|
2
|
-
//
|
|
3
|
-
// Property 19: Every available (zero-dependency) driver conforms to the shared
|
|
4
|
-
// StorageDriver contract. This reuses the parameterized contract-conformance
|
|
5
|
-
// suite from `./contract.js` (task 27.1) — `runStorageDriverContract` and
|
|
6
|
-
// `storageDriverContractChecks` — asserting the returned report passes for both
|
|
7
|
-
// the Memory and Local drivers.
|
|
8
|
-
//
|
|
9
|
-
// Because the contract checks use fixed internal keys, this property ALSO folds
|
|
10
|
-
// in a fast-check-generated round-trip assertion per driver over arbitrary
|
|
11
|
-
// key+byte inputs (put→get equals, exists→true, delete→exists false,
|
|
12
|
-
// get→found:false) so the property genuinely varies its inputs at
|
|
13
|
-
// { numRuns: 100 }. A fresh driver is constructed per run; each Local driver is
|
|
14
|
-
// rooted at a unique temp directory that is cleaned up after the run.
|
|
15
|
-
//
|
|
16
|
-
// Executed via the Node.js built-in test runner (`node --test dist/tests/*.test.js`).
|
|
17
|
-
//
|
|
18
|
-
// Feature: unified-storage-framework, Property 19
|
|
19
|
-
// Validates: Requirements 2.1, 2.3, 2.4, 26.6
|
|
20
|
-
import test from "node:test";
|
|
21
|
-
import assert from "node:assert/strict";
|
|
22
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
23
|
-
import { tmpdir } from "node:os";
|
|
24
|
-
import { join } from "node:path";
|
|
25
|
-
import fc from "fast-check";
|
|
26
|
-
import { runStorageDriverContract, storageDriverContractChecks, } from "./contract.js";
|
|
27
|
-
import { MemoryStorageDriver } from "../drivers/memory.js";
|
|
28
|
-
import { LocalStorageDriver } from "../drivers/local.js";
|
|
29
|
-
/** A fixed clock for deterministic timestamps. */
|
|
30
|
-
const fixedClock = () => 1_700_000_000_000;
|
|
31
|
-
/** Temp roots allocated for Local drivers, cleaned up after the run. */
|
|
32
|
-
const tempRoots = [];
|
|
33
|
-
/** Factory: a fresh in-memory driver per call. */
|
|
34
|
-
function makeMemoryDriver() {
|
|
35
|
-
return new MemoryStorageDriver({ clock: fixedClock });
|
|
36
|
-
}
|
|
37
|
-
/** Factory: a fresh filesystem driver rooted at a unique temp dir per call. */
|
|
38
|
-
function makeLocalDriver() {
|
|
39
|
-
const root = mkdtempSync(join(tmpdir(), "streetjs-storage-conformance-"));
|
|
40
|
-
tempRoots.push(root);
|
|
41
|
-
return new LocalStorageDriver({ root, clock: fixedClock });
|
|
42
|
-
}
|
|
43
|
-
/** The available zero-dependency drivers under test. */
|
|
44
|
-
const DRIVERS = [
|
|
45
|
-
{ label: "memory", make: makeMemoryDriver },
|
|
46
|
-
{ label: "local", make: makeLocalDriver },
|
|
47
|
-
];
|
|
48
|
-
/**
|
|
49
|
-
* A generator over the domain of *valid object keys*.
|
|
50
|
-
*
|
|
51
|
-
* A key is generated as one or more non-empty path segments joined by `/`,
|
|
52
|
-
* where each segment is drawn from a filesystem-safe character set and is never
|
|
53
|
-
* the reserved relative-path names `.` or `..`. This deliberately excludes keys
|
|
54
|
-
* that no real object store accepts as an object key and that the Local driver
|
|
55
|
-
* (which maps keys onto filesystem paths) cannot represent equivalently to the
|
|
56
|
-
* opaque-map Memory driver:
|
|
57
|
-
* - the empty string and empty segments (e.g. `""`, `"a//b"`),
|
|
58
|
-
* - a leading or trailing `/` (e.g. `"/a"`, `"a/"`),
|
|
59
|
-
* - the relative segments `"."` / `".."` (path traversal),
|
|
60
|
-
* - control characters such as NUL.
|
|
61
|
-
* Such inputs resolve to an existing/invalid filesystem path (EISDIR / ENOTDIR
|
|
62
|
-
* / ERR_INVALID_ARG_VALUE) on the Local driver while the Memory driver treats
|
|
63
|
-
* them as opaque map keys — an out-of-domain divergence, not a driver defect.
|
|
64
|
-
* This matches the valid-key domain the equivalence property (Property 18)
|
|
65
|
-
* already documents for its curated key pool.
|
|
66
|
-
*/
|
|
67
|
-
const KEY_SEGMENT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.".split("");
|
|
68
|
-
const segmentArb = fc
|
|
69
|
-
.array(fc.constantFrom(...KEY_SEGMENT_CHARS), { minLength: 1, maxLength: 12 })
|
|
70
|
-
.map((chars) => chars.join(""))
|
|
71
|
-
.filter((segment) => segment !== "." && segment !== "..");
|
|
72
|
-
const keyArb = fc
|
|
73
|
-
.array(segmentArb, { minLength: 1, maxLength: 4 })
|
|
74
|
-
.map((segments) => segments.join("/"));
|
|
75
|
-
test.after(() => {
|
|
76
|
-
for (const root of tempRoots) {
|
|
77
|
-
rmSync(root, { recursive: true, force: true });
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
test("Feature: unified-storage-framework, Property 19 — every driver conforms to the StorageDriver contract", async () => {
|
|
81
|
-
await fc.assert(fc.asyncProperty(
|
|
82
|
-
// A valid object key and arbitrary byte content drive an additional
|
|
83
|
-
// round-trip so inputs genuinely vary across runs. See `keyArb` for why
|
|
84
|
-
// the key domain excludes path-relative / empty-segment / control-char
|
|
85
|
-
// keys that the two drivers cannot represent equivalently.
|
|
86
|
-
keyArb, fc.uint8Array(), async (key, content) => {
|
|
87
|
-
for (const { label, make } of DRIVERS) {
|
|
88
|
-
// 1. The full contract-conformance suite must pass for the driver.
|
|
89
|
-
const report = await runStorageDriverContract(make);
|
|
90
|
-
assert.equal(report.passed, true, `${label} driver must conform to the contract, got: ${JSON.stringify(report.results)}`);
|
|
91
|
-
assert.equal(report.results.length, storageDriverContractChecks.length, `${label} driver must run every contract check`);
|
|
92
|
-
// 2. An input-varying round-trip on a fresh driver instance.
|
|
93
|
-
const driver = await make();
|
|
94
|
-
await driver.put(key, content, {});
|
|
95
|
-
// put→get returns the exact stored bytes.
|
|
96
|
-
const found = await driver.get(key);
|
|
97
|
-
assert.equal(found.found, true, `${label}: get must find the stored key`);
|
|
98
|
-
assert.ok(found.found === true, `${label}: result must be the found variant`);
|
|
99
|
-
assert.deepEqual(found.bytes, content, `${label}: get must return the exact stored bytes`);
|
|
100
|
-
// exists reports presence.
|
|
101
|
-
assert.equal(await driver.exists(key), true, `${label}: exists must be true after put`);
|
|
102
|
-
// delete removes visibility.
|
|
103
|
-
await driver.delete(key);
|
|
104
|
-
assert.equal(await driver.exists(key), false, `${label}: exists must be false after delete`);
|
|
105
|
-
const missing = await driver.get(key);
|
|
106
|
-
assert.equal(missing.found, false, `${label}: get must report not-found after delete`);
|
|
107
|
-
}
|
|
108
|
-
}), { numRuns: 100 });
|
|
109
|
-
});
|
|
110
|
-
//# sourceMappingURL=prop-driver-conformance.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-driver-conformance.test.js","sourceRoot":"","sources":["../../src/tests/prop-driver-conformance.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-driver-equivalence.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-driver-equivalence.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
// Property-based test: Memory and Local drivers are observationally equivalent.
|
|
2
|
-
//
|
|
3
|
-
// Property 18 (Memory and Local drivers are observationally equivalent): for an
|
|
4
|
-
// arbitrary sequence of object operations (put/get/exists/delete/list/stat)
|
|
5
|
-
// applied identically to a `MemoryStorageDriver` and a `LocalStorageDriver`
|
|
6
|
-
// (both constructed with the SAME injected fixed clock, the Local driver bound
|
|
7
|
-
// to a fresh temp dir), the observable results are equivalent at every step —
|
|
8
|
-
// object existence, content bytes, and returned metadata (contentType, size,
|
|
9
|
-
// checksum, etag, accessLevel, owner, tenant, custom). The two zero-dependency
|
|
10
|
-
// drivers are interchangeable, so the same generated op sequence must produce
|
|
11
|
-
// the same observations on both.
|
|
12
|
-
//
|
|
13
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
14
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
15
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
16
|
-
//
|
|
17
|
-
// Feature: unified-storage-framework, Property 18: Memory and Local drivers are observationally equivalent
|
|
18
|
-
//
|
|
19
|
-
// Validates: Requirements 2.2, 26.6
|
|
20
|
-
import test from "node:test";
|
|
21
|
-
import assert from "node:assert/strict";
|
|
22
|
-
import * as fs from "node:fs/promises";
|
|
23
|
-
import * as os from "node:os";
|
|
24
|
-
import * as path from "node:path";
|
|
25
|
-
import fc from "fast-check";
|
|
26
|
-
import { MemoryStorageDriver } from "../drivers/memory.js";
|
|
27
|
-
import { LocalStorageDriver } from "../drivers/local.js";
|
|
28
|
-
/** A fixed clock so both drivers stamp identical timestamps for the same op. */
|
|
29
|
-
const fixedClock = () => 1_700_000_000_000;
|
|
30
|
-
/** The valid AccessLevel values (Requirement 11.1). */
|
|
31
|
-
const ACCESS_LEVELS = [
|
|
32
|
-
"public",
|
|
33
|
-
"private",
|
|
34
|
-
"signed",
|
|
35
|
-
"authenticated",
|
|
36
|
-
"role-based",
|
|
37
|
-
"tenant-aware",
|
|
38
|
-
];
|
|
39
|
-
/**
|
|
40
|
-
* A fixed pool of filesystem-safe keys. No key is a directory-component prefix
|
|
41
|
-
* of another (e.g. there is never both a file `docs` and a file `docs/x`), so
|
|
42
|
-
* the Local driver's on-disk layout can represent any subset the op sequence
|
|
43
|
-
* touches without a file/directory collision — keeping the two drivers on equal
|
|
44
|
-
* footing for the observable behavior under test.
|
|
45
|
-
*/
|
|
46
|
-
const KEYS = [
|
|
47
|
-
"alpha.txt",
|
|
48
|
-
"beta.txt",
|
|
49
|
-
"docs/one.txt",
|
|
50
|
-
"docs/two.txt",
|
|
51
|
-
"docs/sub/three.txt",
|
|
52
|
-
"images/a.png",
|
|
53
|
-
"images/b.png",
|
|
54
|
-
];
|
|
55
|
-
/** Prefixes exercised by `list`, including the empty (match-all) prefix. */
|
|
56
|
-
const PREFIXES = ["", "docs/", "docs/sub/", "images/", "alpha.txt", "doc", "images/a.png"];
|
|
57
|
-
const keyArb = fc.constantFrom(...KEYS);
|
|
58
|
-
const contentArb = fc.uint8Array({ minLength: 0, maxLength: 64 });
|
|
59
|
-
/** Custom metadata with JSON-round-trippable values so it can compare exactly. */
|
|
60
|
-
const customArb = fc.dictionary(fc.string({ maxLength: 12 }), fc.oneof(fc.string(), fc.integer(), fc.boolean()), { maxKeys: 4 });
|
|
61
|
-
/** Arbitrary write-time metadata; every field optional to cover the defaults. */
|
|
62
|
-
const writeMetadataArb = fc.record({
|
|
63
|
-
contentType: fc.string({ minLength: 1, maxLength: 30 }),
|
|
64
|
-
owner: fc.string({ minLength: 1, maxLength: 30 }),
|
|
65
|
-
tenant: fc.string({ minLength: 1, maxLength: 30 }),
|
|
66
|
-
accessLevel: fc.constantFrom(...ACCESS_LEVELS),
|
|
67
|
-
custom: customArb,
|
|
68
|
-
}, { requiredKeys: [] });
|
|
69
|
-
/** Optional list options; both drivers implement these identically. */
|
|
70
|
-
const listOptionsArb = fc.record({
|
|
71
|
-
limit: fc.integer({ min: 1, max: 5 }),
|
|
72
|
-
cursor: fc.constantFrom(...KEYS),
|
|
73
|
-
delimiter: fc.boolean(),
|
|
74
|
-
}, { requiredKeys: [] });
|
|
75
|
-
/** A single object operation applied identically to both drivers. */
|
|
76
|
-
const operationArb = fc.oneof(fc.record({ type: fc.constant("put"), key: keyArb, bytes: contentArb, meta: writeMetadataArb }), fc.record({ type: fc.constant("get"), key: keyArb }), fc.record({ type: fc.constant("exists"), key: keyArb }), fc.record({ type: fc.constant("delete"), key: keyArb }), fc.record({ type: fc.constant("stat"), key: keyArb }), fc.record({ type: fc.constant("list"), prefix: fc.constantFrom(...PREFIXES), options: listOptionsArb }));
|
|
77
|
-
const sequenceArb = fc.array(operationArb, { minLength: 1, maxLength: 30 });
|
|
78
|
-
/**
|
|
79
|
-
* Project a metadata record onto the observable field set the property compares.
|
|
80
|
-
* `owner`/`tenant` collapse absent-vs-undefined to `null` so a driver that
|
|
81
|
-
* persists metadata through JSON (which drops `undefined` keys) compares equal
|
|
82
|
-
* to one that keeps the key present with an `undefined` value.
|
|
83
|
-
*/
|
|
84
|
-
function projectMetadata(meta) {
|
|
85
|
-
if (meta === null || meta === undefined) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
key: meta.key,
|
|
90
|
-
size: meta.size,
|
|
91
|
-
contentType: meta.contentType,
|
|
92
|
-
checksum: meta.checksum,
|
|
93
|
-
etag: meta.etag,
|
|
94
|
-
accessLevel: meta.accessLevel,
|
|
95
|
-
owner: meta.owner ?? null,
|
|
96
|
-
tenant: meta.tenant ?? null,
|
|
97
|
-
// Spread into a plain object so a null-prototype custom map (as produced by
|
|
98
|
-
// fast-check's dictionary generator and kept verbatim by the in-memory
|
|
99
|
-
// driver) compares equal by content to the plain object the Local driver
|
|
100
|
-
// reconstructs from its JSON sidecar. The observable custom fields are the
|
|
101
|
-
// key/value pairs, not the object's internal prototype tag.
|
|
102
|
-
custom: { ...(meta.custom ?? {}) },
|
|
103
|
-
createdAt: meta.createdAt,
|
|
104
|
-
updatedAt: meta.updatedAt,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/** Apply one operation to a driver and return its canonical observation. */
|
|
108
|
-
async function applyOp(driver, op) {
|
|
109
|
-
switch (op.type) {
|
|
110
|
-
case "put": {
|
|
111
|
-
const meta = await driver.put(op.key, op.bytes, op.meta);
|
|
112
|
-
return { type: "put", meta: projectMetadata(meta) };
|
|
113
|
-
}
|
|
114
|
-
case "get": {
|
|
115
|
-
const result = await driver.get(op.key);
|
|
116
|
-
return {
|
|
117
|
-
type: "get",
|
|
118
|
-
found: result.found,
|
|
119
|
-
bytes: result.found ? Array.from(result.bytes) : null,
|
|
120
|
-
meta: result.found ? projectMetadata(result.metadata) : null,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
case "exists": {
|
|
124
|
-
return { type: "exists", exists: await driver.exists(op.key) };
|
|
125
|
-
}
|
|
126
|
-
case "delete": {
|
|
127
|
-
await driver.delete(op.key);
|
|
128
|
-
return { type: "delete" };
|
|
129
|
-
}
|
|
130
|
-
case "stat": {
|
|
131
|
-
return { type: "stat", meta: projectMetadata(await driver.stat(op.key)) };
|
|
132
|
-
}
|
|
133
|
-
case "list": {
|
|
134
|
-
const items = await driver.list(op.prefix, op.options);
|
|
135
|
-
return {
|
|
136
|
-
type: "list",
|
|
137
|
-
items: items.map((item) => ({ key: item.key, size: item.size, updatedAt: item.updatedAt })),
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
default:
|
|
141
|
-
throw new Error(`unknown op type: ${op.type}`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
test("Feature: unified-storage-framework, Property 18: Memory and Local drivers are observationally equivalent", async () => {
|
|
145
|
-
await fc.assert(fc.asyncProperty(sequenceArb, async (operations) => {
|
|
146
|
-
// Fresh temp dir + fresh drivers per run keep every sequence independent.
|
|
147
|
-
const root = await fs.mkdtemp(path.join(os.tmpdir(), "streetjs-driver-equiv-"));
|
|
148
|
-
const memory = new MemoryStorageDriver({ clock: fixedClock });
|
|
149
|
-
const local = new LocalStorageDriver({ root, clock: fixedClock });
|
|
150
|
-
try {
|
|
151
|
-
for (let i = 0; i < operations.length; i++) {
|
|
152
|
-
const op = operations[i];
|
|
153
|
-
const memObs = await applyOp(memory, op);
|
|
154
|
-
const localObs = await applyOp(local, op);
|
|
155
|
-
assert.deepEqual(localObs, memObs, `observation diverged at step ${i} for op ${JSON.stringify(op.type)} (key=${"key" in op ? op.key : op.prefix})`);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
finally {
|
|
159
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
160
|
-
}
|
|
161
|
-
}), { numRuns: 100 });
|
|
162
|
-
});
|
|
163
|
-
//# sourceMappingURL=prop-driver-equivalence.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-driver-equivalence.test.js","sourceRoot":"","sources":["../../src/tests/prop-driver-equivalence.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-lifecycle.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-lifecycle.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's lifecycle engine (task 15.2).
|
|
2
|
-
//
|
|
3
|
-
// Property 14: Lifecycle action applies exactly once. For an arbitrary set of
|
|
4
|
-
// objects (each placed at a controllable age) and a `delete-after-days` rule
|
|
5
|
-
// with an arbitrary day threshold, evaluating the rule via
|
|
6
|
-
// `storage.applyLifecycle(rule)` at a fixed clock instant actions each
|
|
7
|
-
// qualifying object EXACTLY ONCE:
|
|
8
|
-
//
|
|
9
|
-
// - the first evaluation's outcomes are exactly the set of objects whose age
|
|
10
|
-
// meets the threshold (one `deleted` outcome per qualifying object), and
|
|
11
|
-
// - a second evaluation of the same rule at the same clock instant produces
|
|
12
|
-
// no further outcomes, because every actioned object has been removed from
|
|
13
|
-
// the space a subsequent scan enumerates.
|
|
14
|
-
//
|
|
15
|
-
// A controllable clock makes object ages deterministic: each object is written
|
|
16
|
-
// at `now - ageDays` so its age at evaluation time is exactly `ageDays`. Backed
|
|
17
|
-
// by the zero-dependency in-memory provider (no native `lifecycle` capability,
|
|
18
|
-
// so the engine simulates evaluation over the driver primitives). Exercised
|
|
19
|
-
// with fast-check at { numRuns: 100 }; executed via the Node.js built-in test
|
|
20
|
-
// runner (`node --test dist/tests/*.test.js`).
|
|
21
|
-
//
|
|
22
|
-
// Feature: unified-storage-framework, Property 14
|
|
23
|
-
// Validates: Requirements 13.2, 26.6
|
|
24
|
-
import test from "node:test";
|
|
25
|
-
import assert from "node:assert/strict";
|
|
26
|
-
import fc from "fast-check";
|
|
27
|
-
import { createStorage } from "../index.js";
|
|
28
|
-
import { MemoryStorageDriver } from "../drivers/memory.js";
|
|
29
|
-
const DAY = 24 * 60 * 60 * 1000;
|
|
30
|
-
// A fixed evaluation instant, chosen large enough that every object's write
|
|
31
|
-
// time (`NOW - ageDays * DAY`) stays positive for the age ranges used here.
|
|
32
|
-
const NOW = 1_700_000_000_000;
|
|
33
|
-
test("Feature: unified-storage-framework, Property 14 — lifecycle action applies exactly once", { concurrency: false }, async () => {
|
|
34
|
-
await fc.assert(fc.asyncProperty(
|
|
35
|
-
// An arbitrary set of objects with unique, application-visible keys
|
|
36
|
-
// (never a reserved bookkeeping prefix, which age-based rules skip),
|
|
37
|
-
// each with a deterministic age in days and arbitrary byte content.
|
|
38
|
-
fc.uniqueArray(fc.record({
|
|
39
|
-
key: fc
|
|
40
|
-
.string({ minLength: 1 })
|
|
41
|
-
.filter((k) => !k.startsWith(".") && k.trim().length > 0),
|
|
42
|
-
ageDays: fc.integer({ min: 0, max: 60 }),
|
|
43
|
-
content: fc.uint8Array(),
|
|
44
|
-
}), { selector: (o) => o.key, maxLength: 12 }),
|
|
45
|
-
// An arbitrary day threshold for the delete-after-days rule.
|
|
46
|
-
fc.integer({ min: 1, max: 30 }), async (objects, thresholdDays) => {
|
|
47
|
-
// A controllable clock shared by the driver and the facade so both
|
|
48
|
-
// object creation time and lifecycle age are deterministic.
|
|
49
|
-
let clockValue = NOW;
|
|
50
|
-
const clock = () => clockValue;
|
|
51
|
-
const driver = new MemoryStorageDriver({ clock });
|
|
52
|
-
const storage = createStorage({ provider: "memory", driver, clock });
|
|
53
|
-
// Place each object so its age at NOW is exactly `ageDays`.
|
|
54
|
-
for (const { key, ageDays, content } of objects) {
|
|
55
|
-
clockValue = NOW - ageDays * DAY;
|
|
56
|
-
await storage.put(key, content);
|
|
57
|
-
}
|
|
58
|
-
// Evaluate the rule at the fixed instant NOW.
|
|
59
|
-
clockValue = NOW;
|
|
60
|
-
const rule = { type: "delete-after-days", days: thresholdDays };
|
|
61
|
-
// The qualifying set: objects at least `thresholdDays` old.
|
|
62
|
-
const expectedKeys = objects
|
|
63
|
-
.filter((o) => o.ageDays >= thresholdDays)
|
|
64
|
-
.map((o) => o.key)
|
|
65
|
-
.sort();
|
|
66
|
-
const first = await storage.applyLifecycle(rule);
|
|
67
|
-
// Every outcome is a delete, and the actioned keys are exactly the
|
|
68
|
-
// qualifying set — each qualifying object actioned exactly once.
|
|
69
|
-
assert.ok(first.every((o) => o.action === "deleted"));
|
|
70
|
-
assert.deepEqual(first.map((o) => o.key).sort(), expectedKeys);
|
|
71
|
-
// No duplicate outcomes within a single evaluation.
|
|
72
|
-
assert.equal(new Set(first.map((o) => o.key)).size, first.length);
|
|
73
|
-
// A second evaluation at the same instant produces no further
|
|
74
|
-
// outcomes: already-actioned objects are not re-actioned.
|
|
75
|
-
const second = await storage.applyLifecycle(rule);
|
|
76
|
-
assert.deepEqual(second, []);
|
|
77
|
-
// Qualifying objects are gone; non-qualifying objects remain.
|
|
78
|
-
for (const { key, ageDays } of objects) {
|
|
79
|
-
assert.equal(await storage.exists(key), ageDays < thresholdDays);
|
|
80
|
-
}
|
|
81
|
-
}), { numRuns: 100 });
|
|
82
|
-
});
|
|
83
|
-
//# sourceMappingURL=prop-lifecycle.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-lifecycle.test.js","sourceRoot":"","sources":["../../src/tests/prop-lifecycle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-list.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-list.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade `list(prefix)` operation.
|
|
2
|
-
//
|
|
3
|
-
// Feature: unified-storage-framework, Property 6 — List returns exactly the
|
|
4
|
-
// prefix-matching keys. For an arbitrary set of stored objects and an arbitrary
|
|
5
|
-
// prefix, `list(prefix)` returns exactly the set of stored keys that begin with
|
|
6
|
-
// that prefix: no key that starts with the prefix is missing, and no key that
|
|
7
|
-
// does not start with the prefix is included.
|
|
8
|
-
//
|
|
9
|
-
// Uses the public facade via `createStorage({ provider: 'memory' })`, the
|
|
10
|
-
// Node.js built-in test runner (node:test), and fast-check configured with
|
|
11
|
-
// { numRuns: 100 }. Executed via `node --test dist/tests/*.test.js`.
|
|
12
|
-
//
|
|
13
|
-
// Validates: Requirements 4.9
|
|
14
|
-
import test from "node:test";
|
|
15
|
-
import assert from "node:assert/strict";
|
|
16
|
-
import fc from "fast-check";
|
|
17
|
-
import { createStorage } from "../index.js";
|
|
18
|
-
// A key generator that produces non-empty keys drawn from a small alphabet so
|
|
19
|
-
// that shared prefixes arise frequently, exercising the prefix-matching logic
|
|
20
|
-
// on both matching and non-matching keys.
|
|
21
|
-
const keyArb = fc.stringMatching(/^[a-c/]{1,6}$/).filter((k) => k.length > 0);
|
|
22
|
-
test("Feature: unified-storage-framework, Property 6 — list returns exactly the prefix-matching keys", async () => {
|
|
23
|
-
await fc.assert(fc.asyncProperty(
|
|
24
|
-
// A set of unique keys, each paired with arbitrary string content.
|
|
25
|
-
fc.uniqueArray(fc.tuple(keyArb, fc.string()), {
|
|
26
|
-
selector: ([key]) => key,
|
|
27
|
-
minLength: 0,
|
|
28
|
-
maxLength: 12,
|
|
29
|
-
}),
|
|
30
|
-
// An arbitrary prefix, possibly empty, possibly unrelated to any key.
|
|
31
|
-
fc.stringMatching(/^[a-c/]{0,4}$/), async (entries, prefix) => {
|
|
32
|
-
const storage = createStorage({ provider: "memory" });
|
|
33
|
-
for (const [key, content] of entries) {
|
|
34
|
-
await storage.put(key, content, {});
|
|
35
|
-
}
|
|
36
|
-
const listed = await storage.list(prefix);
|
|
37
|
-
// Observed keys returned by list(prefix).
|
|
38
|
-
const observed = new Set(listed.map((item) => item.key));
|
|
39
|
-
// Expected keys: exactly the stored keys that start with the prefix.
|
|
40
|
-
const expected = new Set(entries
|
|
41
|
-
.map(([key]) => key)
|
|
42
|
-
.filter((key) => key.startsWith(prefix)));
|
|
43
|
-
// Same cardinality and same membership => exactly equal sets.
|
|
44
|
-
assert.equal(observed.size, expected.size);
|
|
45
|
-
for (const key of expected) {
|
|
46
|
-
assert.ok(observed.has(key), `expected listed key: ${key}`);
|
|
47
|
-
}
|
|
48
|
-
for (const key of observed) {
|
|
49
|
-
assert.ok(key.startsWith(prefix), `unexpected non-matching key listed: ${key}`);
|
|
50
|
-
}
|
|
51
|
-
}), { numRuns: 100 });
|
|
52
|
-
});
|
|
53
|
-
//# sourceMappingURL=prop-list.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-list.test.js","sourceRoot":"","sources":["../../src/tests/prop-list.test.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,gFAAgF;AAChF,8EAA8E;AAC9E,8CAA8C;AAC9C,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,qEAAqE;AACrE,EAAE;AACF,8BAA8B;AAE9B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,8EAA8E;AAC9E,8EAA8E;AAC9E,0CAA0C;AAC1C,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAE9E,IAAI,CACF,gGAAgG,EAChG,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa;IACd,mEAAmE;IACnE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE;QAC5C,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG;QACxB,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,EAAE;KACd,CAAC;IACF,sEAAsE;IACtE,EAAE,CAAC,cAAc,CAAC,eAAe,CAAC,EAClC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtD,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;YACrC,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE1C,0CAA0C;QAC1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzD,qEAAqE;QACrE,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,OAAO;aACJ,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC;aACnB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAC3C,CAAC;QAEF,8DAA8D;QAC9D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,wBAAwB,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,EAAE,CACP,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EACtB,uCAAuC,GAAG,EAAE,CAC7C,CAAC;QACJ,CAAC;IACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-metadata.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-metadata.test.ts"],"names":[],"mappings":""}
|