From a873f9e152832e9f72d79ad29fce201b8a34d5d7 Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Tue, 22 Aug 2023 13:25:40 -0400 Subject: [PATCH 1/4] chore: cleanup unit tests --- index.html | 17 +- packages/core/__tests__/open.test.ts | 954 ++++++--------------------- 2 files changed, 222 insertions(+), 749 deletions(-) diff --git a/index.html b/index.html index 53bbbf1c..e96e847b 100644 --- a/index.html +++ b/index.html @@ -57,7 +57,7 @@ "3d.chunked.mixed.i2.F", "3d.contiguous.i2", ]) { - let arr = await zarr.open.v2(grp.resolve(fixture), { kind: "array" }); + let arr = await zarr.open.v2(grp.resolve(fixture), { kind: "array", attrs: false }); let { data, shape, stride } = await get(arr); let pre = document.createElement("pre"); pre.textContent = `\ @@ -76,10 +76,18 @@ kind: "group", }); for (let fixture of [ + "1d.chunked.compressed.sharded.i2", + "1d.chunked.filled.compressed.sharded.i2", "1d.chunked.i2", "1d.chunked.ragged.i2", "1d.contiguous.b1", "1d.contiguous.blosc.i2", + "1d.contiguous.compressed.sharded.b1", + "1d.contiguous.compressed.sharded.f4", + "1d.contiguous.compressed.sharded.f8", + "1d.contiguous.compressed.sharded.i2", + "1d.contiguous.compressed.sharded.i4", + "1d.contiguous.compressed.sharded.u1", "1d.contiguous.f4.be", "1d.contiguous.f4.le", "1d.contiguous.f8", @@ -87,12 +95,19 @@ "1d.contiguous.i4", "1d.contiguous.raw.i2", "1d.contiguous.u1", + "2d.chunked.compressed.sharded.filled.i2", + "2d.chunked.compressed.sharded.i2", "2d.chunked.i2", + "2d.chunked.ragged.compressed.sharded.i2", "2d.chunked.ragged.i2", + "2d.contiguous.compressed.sharded.i2", "2d.contiguous.i2", + "3d.chunked.compressed.sharded.i2", "3d.chunked.i2", + "3d.chunked.mixed.compressed.sharded.i2", "3d.chunked.mixed.i2.C", "3d.chunked.mixed.i2.F", + "3d.contiguous.compressed.sharded.i2", "3d.contiguous.i2", ]) { let arr = await zarr.open.v3(grp.resolve(fixture), { kind: "array" }); diff --git a/packages/core/__tests__/open.test.ts b/packages/core/__tests__/open.test.ts index 15d61c4e..4ada419c 100644 --- a/packages/core/__tests__/open.test.ts +++ b/packages/core/__tests__/open.test.ts @@ -12,6 +12,10 @@ import { open } from "../src/open.js"; import { root } from "../src/hierarchy.js"; import { NodeNotFoundError } from "../src/errors.js"; +function range(n: number) { + return Array.from({ length: n }, (_, i) => i); +} + let __dirname = path.dirname(url.fileURLToPath(import.meta.url)); describe("v2", () => { @@ -21,277 +25,97 @@ describe("v2", () => { ), ); - it("loads .zattrs by default", async () => { - let group = await open.v2(store); - expect(group.attrs).toMatchInlineSnapshot(` - { - "answer": 42, - } - `); - }); - - it("loads .zattrs when specified", async () => { - let group = await open.v2(store, { attrs: true }); - expect(group.attrs).toMatchInlineSnapshot(` - { - "answer": 42, - } - `); - }); - - it("skips loading .zattrs when disabled", async () => { - let group = await open.v2(store, { attrs: false }); - expect(group.attrs).toMatchInlineSnapshot("{}"); - }); - - it("1d.contiguous.zlib.i2", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.zlib.i2"), { - kind: "array", - }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.blosc.i2", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.blosc.i2"), { - kind: "array", - }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.lz4.i2", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.lz4.i2"), { - kind: "array", - }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.zstd.i2", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.zstd.i2"), { - kind: "array", + describe("loads .zattrs", () => { + it.each([ + [undefined, { answer: 42 }], + [true, { answer: 42 }], + [false, {}], + ])(`attrs: %j`, async (attrs, expected) => { + let group = await open.v2(store, { attrs }); + expect(group.attrs).toStrictEqual(expected); }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); - it("1d.contiguous.raw.i2", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.raw.i2"), { - kind: "array", + describe("1d.contiguous.i2", () => { + it.each([ + "1d.contiguous.zlib.i2", + "1d.contiguous.blosc.i2", + "1d.contiguous.lz4.i2", + "1d.contiguous.zstd.i2", + "1d.contiguous.raw.i2", + ])(`%s`, async (path) => { + let arr = await open.v2(store.resolve(path), { kind: "array" }); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Int16Array([1, 2, 3, 4]), + shape: [4], + stride: [1], + }); }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); it("1d.contiguous.i4", async () => { let arr = await open.v2(store.resolve("/1d.contiguous.i4"), { kind: "array", }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int32Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Int32Array([1, 2, 3, 4]), + shape: [4], + stride: [1], + }); }); it("1d.contiguous.u1", async () => { let arr = await open.v2(store.resolve("/1d.contiguous.u1"), { kind: "array", }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Uint8Array [ - 255, - 0, - 255, - 0, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.f4.le", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.f4.le"), { - kind: "array", + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Uint8Array([255, 0, 255, 0]), + shape: [4], + stride: [1], }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Float32Array [ - -1000.5, - 0, - 1000.5, - 0, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); - it("1d.contiguous.f4.be", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.f4.be"), { - kind: "array", + describe("1d.contiguous.f4", () => { + it.each([ + "1d.contiguous.f4.le", + "1d.contiguous.f4.be", + ])(`%s`, async (path) => { + let arr = await open.v2(store.resolve(path), { kind: "array" }); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Float32Array([-1000.5, 0, 1000.5, 0]), + shape: [4], + stride: [1], + }); }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Float32Array [ - -1000.5, - 0, - 1000.5, - 0, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); it("1d.contiguous.f8", async () => { let arr = await open.v2(store.resolve("/1d.contiguous.f8"), { kind: "array", }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Float64Array [ - 1.5, - 2.5, - 3.5, - 4.5, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.U13.le", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.U13.le"), { - kind: "array", + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Float64Array([1.5, 2.5, 3.5, 4.5]), + shape: [4], + stride: [1], }); - let chunk = await arr.getChunk([0]); - expect(chunk.data).toBeInstanceOf(UnicodeStringArray); - expect(Array.from(chunk.data as UnicodeStringArray)).toStrictEqual([ - "a", - "b", - "cc", - "d", - ]); - expect(chunk.shape).toStrictEqual([4]); }); - it("1d.contiguous.U13.be", async () => { - let arr = await open.v2(store.resolve("/1d.contiguous.U13.be"), { - kind: "array", + describe("1d.contiguous.U13", () => { + it.each([ + "1d.contiguous.U13.le", + "1d.contiguous.U13.le", + ])(`%s`, async (path) => { + let arr = await open.v2(store.resolve(path), { + kind: "array", + }); + let chunk = await arr.getChunk([0]); + expect(chunk.data).toBeInstanceOf(UnicodeStringArray); + expect({ ...chunk, data: Array.from(chunk.data as any) }).toStrictEqual({ + data: ["a", "b", "cc", "d"], + shape: [4], + stride: [1], + }); }); - let chunk = await arr.getChunk([0]); - expect(chunk.data).toBeInstanceOf(UnicodeStringArray); - expect(Array.from(chunk.data as UnicodeStringArray)).toStrictEqual([ - "a", - "b", - "cc", - "d", - ]); - expect(chunk.shape).toStrictEqual([4]); }); it("1d.contiguous.U7", async () => { @@ -300,13 +124,11 @@ describe("v2", () => { }); let chunk = await arr.getChunk([0]); expect(chunk.data).toBeInstanceOf(UnicodeStringArray); - expect(Array.from(chunk.data as UnicodeStringArray)).toStrictEqual([ - "a", - "b", - "cc", - "d", - ]); - expect(chunk.shape).toStrictEqual([4]); + expect({ ...chunk, data: Array.from(chunk.data as any) }).toStrictEqual({ + data: ["a", "b", "cc", "d"], + shape: [4], + stride: [1], + }); }); it("1d.contiguous.S7", async () => { @@ -315,13 +137,11 @@ describe("v2", () => { }); let chunk = await arr.getChunk([0]); expect(chunk.data).toBeInstanceOf(ByteStringArray); - expect(Array.from(chunk.data as ByteStringArray)).toStrictEqual([ - "a", - "b", - "cc", - "d", - ]); - expect(chunk.shape).toStrictEqual([4]); + expect({ ...chunk, data: Array.from(chunk.data as any) }).toStrictEqual({ + data: ["a", "b", "cc", "d"], + shape: [4], + stride: [1], + }); }); it("1d.contiguous.b1", async () => { @@ -329,543 +149,182 @@ describe("v2", () => { kind: "array", }); let chunk = await arr.getChunk([0]); - expect(chunk).toMatchInlineSnapshot(` - { - "data": BoolArray {}, - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - expect(Array.from(chunk.data as BoolArray)).toMatchInlineSnapshot(` - [ - true, - false, - true, - false, - ] - `); + expect(chunk.data).toBeInstanceOf(BoolArray); + expect({ ...chunk, data: Array.from(chunk.data as any) }).toStrictEqual({ + data: [true, false, true, false], + shape: [4], + stride: [1], + }); }); it("2d.contiguous.i2", async () => { let arr = await open.v2(store.resolve("/2d.contiguous.i2"), { kind: "array", }); - expect(await arr.getChunk([0, 0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - } - `); + expect(await arr.getChunk([0, 0])).toStrictEqual({ + data: new Int16Array([1, 2, 3, 4]), + shape: [2, 2], + stride: [2, 1], + }); }); it("3d.contiguous.i2", async () => { let arr = await open.v2(store.resolve("/3d.contiguous.i2"), { kind: "array", }); - expect(await arr.getChunk([0, 0, 0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - ], - "shape": [ - 3, - 3, - 3, - ], - "stride": [ - 9, - 3, - 1, - ], - } - `); + expect(await arr.getChunk([0, 0, 0])).toStrictEqual({ + data: new Int16Array(range(27)), + shape: [3, 3, 3], + stride: [9, 3, 1], + }); }); - it("1d.chunked.i2", async () => { + describe("1d.chunked.i2", async () => { let arr = await open.v2(store.resolve("/1d.chunked.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0]), - arr.getChunk([1]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - 2, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - { - "data": Int16Array [ - 3, - 4, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - ] - `); + it.each([ + [[0], [1, 2]], + [[1], [3, 4]], + ])("getChunk(%j) -> Int16Array(%j)", async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [2], + stride: [1], + }); + }); }); - it("1d.chunked.ragged.i2", async () => { + describe("1d.chunked.ragged.i2", async () => { let arr = await open.v2(store.resolve("/1d.chunked.ragged.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0]), - arr.getChunk([1]), - arr.getChunk([2]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - 2, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - { - "data": Int16Array [ - 3, - 4, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - { - "data": Int16Array [ - 5, - 0, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - ] - `); + it.each([ + [[0], [1, 2]], + [[1], [3, 4]], + [[2], [5, 0]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [2], + stride: [1], + }); + }); }); - it("2d.chunked.i2", async () => { + describe("2d.chunked.i2", async () => { let arr = await open.v2(store.resolve("/2d.chunked.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0]), - arr.getChunk([0, 1]), - arr.getChunk([1, 0]), - arr.getChunk([1, 1]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - { - "data": Int16Array [ - 2, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - { - "data": Int16Array [ - 3, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - { - "data": Int16Array [ - 4, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0], [1]], + [[0, 1], [2]], + [[1, 0], [3]], + [[1, 1], [4]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [1, 1], + stride: [1, 1], + }); + }); }); - it("2d.chunked.U7", async () => { + describe("2d.chunked.U7", async () => { let arr = await open.v2(store.resolve("/2d.chunked.U7"), { kind: "array", }); - let [c1, c2, c3, c4] = await Promise.all([ - arr.getChunk([0, 0]), - arr.getChunk([0, 1]), - arr.getChunk([1, 0]), - arr.getChunk([1, 1]), - ]); - expect(Array.from(c1.data as UnicodeStringArray)).toStrictEqual(["a"]); - expect(c1.shape).toStrictEqual([1, 1]); - expect(Array.from(c2.data as UnicodeStringArray)).toStrictEqual(["b"]); - expect(c2.shape).toStrictEqual([1, 1]); - expect(Array.from(c3.data as UnicodeStringArray)).toStrictEqual(["cc"]); - expect(c3.shape).toStrictEqual([1, 1]); - expect(Array.from(c4.data as UnicodeStringArray)).toStrictEqual(["d"]); - expect(c4.shape).toStrictEqual([1, 1]); + it.each([ + [[0, 0], ["a"]], + [[0, 1], ["b"]], + [[1, 0], ["cc"]], + [[1, 1], ["d"]], + ])(`getChunk(%j) -> %j`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk.data).toBeInstanceOf(UnicodeStringArray); + expect({ ...chunk, data: Array.from(chunk.data as any) }).toStrictEqual({ + data: expected, + shape: [1, 1], + stride: [1, 1], + }); + }); }); - it("2d.chunked.ragged.i2", async () => { + describe("2d.chunked.ragged.i2", async () => { let arr = await open.v2(store.resolve("/2d.chunked.ragged.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0]), - arr.getChunk([0, 1]), - arr.getChunk([1, 0]), - arr.getChunk([1, 1]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - 2, - 4, - 5, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - { - "data": Int16Array [ - 3, - 0, - 6, - 0, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - { - "data": Int16Array [ - 7, - 8, - 0, - 0, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - { - "data": Int16Array [ - 9, - 0, - 0, - 0, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0], [1, 2, 4, 5]], + [[0, 1], [3, 0, 6, 0]], + [[1, 0], [7, 8, 0, 0]], + [[1, 1], [9, 0, 0, 0]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [2, 2], + stride: [2, 1], + }); + }); }); - it("3d.chunked.i2", async () => { + describe("3d.chunked.i2", async () => { let arr = await open.v2(store.resolve("/3d.chunked.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0, 0]), - arr.getChunk([0, 0, 2]), - arr.getChunk([1, 1, 1]), - arr.getChunk([2, 2, 2]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 0, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 2, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 13, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 26, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0, 0], [0]], + [[0, 0, 2], [2]], + [[1, 1, 1], [13]], + [[2, 2, 2], [26]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [1, 1, 1], + stride: [1, 1, 1], + }); + }); }); - it("3d.chunked.mixed.i2.C", async () => { + describe("3d.chunked.mixed.i2.C", async () => { let arr = await open.v2(store.resolve("/3d.chunked.mixed.i2.C"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0, 0]), - arr.getChunk([0, 0, 1]), - arr.getChunk([0, 0, 2]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 0, - 3, - 6, - 9, - 12, - 15, - 18, - 21, - 24, - ], - "shape": [ - 3, - 3, - 1, - ], - "stride": [ - 3, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 1, - 4, - 7, - 10, - 13, - 16, - 19, - 22, - 25, - ], - "shape": [ - 3, - 3, - 1, - ], - "stride": [ - 3, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 2, - 5, - 8, - 11, - 14, - 17, - 20, - 23, - 26, - ], - "shape": [ - 3, - 3, - 1, - ], - "stride": [ - 3, - 1, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0, 0], [0, 3, 6, 9, 12, 15, 18, 21, 24]], + [[0, 0, 1], [1, 4, 7, 10, 13, 16, 19, 22, 25]], + [[0, 0, 2], [2, 5, 8, 11, 14, 17, 20, 23, 26]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [3, 3, 1], + stride: [3, 1, 1], + }); + }); }); - it("3d.chunked.mixed.i2.F", async () => { + describe("3d.chunked.mixed.i2.F", async () => { let arr = await open.v2(store.resolve("/3d.chunked.mixed.i2.F"), { kind: "array", }); - let [c1, c2, c3] = await Promise.all([ - arr.getChunk([0, 0, 0]), - arr.getChunk([0, 0, 1]), - arr.getChunk([0, 0, 2]), - ]); - let shape = [3, 3, 1]; - let stride = [1, 3, 9]; - expect(c1.data).toStrictEqual( - new Int16Array([0, 9, 18, 3, 12, 21, 6, 15, 24]), - ); - expect(c1.shape).toStrictEqual(shape); - expect(c1.stride).toStrictEqual(stride); - expect(c2.data).toStrictEqual( - new Int16Array([1, 10, 19, 4, 13, 22, 7, 16, 25]), - ); - expect(c2.shape).toStrictEqual(shape); - expect(c2.stride).toStrictEqual(stride); - expect(c3.data).toStrictEqual( - new Int16Array([2, 11, 20, 5, 14, 23, 8, 17, 26]), - ); - expect(c3.shape).toStrictEqual(shape); - expect(c3.stride).toStrictEqual(stride); + it.each([ + [[0, 0, 0], [0, 9, 18, 3, 12, 21, 6, 15, 24]], + [[0, 0, 1], [1, 10, 19, 4, 13, 22, 7, 16, 25]], + [[0, 0, 2], [2, 11, 20, 5, 14, 23, 8, 17, 26]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [3, 3, 1], + stride: [1, 3, 9], + }); + }); }); it("opens group from root", async () => { @@ -879,16 +338,15 @@ describe("v2", () => { .toThrow(NodeNotFoundError); }); - it("opens array from group", async () => { + describe("opens array from group", async () => { let grp = await open.v2(store, { kind: "group" }); - let a1 = await open.v2(store.resolve("/1d.chunked.i2"), { - kind: "array", + it.each([ + "/1d.chunked.i2", + "1d.chunked.i2", + ])(`%s`, async (path) => { + let a = await open.v2(grp.resolve(path), { kind: "array" }); + expect(a.path).toBe("/1d.chunked.i2"); }); - let a2 = await open.v2(grp.resolve("1d.chunked.i2"), { - kind: "array", - }); - expect(a1.path).toBe("/1d.chunked.i2"); - expect(a2.path).toBe("/1d.chunked.i2"); }); }); From 49f1887406fe72218aa86ac49211c6c365b17baf Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Tue, 22 Aug 2023 13:40:35 -0400 Subject: [PATCH 2/4] migrate the rest of v3 tests --- packages/core/__tests__/open.test.ts | 762 ++++++--------------------- 1 file changed, 152 insertions(+), 610 deletions(-) diff --git a/packages/core/__tests__/open.test.ts b/packages/core/__tests__/open.test.ts index 4ada419c..8cc7e62f 100644 --- a/packages/core/__tests__/open.test.ts +++ b/packages/core/__tests__/open.test.ts @@ -357,180 +357,66 @@ describe("v3", () => { ), ); - it("1d.contiguous.gzip.i2", async () => { - let arr = await open.v3(store.resolve("/1d.contiguous.gzip.i2"), { - kind: "array", - }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.blosc.i2", async () => { - let arr = await open.v3(store.resolve("/1d.contiguous.blosc.i2"), { - kind: "array", - }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.raw.i2", async () => { - let arr = await open.v3(store.resolve("/1d.contiguous.raw.i2"), { - kind: "array", + describe("1d.contiguous.i2", async () => { + it.each([ + "1d.contiguous.gzip.i2", + "1d.contiguous.blosc.i2", + "1d.contiguous.raw.i2", + ])(`%s`, async (path) => { + let arr = await open.v3(store.resolve(path), { kind: "array" }); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Int16Array([1, 2, 3, 4]), + shape: [4], + stride: [1], + }); }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); it("1d.contiguous.i4", async () => { let arr = await open.v3(store.resolve("/1d.contiguous.i4"), { kind: "array", }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Int32Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Int32Array([1, 2, 3, 4]), + shape: [4], + stride: [1], + }); }); it("1d.contiguous.u1", async () => { let arr = await open.v3(store.resolve("/1d.contiguous.u1"), { kind: "array", }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Uint8Array [ - 255, - 0, - 255, - 0, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - }); - - it("1d.contiguous.f4.le", async () => { - let arr = await open.v3(store.resolve("/1d.contiguous.f4.le"), { - kind: "array", + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Uint8Array([255, 0, 255, 0]), + shape: [4], + stride: [1], }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Float32Array [ - -1000.5, - 0, - 1000.5, - 0, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); - it("1d.contiguous.f4.be", async () => { - let arr = await open.v3(store.resolve("/1d.contiguous.f4.be"), { - kind: "array", + describe("1d.contiguous.f4", () => { + it.each([ + "1d.contiguous.f4.le", + "1d.contiguous.f4.be", + ])(`%s`, async (path) => { + let arr = await open.v3(store.resolve(path), { kind: "array" }); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Float32Array([-1000.5, 0, 1000.5, 0]), + shape: [4], + stride: [1], + }); }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Float32Array [ - -1000.5, - 0, - 1000.5, - 0, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); }); it("1d.contiguous.f8", async () => { let arr = await open.v3(store.resolve("/1d.contiguous.f8"), { kind: "array", }); - expect(await arr.getChunk([0])).toMatchInlineSnapshot(` - { - "data": Float64Array [ - 1.5, - 2.5, - 3.5, - 4.5, - ], - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); + expect(await arr.getChunk([0])).toStrictEqual({ + data: new Float64Array([1.5, 2.5, 3.5, 4.5]), + shape: [4], + stride: [1], + }); }); it("1d.contiguous.b1", async () => { @@ -538,504 +424,161 @@ describe("v3", () => { kind: "array", }); let chunk = await arr.getChunk([0]); - expect(chunk).toMatchInlineSnapshot(` - { - "data": BoolArray {}, - "shape": [ - 4, - ], - "stride": [ - 1, - ], - } - `); - expect(Array.from(chunk.data as any)).toMatchInlineSnapshot(` - [ - true, - false, - true, - false, - ] - `); + expect(chunk.data).toBeInstanceOf(BoolArray); + expect({ ...chunk, data: Array.from(chunk.data as any) }).toStrictEqual({ + data: [true, false, true, false], + shape: [4], + stride: [1], + }); }); it("2d.contiguous.i2", async () => { let arr = await open.v3(store.resolve("/2d.contiguous.i2"), { kind: "array", }); - expect(await arr.getChunk([0, 0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 1, - 2, - 3, - 4, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - } - `); + expect(await arr.getChunk([0, 0])).toStrictEqual({ + data: new Int16Array([1, 2, 3, 4]), + shape: [2, 2], + stride: [2, 1], + }); }); it("3d.contiguous.i2", async () => { let arr = await open.v3(store.resolve("/3d.contiguous.i2"), { kind: "array", }); - expect(await arr.getChunk([0, 0, 0])).toMatchInlineSnapshot(` - { - "data": Int16Array [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - ], - "shape": [ - 3, - 3, - 3, - ], - "stride": [ - 9, - 3, - 1, - ], - } - `); + expect(await arr.getChunk([0, 0, 0])).toStrictEqual({ + data: new Int16Array(range(27)), + shape: [3, 3, 3], + stride: [9, 3, 1], + }); }); - it("1d.chunked.i2", async () => { + describe("1d.chunked.i2", async () => { let arr = await open.v3(store.resolve("/1d.chunked.i2"), { kind: "array", }); - let chunks = await Promise.all([arr.getChunk([0]), arr.getChunk([1])]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - 2, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - { - "data": Int16Array [ - 3, - 4, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - ] - `); + it.each([ + [[0], [1, 2]], + [[1], [3, 4]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [2], + stride: [1], + }); + }); }); - it("1d.chunked.ragged.i2", async () => { + describe("1d.chunked.ragged.i2", async () => { let arr = await open.v3(store.resolve("/1d.chunked.ragged.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0]), - arr.getChunk([1]), - arr.getChunk([2]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - 2, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - { - "data": Int16Array [ - 3, - 4, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - { - "data": Int16Array [ - 5, - 0, - ], - "shape": [ - 2, - ], - "stride": [ - 1, - ], - }, - ] - `); + it.each([ + [[0], [1, 2]], + [[1], [3, 4]], + [[2], [5, 0]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [2], + stride: [1], + }); + }); }); - it("2d.chunked.i2", async () => { + describe("2d.chunked.i2", async () => { let arr = await open.v3(store.resolve("/2d.chunked.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0]), - arr.getChunk([0, 1]), - arr.getChunk([1, 0]), - arr.getChunk([1, 1]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - { - "data": Int16Array [ - 2, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - { - "data": Int16Array [ - 3, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - { - "data": Int16Array [ - 4, - ], - "shape": [ - 1, - 1, - ], - "stride": [ - 1, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0], [1]], + [[0, 1], [2]], + [[1, 0], [3]], + [[1, 1], [4]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [1, 1], + stride: [1, 1], + }); + }); }); - it("2d.chunked.ragged.i2", async () => { + describe("2d.chunked.ragged.i2", async () => { let arr = await open.v3(store.resolve("/2d.chunked.ragged.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0]), - arr.getChunk([0, 1]), - arr.getChunk([1, 0]), - arr.getChunk([1, 1]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 1, - 2, - 4, - 5, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - { - "data": Int16Array [ - 3, - 0, - 6, - 0, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - { - "data": Int16Array [ - 7, - 8, - 0, - 0, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - { - "data": Int16Array [ - 9, - 0, - 0, - 0, - ], - "shape": [ - 2, - 2, - ], - "stride": [ - 2, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0], [1, 2, 4, 5]], + [[0, 1], [3, 0, 6, 0]], + [[1, 0], [7, 8, 0, 0]], + [[1, 1], [9, 0, 0, 0]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [2, 2], + stride: [2, 1], + }); + }); }); - it("3d.chunked.i2", async () => { + describe("3d.chunked.i2", async () => { let arr = await open.v3(store.resolve("/3d.chunked.i2"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0, 2]), - arr.getChunk([1, 1, 1]), - arr.getChunk([2, 2, 2]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 2, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 13, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 26, - ], - "shape": [ - 1, - 1, - 1, - ], - "stride": [ - 1, - 1, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0, 2], [2]], + [[1, 1, 1], [13]], + [[2, 2, 2], [26]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [1, 1, 1], + stride: [1, 1, 1], + }); + }); }); - it("3d.chunked.mixed.i2.C", async () => { + describe("3d.chunked.mixed.i2.C", async () => { let arr = await open.v3(store.resolve("/3d.chunked.mixed.i2.C"), { kind: "array", }); - let chunks = await Promise.all([ - arr.getChunk([0, 0, 0]), - arr.getChunk([0, 0, 1]), - arr.getChunk([0, 0, 2]), - ]); - expect(chunks).toMatchInlineSnapshot(` - [ - { - "data": Int16Array [ - 0, - 3, - 6, - 9, - 12, - 15, - 18, - 21, - 24, - ], - "shape": [ - 3, - 3, - 1, - ], - "stride": [ - 3, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 1, - 4, - 7, - 10, - 13, - 16, - 19, - 22, - 25, - ], - "shape": [ - 3, - 3, - 1, - ], - "stride": [ - 3, - 1, - 1, - ], - }, - { - "data": Int16Array [ - 2, - 5, - 8, - 11, - 14, - 17, - 20, - 23, - 26, - ], - "shape": [ - 3, - 3, - 1, - ], - "stride": [ - 3, - 1, - 1, - ], - }, - ] - `); + it.each([ + [[0, 0, 0], [0, 3, 6, 9, 12, 15, 18, 21, 24]], + [[0, 0, 1], [1, 4, 7, 10, 13, 16, 19, 22, 25]], + [[0, 0, 2], [2, 5, 8, 11, 14, 17, 20, 23, 26]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [3, 3, 1], + stride: [3, 1, 1], + }); + }); }); - it("3d.chunked.mixed.i2.F", async () => { + describe("3d.chunked.mixed.i2.F", async () => { let arr = await open.v3(store.resolve("/3d.chunked.mixed.i2.F"), { kind: "array", }); - let [c1, c2, c3] = await Promise.all([ - arr.getChunk([0, 0, 0]), - arr.getChunk([0, 0, 1]), - arr.getChunk([0, 0, 2]), - ]); - let shape = [3, 3, 1]; - let stride = [1, 3, 9]; - expect(c1.data).toStrictEqual( - new Int16Array([0, 9, 18, 3, 12, 21, 6, 15, 24]), - ); - expect(c1.shape).toStrictEqual(shape); - expect(c1.stride).toStrictEqual(stride); - expect(c2.data).toStrictEqual( - new Int16Array([1, 10, 19, 4, 13, 22, 7, 16, 25]), - ); - expect(c2.shape).toStrictEqual(shape); - expect(c2.stride).toStrictEqual(stride); - expect(c3.data).toStrictEqual( - new Int16Array([2, 11, 20, 5, 14, 23, 8, 17, 26]), - ); - expect(c3.shape).toStrictEqual(shape); - expect(c3.stride).toStrictEqual(stride); + it.each([ + [[0, 0, 0], [0, 9, 18, 3, 12, 21, 6, 15, 24]], + [[0, 0, 1], [1, 10, 19, 4, 13, 22, 7, 16, 25]], + [[0, 0, 2], [2, 11, 20, 5, 14, 23, 8, 17, 26]], + ])(`getChunk(%j) -> Int16Array(%j)`, async (index, expected) => { + let chunk = await arr.getChunk(index); + expect(chunk).toStrictEqual({ + data: new Int16Array(expected), + shape: [3, 3, 1], + stride: [1, 3, 9], + }); + }); }); it("opens group from root", async () => { @@ -1049,16 +592,15 @@ describe("v3", () => { .toThrow(NodeNotFoundError); }); - it("opens array from group", async () => { + describe("opens array from group", async () => { let grp = await open.v3(store, { kind: "group" }); - let a1 = await open.v3(store.resolve("/1d.chunked.i2"), { - kind: "array", - }); - let a2 = await open.v3(grp.resolve("1d.chunked.i2"), { - kind: "array", + it.each([ + "/1d.chunked.i2", + "1d.chunked.i2", + ])(`%s`, async (path) => { + let a = await open.v3(grp.resolve(path), { kind: "array" }); + expect(a.path).toBe("/1d.chunked.i2"); }); - expect(a1.path).toBe("/1d.chunked.i2"); - expect(a2.path).toBe("/1d.chunked.i2"); }); it("1d.contiguous.compressed.sharded.i2", async () => { From 8745b19f3d5f5f812bed3fee60b3d27e1dc35ef7 Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Tue, 22 Aug 2023 13:44:12 -0400 Subject: [PATCH 3/4] update readme --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d1636025..035cf714 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ - **Zero dependencies** (optionally [`scijs/ndarray`](https://github.com/scijs/ndarray)) - Runs natively in **Node**, **Browsers**, and **Deno** (ESM) -- Supports **v2** or **v3** protocols, C & F-order arrays, and diverse - data-types +- Supports **v2** or **v3** protocols, C & F-order arrays, diverse + data-types, and [ZEP2 Sharding](https://zarr.dev/zeps/draft/ZEP0002.html) - Allows flexible **storage** backends and **compression** codecs - Provides rich, in-editor **type information** via [template literal types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html) @@ -116,3 +116,15 @@ pnpm install pnpm build pnpm test ``` + +The tests are run with [Vitest](https://github.com/vitest-dev/vitest), which is a Node.js test runner. +To try our a development version of **zarrita** in the browser, run `pnpm build` and start a web-server +in the root of the repository: + +```sh +python3 -m http.server . +# navigate to localhost:8000 +``` + +You can edit the contents of `index.html` and refresh the page. + From 9fcc8ebeadafb11707d62770fc11c13d8ba0550d Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Tue, 22 Aug 2023 13:46:04 -0400 Subject: [PATCH 4/4] add docs link --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 035cf714..b837f68f 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ - **Zero dependencies** (optionally [`scijs/ndarray`](https://github.com/scijs/ndarray)) - Runs natively in **Node**, **Browsers**, and **Deno** (ESM) -- Supports **v2** or **v3** protocols, C & F-order arrays, diverse - data-types, and [ZEP2 Sharding](https://zarr.dev/zeps/draft/ZEP0002.html) +- Supports **v2** or **v3** protocols, C & F-order arrays, diverse data-types, + and [ZEP2 Sharding](https://zarr.dev/zeps/draft/ZEP0002.html) - Allows flexible **storage** backends and **compression** codecs - Provides rich, in-editor **type information** via [template literal types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html) @@ -17,9 +17,8 @@ ```javascript import * as zarr from "zarrita"; -import { FetchStore } from "@zarrita/storage"; -const store = new FetchStore("http://localhost:8080/data.zarr"); +const store = new zarr.FetchStore("http://localhost:8080/data.zarr"); const arr = await zarr.open(store, { kind: "array" }); // zarr.Array // read chunk @@ -36,6 +35,8 @@ const full = await get(arr); // ndarray.Ndarray const region = await get(arr, [null, zarr.slice(6)]); ``` +Read [the documentation](https://manzt.github.io/zarrita.js) to learn more. + ### Zarr building blocks zarrita's API is almost entirely tree-shakeable, meaning users are able to pick @@ -117,9 +118,9 @@ pnpm build pnpm test ``` -The tests are run with [Vitest](https://github.com/vitest-dev/vitest), which is a Node.js test runner. -To try our a development version of **zarrita** in the browser, run `pnpm build` and start a web-server -in the root of the repository: +The tests are run with [Vitest](https://github.com/vitest-dev/vitest), which is +a Node.js test runner. To try our a development version of **zarrita** in the +browser, run `pnpm build` and start a web-server in the root of the repository: ```sh python3 -m http.server . @@ -127,4 +128,3 @@ python3 -m http.server . ``` You can edit the contents of `index.html` and refresh the page. -