From 663cd581daadb2e0381e710193c7bfb07987f464 Mon Sep 17 00:00:00 2001 From: brokkoli71 Date: Fri, 13 Feb 2026 14:12:15 +0100 Subject: [PATCH 1/2] add big endian dtypes to v2 --- .../dev/zarr/zarrjava/core/ArrayMetadata.java | 10 +++++----- .../java/dev/zarr/zarrjava/v2/DataType.java | 18 +++++++++++++++++- .../dev/zarr/zarrjava/ZarrPythonTests.java | 14 +++++++++++--- .../java/dev/zarr/zarrjava/ZarrV2Test.java | 6 +++--- src/test/python-scripts/zarr_python_read_v2.py | 2 +- .../python-scripts/zarr_python_write_v2.py | 2 +- 6 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/main/java/dev/zarr/zarrjava/core/ArrayMetadata.java b/src/main/java/dev/zarr/zarrjava/core/ArrayMetadata.java index 4a1a1ad..a2fb48f 100644 --- a/src/main/java/dev/zarr/zarrjava/core/ArrayMetadata.java +++ b/src/main/java/dev/zarr/zarrjava/core/ArrayMetadata.java @@ -36,11 +36,11 @@ public static Object parseFillValue(Object fillValue, @Nonnull DataType dataType } boolean dataTypeIsBool = dataType == dev.zarr.zarrjava.v3.DataType.BOOL || dataType == dev.zarr.zarrjava.v2.DataType.BOOL; boolean dataTypeIsByte = dataType == dev.zarr.zarrjava.v3.DataType.INT8 || dataType == dev.zarr.zarrjava.v2.DataType.INT8 || dataType == dev.zarr.zarrjava.v3.DataType.UINT8 || dataType == dev.zarr.zarrjava.v2.DataType.UINT8; - boolean dataTypeIsShort = dataType == dev.zarr.zarrjava.v3.DataType.INT16 || dataType == dev.zarr.zarrjava.v2.DataType.INT16 || dataType == dev.zarr.zarrjava.v3.DataType.UINT16 || dataType == dev.zarr.zarrjava.v2.DataType.UINT16; - boolean dataTypeIsInt = dataType == dev.zarr.zarrjava.v3.DataType.INT32 || dataType == dev.zarr.zarrjava.v2.DataType.INT32 || dataType == dev.zarr.zarrjava.v3.DataType.UINT32 || dataType == dev.zarr.zarrjava.v2.DataType.UINT32; - boolean dataTypeIsLong = dataType == dev.zarr.zarrjava.v3.DataType.INT64 || dataType == dev.zarr.zarrjava.v2.DataType.INT64 || dataType == dev.zarr.zarrjava.v3.DataType.UINT64 || dataType == dev.zarr.zarrjava.v2.DataType.UINT64; - boolean dataTypeIsFloat = dataType == dev.zarr.zarrjava.v3.DataType.FLOAT32 || dataType == dev.zarr.zarrjava.v2.DataType.FLOAT32; - boolean dataTypeIsDouble = dataType == dev.zarr.zarrjava.v3.DataType.FLOAT64 || dataType == dev.zarr.zarrjava.v2.DataType.FLOAT64; + boolean dataTypeIsShort = dataType == dev.zarr.zarrjava.v3.DataType.INT16 || dataType == dev.zarr.zarrjava.v2.DataType.INT16 || dataType == dev.zarr.zarrjava.v2.DataType.INT16_BE || dataType == dev.zarr.zarrjava.v3.DataType.UINT16 || dataType == dev.zarr.zarrjava.v2.DataType.UINT16|| dataType == dev.zarr.zarrjava.v2.DataType.UINT16_BE; + boolean dataTypeIsInt = dataType == dev.zarr.zarrjava.v3.DataType.INT32 || dataType == dev.zarr.zarrjava.v2.DataType.INT32 || dataType == dev.zarr.zarrjava.v2.DataType.INT32_BE || dataType == dev.zarr.zarrjava.v3.DataType.UINT32 || dataType == dev.zarr.zarrjava.v2.DataType.UINT32 || dataType == dev.zarr.zarrjava.v2.DataType.UINT32_BE; + boolean dataTypeIsLong = dataType == dev.zarr.zarrjava.v3.DataType.INT64 || dataType == dev.zarr.zarrjava.v2.DataType.INT64 || dataType == dev.zarr.zarrjava.v2.DataType.INT64_BE || dataType == dev.zarr.zarrjava.v3.DataType.UINT64 || dataType == dev.zarr.zarrjava.v2.DataType.UINT64 || dataType == dev.zarr.zarrjava.v2.DataType.UINT64_BE; + boolean dataTypeIsFloat = dataType == dev.zarr.zarrjava.v3.DataType.FLOAT32 || dataType == dev.zarr.zarrjava.v2.DataType.FLOAT32 || dataType == dev.zarr.zarrjava.v2.DataType.FLOAT32_BE; + boolean dataTypeIsDouble = dataType == dev.zarr.zarrjava.v3.DataType.FLOAT64 || dataType == dev.zarr.zarrjava.v2.DataType.FLOAT64 || dataType == dev.zarr.zarrjava.v2.DataType.FLOAT64_BE; if (fillValue instanceof Boolean) { Boolean fillValueBool = (Boolean) fillValue; diff --git a/src/main/java/dev/zarr/zarrjava/v2/DataType.java b/src/main/java/dev/zarr/zarrjava/v2/DataType.java index df06a7b..a0bbd73 100644 --- a/src/main/java/dev/zarr/zarrjava/v2/DataType.java +++ b/src/main/java/dev/zarr/zarrjava/v2/DataType.java @@ -13,7 +13,15 @@ public enum DataType implements dev.zarr.zarrjava.core.DataType { UINT32("u4", Endianness.LITTLE), UINT64("u8", Endianness.LITTLE), FLOAT32("f4", Endianness.LITTLE), - FLOAT64("f8", Endianness.LITTLE); + FLOAT64("f8", Endianness.LITTLE), + INT16_BE("i2", Endianness.BIG), + INT32_BE("i4", Endianness.BIG), + INT64_BE("i8", Endianness.BIG), + UINT16_BE("u2", Endianness.BIG), + UINT32_BE("u4", Endianness.BIG), + UINT64_BE("u8", Endianness.BIG), + FLOAT32_BE("f4", Endianness.BIG), + FLOAT64_BE("f8", Endianness.BIG); private final String dtype; private final Endianness endianness; @@ -41,22 +49,30 @@ public ucar.ma2.DataType getMA2DataType() { case INT8: return ucar.ma2.DataType.BYTE; case INT16: + case INT16_BE: return ucar.ma2.DataType.SHORT; case INT32: + case INT32_BE: return ucar.ma2.DataType.INT; case INT64: + case INT64_BE: return ucar.ma2.DataType.LONG; case UINT8: return ucar.ma2.DataType.UBYTE; case UINT16: + case UINT16_BE: return ucar.ma2.DataType.USHORT; case UINT32: + case UINT32_BE: return ucar.ma2.DataType.UINT; case UINT64: + case UINT64_BE: return ucar.ma2.DataType.ULONG; case FLOAT32: + case FLOAT32_BE: return ucar.ma2.DataType.FLOAT; case FLOAT64: + case FLOAT64_BE: return ucar.ma2.DataType.DOUBLE; default: throw new RuntimeException("Unreachable"); diff --git a/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java b/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java index 859314d..8bc26e2 100644 --- a/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java +++ b/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java @@ -196,7 +196,15 @@ static Stream compressorAndDataTypeProviderV2() { dev.zarr.zarrjava.v2.DataType.INT64, dev.zarr.zarrjava.v2.DataType.UINT64, dev.zarr.zarrjava.v2.DataType.FLOAT32, - dev.zarr.zarrjava.v2.DataType.FLOAT64 + dev.zarr.zarrjava.v2.DataType.FLOAT64, + dev.zarr.zarrjava.v2.DataType.UINT16_BE, + dev.zarr.zarrjava.v2.DataType.UINT32_BE, + dev.zarr.zarrjava.v2.DataType.UINT64_BE, + dev.zarr.zarrjava.v2.DataType.INT16_BE, + dev.zarr.zarrjava.v2.DataType.INT32_BE, + dev.zarr.zarrjava.v2.DataType.INT64_BE, + dev.zarr.zarrjava.v2.DataType.FLOAT32_BE, + dev.zarr.zarrjava.v2.DataType.FLOAT64_BE ).flatMap(dt -> Stream.of( new Object[]{"zlib", "0", dt}, new Object[]{"blosc", "blosclz_shuffle_3", dt} @@ -305,7 +313,7 @@ public void testWriteV3(String codec, String codecParam, DataType dataType) thro @MethodSource("compressorAndDataTypeProviderV2") public void testReadV2(String compressor, String compressorParam, dev.zarr.zarrjava.v2.DataType dt) throws IOException, ZarrException, InterruptedException { StoreHandle storeHandle = new FilesystemStore(TESTOUTPUT).resolve("testReadV2", compressor, compressorParam, dt.name()); - run_python_script("zarr_python_write_v2.py", compressor, compressorParam, dt.name().toLowerCase(), storeHandle.toPath().toString()); + run_python_script("zarr_python_write_v2.py", compressor, compressorParam, dt.getValue(), storeHandle.toPath().toString()); dev.zarr.zarrjava.v2.Array array = dev.zarr.zarrjava.v2.Array.open(storeHandle); ucar.ma2.Array result = array.read(); @@ -361,7 +369,7 @@ public void testWriteV2(String compressor, String compressorParam, dev.zarr.zarr assertIsTestdata(result, dt); //read in zarr_python - run_python_script("zarr_python_read_v2.py", compressor, compressorParam, dt.name().toLowerCase(), storeHandle.toPath().toString()); + run_python_script("zarr_python_read_v2.py", compressor, compressorParam, dt.getValue(), storeHandle.toPath().toString()); } @CsvSource({"0,true", "0,false", "5, true", "10, false"}) diff --git a/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java b/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java index c30f01d..583f254 100644 --- a/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java +++ b/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java @@ -109,7 +109,7 @@ public void testCreateZlib(int level) throws IOException, ZarrException { } @ParameterizedTest - @ValueSource(strings = {"BOOL", "INT8", "UINT8", "INT16", "UINT16", "INT32", "UINT32", "INT64", "UINT64", "FLOAT32", "FLOAT64"}) + @ValueSource(strings = {"BOOL", "INT8", "UINT8", "INT16", "UINT16", "INT32", "UINT32", "INT64", "UINT64", "FLOAT32", "FLOAT64", "INT16_BE", "UINT16_BE", "INT32_BE", "UINT32_BE", "INT64_BE", "UINT64_BE", "FLOAT32_BE", "FLOAT64_BE"}) public void testNoFillValue(DataType dataType) throws IOException, ZarrException { StoreHandle storeHandle = new FilesystemStore(TESTOUTPUT).resolve("v2_no_fillvalue", dataType.name()); @@ -409,7 +409,7 @@ public void testResizeArrayShrink() throws IOException, ZarrException { ucar.ma2.Array data = array.read(); int[] expectedData = new int[5 * 5]; for (int i = 0; i < 5; i++) { - System.arraycopy(testData, i * 10 + 0, expectedData, i * 5 + 0, 5); + System.arraycopy(testData, i * 10, expectedData, i * 5, 5); } Assertions.assertArrayEquals(expectedData, (int[]) data.get1DJavaArray(ma2DataType)); } @@ -449,7 +449,7 @@ public void testResizeArrayShrinkWithChunkCleanup() throws IOException, ZarrExce ucar.ma2.Array data = array.read(); int[] expectedData = new int[5 * 5]; for (int i = 0; i < 5; i++) { - System.arraycopy(testData, i * 10 + 0, expectedData, i * 5 + 0, 5); + System.arraycopy(testData, i * 10, expectedData, i * 5, 5); } Assertions.assertArrayEquals(expectedData, (int[]) data.get1DJavaArray(ma2DataType)); } diff --git a/src/test/python-scripts/zarr_python_read_v2.py b/src/test/python-scripts/zarr_python_read_v2.py index 2655231..7da8861 100644 --- a/src/test/python-scripts/zarr_python_read_v2.py +++ b/src/test/python-scripts/zarr_python_read_v2.py @@ -12,7 +12,7 @@ dtype = sys.argv[3] store_path = Path(sys.argv[4]) -if dtype == 'bool': +if 'b1' in dtype: expected_data = np.arange(16 * 16 * 16, dtype='uint8').reshape(16, 16, 16) % 2 == 0 else: expected_data = np.arange(16 * 16 * 16, dtype=dtype).reshape(16, 16, 16) diff --git a/src/test/python-scripts/zarr_python_write_v2.py b/src/test/python-scripts/zarr_python_write_v2.py index f362b0c..03a1774 100644 --- a/src/test/python-scripts/zarr_python_write_v2.py +++ b/src/test/python-scripts/zarr_python_write_v2.py @@ -12,7 +12,7 @@ dtype = sys.argv[3] store_path = Path(sys.argv[4]) -if dtype == 'bool': +if 'b1' in dtype: testdata = np.arange(16 * 16 * 16, dtype='uint8').reshape(16, 16, 16) % 2 == 0 else: testdata = np.arange(16 * 16 * 16, dtype=dtype).reshape(16, 16, 16) From aa8931a2a4613ea438927f8a0978a82328b38b1d Mon Sep 17 00:00:00 2001 From: brokkoli71 Date: Fri, 13 Feb 2026 15:04:47 +0100 Subject: [PATCH 2/2] add endian tests --- .../zarrjava/v2/ArrayMetadataBuilder.java | 4 +- .../dev/zarr/zarrjava/ZarrPythonTests.java | 113 +---------------- src/test/java/dev/zarr/zarrjava/ZarrTest.java | 120 ++++++++++++++++++ .../java/dev/zarr/zarrjava/ZarrV2Test.java | 20 +++ .../java/dev/zarr/zarrjava/ZarrV3Test.java | 38 +++++- 5 files changed, 181 insertions(+), 114 deletions(-) diff --git a/src/main/java/dev/zarr/zarrjava/v2/ArrayMetadataBuilder.java b/src/main/java/dev/zarr/zarrjava/v2/ArrayMetadataBuilder.java index 091762c..9a26f93 100644 --- a/src/main/java/dev/zarr/zarrjava/v2/ArrayMetadataBuilder.java +++ b/src/main/java/dev/zarr/zarrjava/v2/ArrayMetadataBuilder.java @@ -150,12 +150,12 @@ public ArrayMetadata build() throws ZarrException { if (dataType == null) { throw new IllegalStateException("Please call `withDataType` first."); } - + // If chunks are not specified, calculate default chunks if (chunks == null) { chunks = Utils.calculateDefaultChunks(shape); } - + return new ArrayMetadata( 2, shape, diff --git a/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java b/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java index 8bc26e2..8b685a0 100644 --- a/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java +++ b/src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java @@ -66,97 +66,8 @@ public static void setupUV() { } } - static ucar.ma2.Array testdata(dev.zarr.zarrjava.core.DataType dt) { - ucar.ma2.DataType ma2Type = dt.getMA2DataType(); - ucar.ma2.Array array = ucar.ma2.Array.factory(ma2Type, new int[]{16, 16, 16}); - for (int i = 0; i < array.getSize(); i++) { - switch (ma2Type) { - case BOOLEAN: - array.setBoolean(i, i % 2 == 0); - break; - case BYTE: - case UBYTE: - array.setByte(i, (byte) i); - break; - case SHORT: - case USHORT: - array.setShort(i, (short) i); - break; - case INT: - array.setInt(i, i); - break; - case UINT: - array.setLong(i, i & 0xFFFFFFFFL); - break; - case LONG: - case ULONG: - array.setLong(i, i); - break; - case FLOAT: - array.setFloat(i, (float) i); - break; - case DOUBLE: - array.setDouble(i, i); - break; - default: - throw new IllegalArgumentException("Invalid DataType: " + dt); - } - } - return array; - } - - static void assertIsTestdata(ucar.ma2.Array result, dev.zarr.zarrjava.core.DataType dt) { - // expected values are i for index i - ucar.ma2.DataType ma2Type = dt.getMA2DataType(); - for (int i = 0; i < result.getSize(); i++) { - switch (ma2Type) { - case BOOLEAN: - Assertions.assertEquals(i % 2 == 0, result.getBoolean(i)); - break; - case BYTE: - case UBYTE: - Assertions.assertEquals((byte) i, result.getByte(i)); - break; - case SHORT: - case USHORT: - Assertions.assertEquals((short) i, result.getShort(i)); - break; - case INT: - Assertions.assertEquals(i, result.getInt(i)); - break; - case UINT: - Assertions.assertEquals(i & 0xFFFFFFFFL, result.getLong(i)); - break; - case LONG: - case ULONG: - Assertions.assertEquals(i, result.getLong(i)); - break; - case FLOAT: - Assertions.assertEquals((float) i, result.getFloat(i), 1e-6); - break; - case DOUBLE: - Assertions.assertEquals(i, result.getDouble(i), 1e-12); - break; - default: - throw new IllegalArgumentException("Invalid DataType: " + dt); - } - } - } - static Stream compressorAndDataTypeProviderV3() { - Stream datatypeTests = Stream.of( - DataType.BOOL, - DataType.INT8, - DataType.UINT8, - DataType.INT16, - DataType.UINT16, - DataType.INT32, - DataType.UINT32, - DataType.INT64, - DataType.UINT64, - DataType.FLOAT32, - DataType.FLOAT64 - ).flatMap(dt -> Stream.of( + Stream datatypeTests = dataTypeProviderV3().flatMap(dt -> Stream.of( new Object[]{"sharding", "end", dt}, new Object[]{"blosc", "blosclz_shuffle_3", dt} )); @@ -185,27 +96,7 @@ static Stream compressorAndDataTypeProviderV3() { } static Stream compressorAndDataTypeProviderV2() { - Stream datatypeTests = Stream.of( - dev.zarr.zarrjava.v2.DataType.BOOL, - dev.zarr.zarrjava.v2.DataType.INT8, - dev.zarr.zarrjava.v2.DataType.UINT8, - dev.zarr.zarrjava.v2.DataType.INT16, - dev.zarr.zarrjava.v2.DataType.UINT16, - dev.zarr.zarrjava.v2.DataType.INT32, - dev.zarr.zarrjava.v2.DataType.UINT32, - dev.zarr.zarrjava.v2.DataType.INT64, - dev.zarr.zarrjava.v2.DataType.UINT64, - dev.zarr.zarrjava.v2.DataType.FLOAT32, - dev.zarr.zarrjava.v2.DataType.FLOAT64, - dev.zarr.zarrjava.v2.DataType.UINT16_BE, - dev.zarr.zarrjava.v2.DataType.UINT32_BE, - dev.zarr.zarrjava.v2.DataType.UINT64_BE, - dev.zarr.zarrjava.v2.DataType.INT16_BE, - dev.zarr.zarrjava.v2.DataType.INT32_BE, - dev.zarr.zarrjava.v2.DataType.INT64_BE, - dev.zarr.zarrjava.v2.DataType.FLOAT32_BE, - dev.zarr.zarrjava.v2.DataType.FLOAT64_BE - ).flatMap(dt -> Stream.of( + Stream datatypeTests = dataTypeProviderV2().flatMap(dt -> Stream.of( new Object[]{"zlib", "0", dt}, new Object[]{"blosc", "blosclz_shuffle_3", dt} )); diff --git a/src/test/java/dev/zarr/zarrjava/ZarrTest.java b/src/test/java/dev/zarr/zarrjava/ZarrTest.java index 7657b83..fdb8ec1 100644 --- a/src/test/java/dev/zarr/zarrjava/ZarrTest.java +++ b/src/test/java/dev/zarr/zarrjava/ZarrTest.java @@ -1,6 +1,7 @@ package dev.zarr.zarrjava; import dev.zarr.zarrjava.core.Attributes; +import dev.zarr.zarrjava.v3.DataType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -34,6 +35,46 @@ public static void clearTestoutputFolder() throws IOException { Files.createDirectory(TESTOUTPUT); } + static Stream dataTypeProviderV3() { + return Stream.of( + DataType.BOOL, + DataType.INT8, + DataType.UINT8, + DataType.INT16, + DataType.UINT16, + DataType.INT32, + DataType.UINT32, + DataType.INT64, + DataType.UINT64, + DataType.FLOAT32, + DataType.FLOAT64 + ); + } + + static Stream dataTypeProviderV2() { + return Stream.of( + dev.zarr.zarrjava.v2.DataType.BOOL, + dev.zarr.zarrjava.v2.DataType.INT8, + dev.zarr.zarrjava.v2.DataType.UINT8, + dev.zarr.zarrjava.v2.DataType.INT16, + dev.zarr.zarrjava.v2.DataType.UINT16, + dev.zarr.zarrjava.v2.DataType.INT32, + dev.zarr.zarrjava.v2.DataType.UINT32, + dev.zarr.zarrjava.v2.DataType.INT64, + dev.zarr.zarrjava.v2.DataType.UINT64, + dev.zarr.zarrjava.v2.DataType.FLOAT32, + dev.zarr.zarrjava.v2.DataType.FLOAT64, + dev.zarr.zarrjava.v2.DataType.UINT16_BE, + dev.zarr.zarrjava.v2.DataType.UINT32_BE, + dev.zarr.zarrjava.v2.DataType.UINT64_BE, + dev.zarr.zarrjava.v2.DataType.INT16_BE, + dev.zarr.zarrjava.v2.DataType.INT32_BE, + dev.zarr.zarrjava.v2.DataType.INT64_BE, + dev.zarr.zarrjava.v2.DataType.FLOAT32_BE, + dev.zarr.zarrjava.v2.DataType.FLOAT64_BE + ); + } + protected void assertListEquals(List a, List b) { Assertions.assertEquals(a.size(), b.size()); for (int i = 0; i < a.size(); i++) { @@ -112,4 +153,83 @@ protected void assertContainsTestAttributes(Attributes attributes) throws ZarrEx ); } + + protected ucar.ma2.Array testdata(dev.zarr.zarrjava.core.DataType dt) { + ucar.ma2.DataType ma2Type = dt.getMA2DataType(); + ucar.ma2.Array array = ucar.ma2.Array.factory(ma2Type, new int[]{16, 16, 16}); + for (int i = 0; i < array.getSize(); i++) { + switch (ma2Type) { + case BOOLEAN: + array.setBoolean(i, i % 2 == 0); + break; + case BYTE: + case UBYTE: + array.setByte(i, (byte) i); + break; + case SHORT: + case USHORT: + array.setShort(i, (short) i); + break; + case INT: + array.setInt(i, i); + break; + case UINT: + array.setLong(i, i & 0xFFFFFFFFL); + break; + case LONG: + case ULONG: + array.setLong(i, i); + break; + case FLOAT: + array.setFloat(i, (float) i); + break; + case DOUBLE: + array.setDouble(i, i); + break; + default: + throw new IllegalArgumentException("Invalid DataType: " + dt); + } + } + return array; + } + + protected void assertIsTestdata(ucar.ma2.Array result, dev.zarr.zarrjava.core.DataType dt) { + // expected values are i for index i + ucar.ma2.DataType ma2Type = dt.getMA2DataType(); + for (int i = 0; i < result.getSize(); i++) { + switch (ma2Type) { + case BOOLEAN: + Assertions.assertEquals(i % 2 == 0, result.getBoolean(i)); + break; + case BYTE: + case UBYTE: + Assertions.assertEquals((byte) i, result.getByte(i)); + break; + case SHORT: + case USHORT: + Assertions.assertEquals((short) i, result.getShort(i)); + break; + case INT: + Assertions.assertEquals(i, result.getInt(i)); + break; + case UINT: + Assertions.assertEquals(i & 0xFFFFFFFFL, result.getLong(i)); + break; + case LONG: + case ULONG: + Assertions.assertEquals(i, result.getLong(i)); + break; + case FLOAT: + Assertions.assertEquals((float) i, result.getFloat(i), 1e-6); + break; + case DOUBLE: + Assertions.assertEquals(i, result.getDouble(i), 1e-12); + break; + default: + throw new IllegalArgumentException("Invalid DataType: " + dt); + } + } + } + + } diff --git a/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java b/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java index 583f254..bb0f5a5 100644 --- a/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java +++ b/src/test/java/dev/zarr/zarrjava/ZarrV2Test.java @@ -26,6 +26,7 @@ import java.util.stream.Stream; import static dev.zarr.zarrjava.core.Node.ZARRAY; +import static dev.zarr.zarrjava.utils.Utils.toLongArray; public class ZarrV2Test extends ZarrTest { static Stream> compressorBuilder() { @@ -581,4 +582,23 @@ public void testDefaultChunkShape() throws IOException, ZarrException { Assertions.assertTrue(mixedArray.metadata().chunks[2] > 0); Assertions.assertTrue(mixedArray.metadata().chunks[2] <= 2048); } + + @ParameterizedTest + @MethodSource("dataTypeProviderV2") + public void testEndianness(DataType dataType) throws IOException, ZarrException { + StoreHandle storeHandle = new FilesystemStore(TESTOUTPUT).resolve("testEndiannessV2").resolve(dataType.name()); + ucar.ma2.Array testData = testdata(dataType); + + Array array = Array.create( + storeHandle, + Array.metadataBuilder() + .withShape(toLongArray(testData.getShape())) + .withDataType(dataType) + .build() + ); + array.write(testData); + Array reopenedArray = Array.open(storeHandle); + ucar.ma2.Array readData = reopenedArray.read(); + assertIsTestdata(readData, dataType); + } } diff --git a/src/test/java/dev/zarr/zarrjava/ZarrV3Test.java b/src/test/java/dev/zarr/zarrjava/ZarrV3Test.java index 601b6da..fa0006e 100644 --- a/src/test/java/dev/zarr/zarrjava/ZarrV3Test.java +++ b/src/test/java/dev/zarr/zarrjava/ZarrV3Test.java @@ -40,6 +40,7 @@ import static dev.zarr.zarrjava.core.ArrayMetadata.parseFillValue; import static dev.zarr.zarrjava.core.Node.ZARR_JSON; +import static dev.zarr.zarrjava.utils.Utils.toLongArray; import static org.junit.Assert.assertThrows; public class ZarrV3Test extends ZarrTest { @@ -118,6 +119,23 @@ static Stream unalignedArrayAccessProvider() { return builder.build(); } + static Stream dataTypeAndEndianProvider() { + return Stream.of( + Arguments.of(DataType.INT16, BytesCodec.Endian.LITTLE), + Arguments.of(DataType.INT16, BytesCodec.Endian.BIG), + Arguments.of(DataType.UINT16, BytesCodec.Endian.LITTLE), + Arguments.of(DataType.UINT16, BytesCodec.Endian.BIG), + Arguments.of(DataType.INT32, BytesCodec.Endian.LITTLE), + Arguments.of(DataType.INT32, BytesCodec.Endian.BIG), + Arguments.of(DataType.UINT32, BytesCodec.Endian.LITTLE), + Arguments.of(DataType.UINT32, BytesCodec.Endian.BIG), + Arguments.of(DataType.FLOAT32, BytesCodec.Endian.LITTLE), + Arguments.of(DataType.FLOAT32, BytesCodec.Endian.BIG), + Arguments.of(DataType.FLOAT64, BytesCodec.Endian.LITTLE), + Arguments.of(DataType.FLOAT64, BytesCodec.Endian.BIG) + ); + } + @ParameterizedTest @MethodSource("invalidCodecBuilder") public void testCheckInvalidCodecConfiguration(Function codecBuilder) { @@ -997,7 +1015,7 @@ public void testLargeArrayWithOffsetBeyondMaxInt() throws IOException, ZarrExcep array.write(new long[]{0, 0}, smallChunk); // Write a small chunk at position [1, Integer.MAX_VALUE + 1] - long beyondIntMax = (long)(Integer.MAX_VALUE) + 1; + long beyondIntMax = (long) (Integer.MAX_VALUE) + 1; long[] offset = new long[]{1, beyondIntMax}; Arrays.fill(testData, 200); smallChunk = ucar.ma2.Array.factory(ucar.ma2.DataType.INT, new int[]{1, 1000}, testData); @@ -1016,4 +1034,22 @@ public void testLargeArrayWithOffsetBeyondMaxInt() throws IOException, ZarrExcep Assertions.assertEquals(largeSize, array.metadata().shape[0]); Assertions.assertEquals(largeSize, array.metadata().shape[1]); } + + @ParameterizedTest + @MethodSource("dataTypeAndEndianProvider") + public void testEndianness(DataType dataType, BytesCodec.Endian endian) throws IOException, ZarrException { + StoreHandle storeHandle = new FilesystemStore(TESTOUTPUT).resolve("testEndiannessV3").resolve(dataType.name()).resolve(endian.name()); + ucar.ma2.Array testData = testdata(dataType); + + ArrayMetadata metadata = Array.metadataBuilder() + .withShape(toLongArray(testData.getShape())) + .withDataType(dataType) + .withCodecs(c -> c.withBytes(endian)) + .build(); + Array array = Array.create(storeHandle, metadata); + array.write(testData); + Array reopenedArray = Array.open(storeHandle); + ucar.ma2.Array readData = reopenedArray.read(); + assertIsTestdata(readData, dataType); + } }