@streetjs/storage 1.0.0 → 1.0.2
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/dist/tests/contract.d.ts +19 -0
- package/dist/tests/contract.d.ts.map +1 -1
- package/dist/tests/contract.js +28 -0
- package/dist/tests/contract.js.map +1 -1
- package/package.json +10 -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.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,65 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's multipart upload guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 8 (Multipart equals a single upload): for arbitrary content split
|
|
4
|
-
// into arbitrary ordered parts, performing a multipart upload
|
|
5
|
-
// (`createMultipartUpload` → `uploadPart` for each part in order →
|
|
6
|
-
// `completeMultipartUpload`) produces an object whose bytes are exactly equal
|
|
7
|
-
// to a single `put` of the concatenation of those parts. Equality is checked
|
|
8
|
-
// both by the raw stored bytes and by the content checksum the drivers compute,
|
|
9
|
-
// so the multipart assembly path is proven observationally identical to the
|
|
10
|
-
// single-shot write path (Requirement 6.3). Both uploads run over the
|
|
11
|
-
// zero-dependency `memory` provider — the identical code path every provider
|
|
12
|
-
// shares — exercised via the public facade.
|
|
13
|
-
//
|
|
14
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
15
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
16
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
17
|
-
//
|
|
18
|
-
// Feature: unified-storage-framework, Property 8: Multipart equals a single upload
|
|
19
|
-
//
|
|
20
|
-
// Validates: Requirements 6.3, 26.5
|
|
21
|
-
import test from "node:test";
|
|
22
|
-
import assert from "node:assert/strict";
|
|
23
|
-
import { Buffer } from "node:buffer";
|
|
24
|
-
import fc from "fast-check";
|
|
25
|
-
import { createStorage } from "../facade.js";
|
|
26
|
-
test("Feature: unified-storage-framework, Property 8: Multipart equals a single upload", async () => {
|
|
27
|
-
await fc.assert(fc.asyncProperty(
|
|
28
|
-
// A key for both objects and an arbitrary ordered list of parts. At
|
|
29
|
-
// least one part is generated so there is always something to upload;
|
|
30
|
-
// individual parts may be empty, exercising the assembly of zero-length
|
|
31
|
-
// segments.
|
|
32
|
-
fc.string(), fc.array(fc.uint8Array(), { minLength: 1, maxLength: 8 }), async (key, parts) => {
|
|
33
|
-
// A fresh store per run keeps each key/parts pair independent.
|
|
34
|
-
const storage = createStorage({ provider: "memory" });
|
|
35
|
-
// The concatenation of the parts, in the order they will be uploaded,
|
|
36
|
-
// is the exact byte sequence a single `put` would persist.
|
|
37
|
-
const concatenated = Buffer.concat(parts.map((part) => Buffer.from(part)));
|
|
38
|
-
// ── Multipart upload path ─────────────────────────────────────────
|
|
39
|
-
const multipartKey = `${key}/multipart`;
|
|
40
|
-
const uploadId = await storage.createMultipartUpload(multipartKey);
|
|
41
|
-
const storedParts = [];
|
|
42
|
-
for (let index = 0; index < parts.length; index += 1) {
|
|
43
|
-
// Part numbers are 1-based positive integers assigned in order.
|
|
44
|
-
const stored = await storage.uploadPart(uploadId, index + 1, parts[index]);
|
|
45
|
-
storedParts.push(stored);
|
|
46
|
-
}
|
|
47
|
-
const multipartMeta = await storage.completeMultipartUpload(uploadId, storedParts);
|
|
48
|
-
// ── Single upload path ────────────────────────────────────────────
|
|
49
|
-
const singleKey = `${key}/single`;
|
|
50
|
-
const singleMeta = await storage.put(singleKey, concatenated);
|
|
51
|
-
// The assembled object must equal a single put of the concatenation,
|
|
52
|
-
// both in raw bytes and in the computed content checksum.
|
|
53
|
-
const multipartResult = await storage.get(multipartKey);
|
|
54
|
-
const singleResult = await storage.get(singleKey);
|
|
55
|
-
assert.equal(multipartResult.found, true);
|
|
56
|
-
assert.equal(singleResult.found, true);
|
|
57
|
-
assert.ok(multipartResult.bytes);
|
|
58
|
-
assert.ok(singleResult.bytes);
|
|
59
|
-
assert.deepEqual(Buffer.from(multipartResult.bytes), Buffer.from(singleResult.bytes));
|
|
60
|
-
assert.deepEqual(Buffer.from(multipartResult.bytes), concatenated);
|
|
61
|
-
assert.equal(multipartMeta.checksum, singleMeta.checksum);
|
|
62
|
-
assert.equal(multipartMeta.size, singleMeta.size);
|
|
63
|
-
}), { numRuns: 100 });
|
|
64
|
-
});
|
|
65
|
-
//# sourceMappingURL=prop-multipart.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-multipart.test.js","sourceRoot":"","sources":["../../src/tests/prop-multipart.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-resumable.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-resumable.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// Property-based test for the resumable upload equivalence guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 10 (Resumable equals uninterrupted): for arbitrary content, a
|
|
4
|
-
// resumable upload — optionally interrupted partway (a first `resumeUpload`
|
|
5
|
-
// whose source stream errors after emitting a prefix) and then resumed with the
|
|
6
|
-
// object's full content — produces an object byte-identical to an equivalent
|
|
7
|
-
// single, uninterrupted `put` of the same content on a separate store. The
|
|
8
|
-
// upload is driven through `startUpload` → (optional failing `resumeUpload`) →
|
|
9
|
-
// `resumeUpload(full stream)`; the resulting bytes and checksum are compared
|
|
10
|
-
// against a plain `put` on an independent `memory` store.
|
|
11
|
-
//
|
|
12
|
-
// This exercises the facade's ResumableManager over the zero-dependency
|
|
13
|
-
// `memory` provider, driving the identical offset-tracked resume code path
|
|
14
|
-
// every provider shares (Requirements 7.2, 7.3), and asserts the cross-path
|
|
15
|
-
// determinism the framework guarantees (Requirement 26.5).
|
|
16
|
-
//
|
|
17
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
18
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
19
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
20
|
-
//
|
|
21
|
-
// Feature: unified-storage-framework, Property 10: Resumable equals uninterrupted
|
|
22
|
-
//
|
|
23
|
-
// Validates: Requirements 7.2, 7.3, 26.5
|
|
24
|
-
import test from "node:test";
|
|
25
|
-
import assert from "node:assert/strict";
|
|
26
|
-
import { Readable } from "node:stream";
|
|
27
|
-
import { Buffer } from "node:buffer";
|
|
28
|
-
import fc from "fast-check";
|
|
29
|
-
import { createStorage } from "../facade.js";
|
|
30
|
-
test("Feature: unified-storage-framework, Property 10: Resumable equals uninterrupted", async () => {
|
|
31
|
-
await fc.assert(fc.asyncProperty(fc.string(), fc.uint8Array(),
|
|
32
|
-
// `interrupt` decides whether the upload is interrupted before its
|
|
33
|
-
// final resume; `prefixLen` (bounded to the content) picks how many
|
|
34
|
-
// bytes the interrupted resume persists before erroring.
|
|
35
|
-
fc.boolean(), fc.nat(), async (key, content, interrupt, prefixLen) => {
|
|
36
|
-
const payload = Buffer.from(content);
|
|
37
|
-
// The resumable store: start a session, optionally interrupt, then
|
|
38
|
-
// resume with the FULL content.
|
|
39
|
-
const resumableStore = createStorage({ provider: "memory" });
|
|
40
|
-
const sessionId = await resumableStore.startUpload(key, {});
|
|
41
|
-
if (interrupt && payload.byteLength > 0) {
|
|
42
|
-
// Emit a prefix of the content then error partway, simulating a
|
|
43
|
-
// network interruption. Only the prefix is persisted (Req 7.2).
|
|
44
|
-
const cut = prefixLen % payload.byteLength;
|
|
45
|
-
const prefix = payload.subarray(0, cut);
|
|
46
|
-
const failing = new Readable({
|
|
47
|
-
read() {
|
|
48
|
-
if (prefix.byteLength > 0) {
|
|
49
|
-
this.push(prefix);
|
|
50
|
-
}
|
|
51
|
-
this.destroy(new Error("network interruption"));
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
await assert.rejects(() => resumableStore.resumeUpload(sessionId, failing), /network interruption/);
|
|
55
|
-
// No final object exists yet after an interrupted resume.
|
|
56
|
-
assert.equal(await resumableStore.exists(key), false);
|
|
57
|
-
}
|
|
58
|
-
// Resume with the full content: the manager appends only the bytes
|
|
59
|
-
// beyond the persisted offset and completes (Req 7.3).
|
|
60
|
-
const resumedMeta = await resumableStore.resumeUpload(sessionId, Readable.from([payload]));
|
|
61
|
-
// The reference store: a single, uninterrupted put of the same bytes.
|
|
62
|
-
const referenceStore = createStorage({ provider: "memory" });
|
|
63
|
-
const singleMeta = await referenceStore.put(key, new Uint8Array(payload), {});
|
|
64
|
-
// Byte-identical object: same size and checksum as the single put.
|
|
65
|
-
assert.equal(resumedMeta.size, singleMeta.size);
|
|
66
|
-
assert.equal(resumedMeta.checksum, singleMeta.checksum);
|
|
67
|
-
// And the stored bytes read back equal on both stores.
|
|
68
|
-
const resumedGet = await resumableStore.get(key);
|
|
69
|
-
const referenceGet = await referenceStore.get(key);
|
|
70
|
-
assert.equal(resumedGet.found, true);
|
|
71
|
-
assert.equal(referenceGet.found, true);
|
|
72
|
-
assert.ok(resumedGet.bytes);
|
|
73
|
-
assert.ok(referenceGet.bytes);
|
|
74
|
-
assert.deepEqual(Buffer.from(resumedGet.bytes), payload);
|
|
75
|
-
assert.deepEqual(Buffer.from(resumedGet.bytes), Buffer.from(referenceGet.bytes));
|
|
76
|
-
}), { numRuns: 100 });
|
|
77
|
-
});
|
|
78
|
-
//# sourceMappingURL=prop-resumable.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-resumable.test.js","sourceRoot":"","sources":["../../src/tests/prop-resumable.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-search.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-search.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade `search(filters)` operation.
|
|
2
|
-
//
|
|
3
|
-
// Feature: unified-storage-framework, Property 15 — Search returns exactly the
|
|
4
|
-
// matching objects. For an arbitrary set of stored objects (with varied
|
|
5
|
-
// owner/tenant/contentType/size/custom metadata) and an arbitrary combination
|
|
6
|
-
// of SearchFilters, `storage.search(filters)` returns EXACTLY the set of
|
|
7
|
-
// objects that satisfy EVERY supplied filter (conjunctive / AND semantics):
|
|
8
|
-
// no matching object is missing and no non-matching object is included. When
|
|
9
|
-
// no object satisfies the filters, the result is the empty set.
|
|
10
|
-
//
|
|
11
|
-
// The expected set is computed independently of the implementation and
|
|
12
|
-
// compared for exact set equality.
|
|
13
|
-
//
|
|
14
|
-
// Uses the public facade via `createStorage({ provider: 'memory' })`, the
|
|
15
|
-
// Node.js built-in test runner (node:test), and fast-check configured with
|
|
16
|
-
// { numRuns: 100 }. Executed via `node --test dist/tests/*.test.js`.
|
|
17
|
-
//
|
|
18
|
-
// Validates: Requirements 16.2, 16.3
|
|
19
|
-
import test from "node:test";
|
|
20
|
-
import assert from "node:assert/strict";
|
|
21
|
-
import fc from "fast-check";
|
|
22
|
-
import { createStorage } from "../index.js";
|
|
23
|
-
// UTF-8 byte length, matching how the facade encodes string payloads before
|
|
24
|
-
// the driver records `size`.
|
|
25
|
-
const byteSize = (content) => new TextEncoder().encode(content).length;
|
|
26
|
-
// Domains kept small so filters match frequently, exercising both the
|
|
27
|
-
// "matches" and "excludes nothing/everything" branches.
|
|
28
|
-
const ownerArb = fc.option(fc.constantFrom("alice", "bob"), { nil: undefined });
|
|
29
|
-
const tenantArb = fc.option(fc.constantFrom("acme", "globex"), { nil: undefined });
|
|
30
|
-
const contentTypeArb = fc.constantFrom("image/jpeg", "image/png", "text/plain");
|
|
31
|
-
const categoryArb = fc.option(fc.constantFrom("invoice", "receipt"), { nil: undefined });
|
|
32
|
-
// Keys drawn from a small alphabet so shared prefixes arise often. The alphabet
|
|
33
|
-
// excludes '.', so no key collides with the reserved internal key spaces.
|
|
34
|
-
const keyArb = fc.stringMatching(/^[a-c/]{1,6}$/).filter((k) => k.length > 0);
|
|
35
|
-
// An object to store: a key, content (whose byte length gives size), and
|
|
36
|
-
// varied metadata.
|
|
37
|
-
const objectArb = fc.record({
|
|
38
|
-
key: keyArb,
|
|
39
|
-
content: fc.string({ maxLength: 6 }),
|
|
40
|
-
owner: ownerArb,
|
|
41
|
-
tenant: tenantArb,
|
|
42
|
-
contentType: contentTypeArb,
|
|
43
|
-
category: categoryArb,
|
|
44
|
-
});
|
|
45
|
-
// Arbitrary SearchFilters. Every field is optional (undefined => no
|
|
46
|
-
// constraint). Filter domains deliberately include values that may match
|
|
47
|
-
// nothing (e.g. owner "carol") so the empty-result case is covered.
|
|
48
|
-
const filtersArb = fc.record({
|
|
49
|
-
prefix: fc.option(fc.stringMatching(/^[a-c/]{0,3}$/), { nil: undefined }),
|
|
50
|
-
contentType: fc.option(fc.constantFrom("image/jpeg", "image/png", "text/plain", "application/pdf"), {
|
|
51
|
-
nil: undefined,
|
|
52
|
-
}),
|
|
53
|
-
owner: fc.option(fc.constantFrom("alice", "bob", "carol"), { nil: undefined }),
|
|
54
|
-
tenant: fc.option(fc.constantFrom("acme", "globex", "initech"), { nil: undefined }),
|
|
55
|
-
minSize: fc.option(fc.integer({ min: 0, max: 6 }), { nil: undefined }),
|
|
56
|
-
maxSize: fc.option(fc.integer({ min: 0, max: 6 }), { nil: undefined }),
|
|
57
|
-
metadata: fc.option(fc.constantFrom({ category: "invoice" }, { category: "receipt" }), {
|
|
58
|
-
nil: undefined,
|
|
59
|
-
}),
|
|
60
|
-
});
|
|
61
|
-
// Independent reference implementation of the AND-semantics filter, evaluated
|
|
62
|
-
// against the known write-time metadata of a stored object.
|
|
63
|
-
function satisfies(obj, filters) {
|
|
64
|
-
const size = byteSize(obj.content);
|
|
65
|
-
const custom = obj.category !== undefined ? { category: obj.category } : {};
|
|
66
|
-
if (filters.prefix !== undefined && !obj.key.startsWith(filters.prefix))
|
|
67
|
-
return false;
|
|
68
|
-
if (filters.contentType !== undefined && obj.contentType !== filters.contentType)
|
|
69
|
-
return false;
|
|
70
|
-
if (filters.owner !== undefined && obj.owner !== filters.owner)
|
|
71
|
-
return false;
|
|
72
|
-
if (filters.tenant !== undefined && obj.tenant !== filters.tenant)
|
|
73
|
-
return false;
|
|
74
|
-
if (filters.minSize !== undefined && size < filters.minSize)
|
|
75
|
-
return false;
|
|
76
|
-
if (filters.maxSize !== undefined && size > filters.maxSize)
|
|
77
|
-
return false;
|
|
78
|
-
if (filters.metadata !== undefined) {
|
|
79
|
-
for (const [field, value] of Object.entries(filters.metadata)) {
|
|
80
|
-
if (custom[field] !== value)
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
test("Feature: unified-storage-framework, Property 15 — search returns exactly the matching objects", async () => {
|
|
87
|
-
await fc.assert(fc.asyncProperty(fc.uniqueArray(objectArb, {
|
|
88
|
-
selector: (obj) => obj.key,
|
|
89
|
-
minLength: 0,
|
|
90
|
-
maxLength: 12,
|
|
91
|
-
}), filtersArb, async (objects, filters) => {
|
|
92
|
-
const storage = createStorage({ provider: "memory" });
|
|
93
|
-
for (const obj of objects) {
|
|
94
|
-
const metadata = {
|
|
95
|
-
contentType: obj.contentType,
|
|
96
|
-
};
|
|
97
|
-
if (obj.owner !== undefined)
|
|
98
|
-
metadata.owner = obj.owner;
|
|
99
|
-
if (obj.tenant !== undefined)
|
|
100
|
-
metadata.tenant = obj.tenant;
|
|
101
|
-
if (obj.category !== undefined)
|
|
102
|
-
metadata.custom = { category: obj.category };
|
|
103
|
-
await storage.put(obj.key, obj.content, metadata);
|
|
104
|
-
}
|
|
105
|
-
const result = await storage.search(filters);
|
|
106
|
-
const observed = new Set(result.map((item) => item.key));
|
|
107
|
-
// Expected: exactly the stored keys whose object satisfies every filter.
|
|
108
|
-
const expected = new Set(objects.filter((obj) => satisfies(obj, filters)).map((obj) => obj.key));
|
|
109
|
-
// Exact set equality: same cardinality + same membership (no extras,
|
|
110
|
-
// none missing). An empty expected set implies an empty result.
|
|
111
|
-
assert.equal(observed.size, expected.size, `size mismatch: observed ${[...observed]} vs expected ${[...expected]}`);
|
|
112
|
-
for (const key of expected) {
|
|
113
|
-
assert.ok(observed.has(key), `missing matching key: ${key}`);
|
|
114
|
-
}
|
|
115
|
-
for (const key of observed) {
|
|
116
|
-
assert.ok(expected.has(key), `unexpected non-matching key: ${key}`);
|
|
117
|
-
}
|
|
118
|
-
}), { numRuns: 100 });
|
|
119
|
-
});
|
|
120
|
-
//# sourceMappingURL=prop-search.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-search.test.js","sourceRoot":"","sources":["../../src/tests/prop-search.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-signed-url.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-signed-url.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's signed URL expiry guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 11 (Signed URL expiry is honored): for an arbitrary key, operation
|
|
4
|
-
// (GET/PUT/DELETE), and expiry window, a signed URL minted at time T with
|
|
5
|
-
// `expiresInMs = E` verifies as VALID for its authorized operation when checked
|
|
6
|
-
// at any instant strictly before `T + E`, and verifies as INVALID with reason
|
|
7
|
-
// `'expired'` when checked at any instant at or after `T + E`.
|
|
8
|
-
//
|
|
9
|
-
// Time is made deterministic with an injected, controllable clock passed to
|
|
10
|
-
// `createStorage({ provider: 'memory', signingSecret, clock })`. The facade
|
|
11
|
-
// mints the URL over the zero-dependency memory provider (which has no native
|
|
12
|
-
// signed-URL capability, so the HMAC simulation path runs). A second
|
|
13
|
-
// `SignedUrlService` constructed with the SAME signing secret verifies the URL
|
|
14
|
-
// at an explicit check time via its `verify(url, op, now)` path, exercising the
|
|
15
|
-
// same code every provider shares (Requirements 8.1, 8.3, 8.4, 26.6).
|
|
16
|
-
//
|
|
17
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
18
|
-
// generation, executed via `node --test dist/tests/*.test.js`, configured with
|
|
19
|
-
// { numRuns: 100 } per the design's property-testing contract.
|
|
20
|
-
//
|
|
21
|
-
// Feature: unified-storage-framework, Property 11: Signed URL expiry is honored
|
|
22
|
-
//
|
|
23
|
-
// Validates: Requirements 8.1, 8.3, 8.4, 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 "../facade.js";
|
|
28
|
-
import { SignedUrlService } from "../signed-url.js";
|
|
29
|
-
const SIGNING_SECRET = "prop-11-signing-secret";
|
|
30
|
-
test("Feature: unified-storage-framework, Property 11: Signed URL expiry is honored", async () => {
|
|
31
|
-
await fc.assert(fc.asyncProperty(
|
|
32
|
-
// An arbitrary object key.
|
|
33
|
-
fc.string(),
|
|
34
|
-
// The single operation the URL authorizes (Requirement 8.1).
|
|
35
|
-
fc.constantFrom("GET", "PUT", "DELETE"),
|
|
36
|
-
// The mint instant T as epoch milliseconds.
|
|
37
|
-
fc.integer({ min: 0, max: 2 ** 40 }),
|
|
38
|
-
// A strictly-positive expiry window E, so the URL is valid at mint time.
|
|
39
|
-
fc.integer({ min: 1, max: 2 ** 32 }),
|
|
40
|
-
// An offset relative to the expiry instant (T + E). A negative offset
|
|
41
|
-
// lands strictly before expiry (must be VALID); a non-negative offset
|
|
42
|
-
// lands at or after expiry (must be 'expired'). The range straddles zero
|
|
43
|
-
// so both branches are exercised across the 100 runs.
|
|
44
|
-
fc.integer({ min: -(2 ** 20), max: 2 ** 20 }), async (key, op, mintTime, expiresInMs, offsetFromExpiry) => {
|
|
45
|
-
// A controllable clock so minting stamps expiry as T + E deterministically.
|
|
46
|
-
let now = mintTime;
|
|
47
|
-
const clock = () => now;
|
|
48
|
-
const storage = createStorage({
|
|
49
|
-
provider: "memory",
|
|
50
|
-
signingSecret: SIGNING_SECRET,
|
|
51
|
-
clock,
|
|
52
|
-
});
|
|
53
|
-
// Mint through the facade at time T; expiry = T + E.
|
|
54
|
-
const url = await storage.signedUrl(key, op, { expiresInMs });
|
|
55
|
-
const expiry = mintTime + expiresInMs;
|
|
56
|
-
// Independent verifier sharing only the secret; the check time is
|
|
57
|
-
// supplied explicitly so expiry is driven deterministically.
|
|
58
|
-
const verifier = new SignedUrlService({ signingSecret: SIGNING_SECRET });
|
|
59
|
-
const checkTime = expiry + offsetFromExpiry;
|
|
60
|
-
const verification = verifier.verify(url, op, checkTime);
|
|
61
|
-
if (checkTime < expiry) {
|
|
62
|
-
// Strictly before T + E: the URL is valid for its authorized op.
|
|
63
|
-
assert.equal(verification.valid, true);
|
|
64
|
-
assert.equal(verification.key, key);
|
|
65
|
-
assert.equal(verification.op, op);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
// At or after T + E: the URL is invalid, specifically 'expired'.
|
|
69
|
-
assert.equal(verification.valid, false);
|
|
70
|
-
assert.equal(verification.reason, "expired");
|
|
71
|
-
}
|
|
72
|
-
}), { numRuns: 100 });
|
|
73
|
-
});
|
|
74
|
-
//# sourceMappingURL=prop-signed-url.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-signed-url.test.js","sourceRoot":"","sources":["../../src/tests/prop-signed-url.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-streaming.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-streaming.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade streaming round-trip guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 7 (Streaming preserves bytes): for arbitrary keys and byte contents,
|
|
4
|
-
// persisting bytes with `putStream(key, Readable.from([bytes]))` and then
|
|
5
|
-
// reading them back with `getStream(key)` (collecting every emitted chunk)
|
|
6
|
-
// yields content bytes exactly equal to the original input. This exercises the
|
|
7
|
-
// facade over the zero-dependency `memory` provider, driving the identical
|
|
8
|
-
// streaming code path every provider shares (Requirement 5.1, 5.2, 5.4).
|
|
9
|
-
//
|
|
10
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
11
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
12
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
13
|
-
//
|
|
14
|
-
// Feature: unified-storage-framework, Property 7: Streaming preserves bytes
|
|
15
|
-
//
|
|
16
|
-
// Validates: Requirements 5.1, 5.2, 5.4
|
|
17
|
-
import test from "node:test";
|
|
18
|
-
import assert from "node:assert/strict";
|
|
19
|
-
import { Readable } from "node:stream";
|
|
20
|
-
import { buffer as streamToBuffer } from "node:stream/consumers";
|
|
21
|
-
import fc from "fast-check";
|
|
22
|
-
import { createStorage } from "../facade.js";
|
|
23
|
-
test("Feature: unified-storage-framework, Property 7: Streaming preserves bytes", async () => {
|
|
24
|
-
await fc.assert(fc.asyncProperty(fc.string(), fc.uint8Array(), async (key, content) => {
|
|
25
|
-
// A fresh store per run keeps each key/content pair independent.
|
|
26
|
-
const storage = createStorage({ provider: "memory" });
|
|
27
|
-
// Build the source stream from the raw bytes and stream it in.
|
|
28
|
-
await storage.putStream(key, Readable.from([Buffer.from(content)]));
|
|
29
|
-
// Collect all emitted chunks from the readable back into a buffer.
|
|
30
|
-
const out = await streamToBuffer(await storage.getStream(key));
|
|
31
|
-
assert.deepEqual(new Uint8Array(out), content);
|
|
32
|
-
}), { numRuns: 100 });
|
|
33
|
-
});
|
|
34
|
-
//# sourceMappingURL=prop-streaming.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-streaming.test.js","sourceRoot":"","sources":["../../src/tests/prop-streaming.test.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,0EAA0E;AAC1E,2EAA2E;AAC3E,+EAA+E;AAC/E,2EAA2E;AAC3E,yEAAyE;AACzE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,EAAE;AACF,4EAA4E;AAC5E,EAAE;AACF,wCAAwC;AAExC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,IAAI,CACF,2EAA2E,EAC3E,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,EAAE,CAAC,MAAM,EAAE,EACX,EAAE,CAAC,UAAU,EAAE,EACf,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACrB,iEAAiE;QACjE,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtD,+DAA+D;QAC/D,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpE,mEAAmE;QACnE,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAE/D,MAAM,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-upload-download.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-upload-download.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade round-trip guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 1 (Upload/download preserves bytes): for arbitrary keys and byte
|
|
4
|
-
// contents, persisting bytes with `put(key, bytes)` and then reading them back
|
|
5
|
-
// with `get(key)` yields `found: true` and content bytes exactly equal to the
|
|
6
|
-
// original input. This exercises the facade over the zero-dependency `memory`
|
|
7
|
-
// provider, driving the identical code path every provider shares.
|
|
8
|
-
//
|
|
9
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
10
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
11
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
12
|
-
//
|
|
13
|
-
// Feature: unified-storage-framework, Property 1: Upload/download preserves bytes
|
|
14
|
-
//
|
|
15
|
-
// Validates: Requirements 4.1, 4.2, 26.2
|
|
16
|
-
import test from "node:test";
|
|
17
|
-
import assert from "node:assert/strict";
|
|
18
|
-
import fc from "fast-check";
|
|
19
|
-
import { createStorage } from "../facade.js";
|
|
20
|
-
test("Feature: unified-storage-framework, Property 1: Upload/download preserves bytes", async () => {
|
|
21
|
-
await fc.assert(fc.asyncProperty(fc.string(), fc.uint8Array(), async (key, content) => {
|
|
22
|
-
// A fresh store per run keeps each key/content pair independent.
|
|
23
|
-
const storage = createStorage({ provider: "memory" });
|
|
24
|
-
await storage.put(key, content);
|
|
25
|
-
const result = await storage.get(key);
|
|
26
|
-
assert.equal(result.found, true);
|
|
27
|
-
assert.deepEqual(result.bytes, content);
|
|
28
|
-
}), { numRuns: 100 });
|
|
29
|
-
});
|
|
30
|
-
//# sourceMappingURL=prop-upload-download.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-upload-download.test.js","sourceRoot":"","sources":["../../src/tests/prop-upload-download.test.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,EAAE;AACF,kFAAkF;AAClF,EAAE;AACF,yCAAyC;AAEzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,IAAI,CACF,iFAAiF,EACjF,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,EAAE,CAAC,MAAM,EAAE,EACX,EAAE,CAAC,UAAU,EAAE,EACf,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACrB,iEAAiE;QACjE,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtD,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-validation.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-validation.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's validation pipeline guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 12 (Validation rejects leave no partial object): a Storage instance
|
|
4
|
-
// configured with a size validator (`validation: { maxSize: N }`) must, for any
|
|
5
|
-
// upload whose byte length exceeds `N`, reject the `put` with a `ValidationError`
|
|
6
|
-
// AND leave no partial object behind (`exists(key)` is false afterward). For any
|
|
7
|
-
// upload within the limit, `put` succeeds and the object then exists. Because the
|
|
8
|
-
// facade runs the validation pipeline before any bytes reach the driver, a
|
|
9
|
-
// rejection can never persist content (Requirements 9.3, 9.4).
|
|
10
|
-
//
|
|
11
|
-
// Backed by the zero-dependency in-memory provider via `createStorage({
|
|
12
|
-
// provider: 'memory', validation: { maxSize } })`, exercised across arbitrary
|
|
13
|
-
// keys, byte contents, and size limits with fast-check at { numRuns: 100 }.
|
|
14
|
-
// Executed via the Node.js built-in test runner (`node --test dist/tests/*.test.js`).
|
|
15
|
-
//
|
|
16
|
-
// Feature: unified-storage-framework, Property 12
|
|
17
|
-
// Validates: Requirements 9.3, 9.4
|
|
18
|
-
import test from "node:test";
|
|
19
|
-
import assert from "node:assert/strict";
|
|
20
|
-
import fc from "fast-check";
|
|
21
|
-
import { createStorage } from "../index.js";
|
|
22
|
-
import { ValidationError } from "../errors.js";
|
|
23
|
-
test("Feature: unified-storage-framework, Property 12 — validation rejects leave no partial object", async () => {
|
|
24
|
-
await fc.assert(fc.asyncProperty(
|
|
25
|
-
// Arbitrary non-empty keys and arbitrary byte contents.
|
|
26
|
-
fc.string({ minLength: 1 }), fc.uint8Array(),
|
|
27
|
-
// A non-negative size limit; chosen from a range that straddles typical
|
|
28
|
-
// fast-check byte-array lengths so both accepted and rejected inputs are
|
|
29
|
-
// generated across the 100 runs.
|
|
30
|
-
fc.nat({ max: 16 }), async (key, content, maxSize) => {
|
|
31
|
-
// A fresh store per run keeps each key/content pair independent.
|
|
32
|
-
const storage = createStorage({
|
|
33
|
-
provider: "memory",
|
|
34
|
-
validation: { maxSize },
|
|
35
|
-
});
|
|
36
|
-
const violatesLimit = content.byteLength > maxSize;
|
|
37
|
-
if (violatesLimit) {
|
|
38
|
-
// The oversized upload must be rejected with a ValidationError...
|
|
39
|
-
await assert.rejects(() => storage.put(key, content), (error) => error instanceof ValidationError);
|
|
40
|
-
// ...and must leave no partial object stored.
|
|
41
|
-
assert.equal(await storage.exists(key), false);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// A within-limit upload succeeds and the object then exists.
|
|
45
|
-
await storage.put(key, content);
|
|
46
|
-
assert.equal(await storage.exists(key), true);
|
|
47
|
-
}
|
|
48
|
-
}), { numRuns: 100 });
|
|
49
|
-
});
|
|
50
|
-
//# sourceMappingURL=prop-validation.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-validation.test.js","sourceRoot":"","sources":["../../src/tests/prop-validation.test.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,kFAAkF;AAClF,iFAAiF;AACjF,kFAAkF;AAClF,2EAA2E;AAC3E,+DAA+D;AAC/D,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,4EAA4E;AAC5E,sFAAsF;AACtF,EAAE;AACF,kDAAkD;AAClD,mCAAmC;AAEnC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,IAAI,CACF,8FAA8F,EAC9F,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa;IACd,wDAAwD;IACxD,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAC3B,EAAE,CAAC,UAAU,EAAE;IACf,wEAAwE;IACxE,yEAAyE;IACzE,iCAAiC;IACjC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EACnB,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAC9B,iEAAiE;QACjE,MAAM,OAAO,GAAG,aAAa,CAAC;YAC5B,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,EAAE,OAAO,EAAE;SACxB,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC;QAEnD,IAAI,aAAa,EAAE,CAAC;YAClB,kEAAkE;YAClE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,eAAe,CAC5C,CAAC;YACF,8CAA8C;YAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,6DAA6D;YAC7D,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-versioning.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-versioning.test.ts"],"names":[],"mappings":""}
|