mirror of
https://github.com/HDFGroup/hdf5.git
synced 2026-09-25 04:09:44 +03:00
FFM build requires Java 25, Jextract 25. Generates FFM bindings during configure. JNI is default when the requirements are not met or can be forced. Presets added for maven and FFM - JNI is default selection. Enhanced Maven options will work with either JNI or FFM New Workflows for testing and maven uploads. Extensive documentation changes for java.
2207 lines
84 KiB
Java
2207 lines
84 KiB
Java
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the LICENSE file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
package jtest;
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
import static jtest.FfmTestSupport.*;
|
|
|
|
import java.lang.foreign.Arena;
|
|
import java.lang.foreign.MemorySegment;
|
|
import java.lang.foreign.ValueLayout;
|
|
|
|
import org.hdfgroup.javahdf5.hdf5_h;
|
|
import org.junit.After;
|
|
import org.junit.Assume;
|
|
import org.junit.Ignore;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.rules.TestName;
|
|
|
|
/**
|
|
* FFM-only tests for HDF5 Datatype (H5T) operations.
|
|
*
|
|
* This test class uses direct FFM bindings without the hdf.hdf5lib wrapper layer.
|
|
*
|
|
* Note: Some tests are disabled on Windows due to known FFM limitations.
|
|
*/
|
|
public class TestH5Tffm {
|
|
@Rule
|
|
public TestName testname = new TestName();
|
|
|
|
/** Helper to check if running on Windows */
|
|
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
|
|
|
|
static
|
|
{
|
|
// Initialize FFM library by calling H5open()
|
|
// This ensures global type variables are properly initialized
|
|
try {
|
|
hdf5_h.H5open();
|
|
}
|
|
catch (Exception e) {
|
|
System.err.println("Warning: H5open() failed during FFM initialization: " + e);
|
|
}
|
|
}
|
|
|
|
// Predefined datatype constants
|
|
|
|
// Datatype classes
|
|
|
|
// String padding
|
|
|
|
long H5tid = hdf5_h.H5I_INVALID_HID();
|
|
|
|
@After
|
|
public void cleanup()
|
|
{
|
|
closeQuietly(H5tid, hdf5_h::H5Tclose);
|
|
H5tid = hdf5_h.H5I_INVALID_HID();
|
|
System.out.println();
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcopy()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tequal()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
long tid2 = hdf5_h.H5I_INVALID_HID();
|
|
|
|
try {
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
tid2 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(tid2));
|
|
|
|
int result = hdf5_h.H5Tequal(H5tid, tid2);
|
|
assertTrue("Types should be equal", result > 0);
|
|
|
|
// Compare with different type
|
|
result = hdf5_h.H5Tequal(H5tid, hdf5_h.H5T_IEEE_F32LE_g());
|
|
assertFalse("Types should not be equal", result > 0);
|
|
}
|
|
finally {
|
|
closeQuietly(tid2, hdf5_h::H5Tclose);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_class()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Type class should be INTEGER", hdf5_h.H5T_INTEGER(), tclass);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_size()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertTrue("Type size should be > 0", size > 0);
|
|
assertEquals("H5T_STD_I32LE should be 4 bytes", 4, size);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_size()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int result = hdf5_h.H5Tset_size(H5tid, 64);
|
|
assertTrue("H5Tset_size failed", isSuccess(result));
|
|
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertEquals("Size should be 64", 64, size);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_order()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int order = hdf5_h.H5Tget_order(H5tid);
|
|
assertTrue("Byte order should be valid", order >= 0);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_precision()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
long precision = hdf5_h.H5Tget_precision(H5tid);
|
|
assertTrue("Precision should be > 0", precision > 0);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_precision()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int result = hdf5_h.H5Tset_precision(H5tid, 16);
|
|
assertTrue("H5Tset_precision failed", isSuccess(result));
|
|
|
|
long precision = hdf5_h.H5Tget_precision(H5tid);
|
|
assertEquals("Precision should be 16", 16, precision);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_strpad()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int strpad = hdf5_h.H5Tget_strpad(H5tid);
|
|
assertTrue("String padding should be valid", strpad >= 0);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcreate_compound()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create a compound type with int and double
|
|
int compoundSize = 4 + 8; // sizeof(int) + sizeof(double)
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), compoundSize);
|
|
assertTrue("H5Tcreate failed", isValidId(H5tid));
|
|
|
|
// Insert int member
|
|
MemorySegment intNameSegment = stringToSegment(arena, "int_field");
|
|
int result = hdf5_h.H5Tinsert(H5tid, intNameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tinsert int failed", isSuccess(result));
|
|
|
|
// Insert double member
|
|
MemorySegment doubleNameSegment = stringToSegment(arena, "double_field");
|
|
result = hdf5_h.H5Tinsert(H5tid, doubleNameSegment, 4, hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("H5Tinsert double failed", isSuccess(result));
|
|
|
|
// Verify it's a compound type
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Type class should be COMPOUND", hdf5_h.H5T_COMPOUND(), tclass);
|
|
|
|
// Verify number of members
|
|
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
|
|
assertEquals("Should have 2 members", 2, nmembers);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_nmembers()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
assertTrue("H5Tcreate failed", isValidId(H5tid));
|
|
|
|
MemorySegment nameSegment = stringToSegment(arena, "field1");
|
|
hdf5_h.H5Tinsert(H5tid, nameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
|
|
assertEquals("Should have 1 member", 1, nmembers);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_member_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
assertTrue("H5Tcreate failed", isValidId(H5tid));
|
|
|
|
String fieldName = "test_field";
|
|
MemorySegment nameSegment = stringToSegment(arena, fieldName);
|
|
hdf5_h.H5Tinsert(H5tid, nameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
MemorySegment returnedName = hdf5_h.H5Tget_member_name(H5tid, 0);
|
|
assertFalse("Returned name should not be null", returnedName.equals(MemorySegment.NULL));
|
|
|
|
String memberName = returnedName.getString(0);
|
|
assertEquals("Member name should match", fieldName, memberName);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_member_offset()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
assertTrue("H5Tcreate failed", isValidId(H5tid));
|
|
|
|
long expectedOffset = 4;
|
|
MemorySegment nameSegment = stringToSegment(arena, "field");
|
|
hdf5_h.H5Tinsert(H5tid, nameSegment, expectedOffset, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
long offset = hdf5_h.H5Tget_member_offset(H5tid, 0);
|
|
assertEquals("Offset should match", expectedOffset, offset);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_member_type()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
long memberType = hdf5_h.H5I_INVALID_HID();
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
assertTrue("H5Tcreate failed", isValidId(H5tid));
|
|
|
|
MemorySegment nameSegment = stringToSegment(arena, "field");
|
|
hdf5_h.H5Tinsert(H5tid, nameSegment, 0, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
memberType = hdf5_h.H5Tget_member_type(H5tid, 0);
|
|
assertTrue("H5Tget_member_type failed", isValidId(memberType));
|
|
|
|
// Verify it's an integer type
|
|
int tclass = hdf5_h.H5Tget_class(memberType);
|
|
assertEquals("Member type should be INTEGER", hdf5_h.H5T_INTEGER(), tclass);
|
|
}
|
|
finally {
|
|
closeQuietly(memberType, hdf5_h::H5Tclose);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tarray_create()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create array type: int[3][4]
|
|
int rank = 2;
|
|
long[] dims = {3, 4};
|
|
MemorySegment dimsSegment = allocateLongArray(arena, rank);
|
|
copyToSegment(dimsSegment, dims);
|
|
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), rank, dimsSegment);
|
|
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
|
|
|
|
// Verify it's an array type
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Type class should be ARRAY", hdf5_h.H5T_ARRAY(), tclass);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_array_dims()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
int rank = 2;
|
|
long[] expectedDims = {3, 4};
|
|
MemorySegment dimsSegment = allocateLongArray(arena, rank);
|
|
copyToSegment(dimsSegment, expectedDims);
|
|
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), rank, dimsSegment);
|
|
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
|
|
|
|
MemorySegment returnedDimsSegment = allocateLongArray(arena, rank);
|
|
int result = hdf5_h.H5Tget_array_dims2(H5tid, returnedDimsSegment);
|
|
assertEquals("H5Tget_array_dims2 should return rank", rank, result);
|
|
|
|
long[] returnedDims = new long[rank];
|
|
copyFromSegment(returnedDimsSegment, returnedDims);
|
|
assertArrayEquals("Array dimensions should match", expectedDims, returnedDims);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_operations()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create enum type
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tenum_create failed", isValidId(H5tid));
|
|
|
|
// Insert enum values
|
|
MemorySegment redSegment = stringToSegment(arena, "RED");
|
|
MemorySegment redValueSegment = allocateInt(arena);
|
|
setInt(redValueSegment, 0);
|
|
int result = hdf5_h.H5Tenum_insert(H5tid, redSegment, redValueSegment);
|
|
assertTrue("H5Tenum_insert RED failed", isSuccess(result));
|
|
|
|
MemorySegment greenSegment = stringToSegment(arena, "GREEN");
|
|
MemorySegment greenValueSegment = allocateInt(arena);
|
|
setInt(greenValueSegment, 1);
|
|
result = hdf5_h.H5Tenum_insert(H5tid, greenSegment, greenValueSegment);
|
|
assertTrue("H5Tenum_insert GREEN failed", isSuccess(result));
|
|
|
|
MemorySegment blueSegment = stringToSegment(arena, "BLUE");
|
|
MemorySegment blueValueSegment = allocateInt(arena);
|
|
setInt(blueValueSegment, 2);
|
|
result = hdf5_h.H5Tenum_insert(H5tid, blueSegment, blueValueSegment);
|
|
assertTrue("H5Tenum_insert BLUE failed", isSuccess(result));
|
|
|
|
// Verify number of members
|
|
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
|
|
assertEquals("Should have 3 members", 3, nmembers);
|
|
|
|
// Test H5Tenum_nameof - get name from value
|
|
MemorySegment lookupValueSegment = allocateInt(arena);
|
|
setInt(lookupValueSegment, 1);
|
|
|
|
MemorySegment nameSegment = arena.allocate(64); // Allocate buffer for name
|
|
int nameResult = hdf5_h.H5Tenum_nameof(H5tid, lookupValueSegment, nameSegment, 64);
|
|
assertTrue("H5Tenum_nameof failed", isSuccess(nameResult));
|
|
|
|
String name = nameSegment.getString(0);
|
|
assertEquals("Name should be GREEN", "GREEN", name);
|
|
|
|
// Test H5Tenum_valueof - get value from name
|
|
MemorySegment lookupNameSegment = stringToSegment(arena, "BLUE");
|
|
MemorySegment valueSegment = allocateInt(arena);
|
|
result = hdf5_h.H5Tenum_valueof(H5tid, lookupNameSegment, valueSegment);
|
|
assertTrue("H5Tenum_valueof failed", isSuccess(result));
|
|
|
|
int value = getInt(valueSegment);
|
|
assertEquals("Value should be 2", 2, value);
|
|
|
|
// Verify it's an enum type
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Type class should be ENUM", hdf5_h.H5T_ENUM(), tclass);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tis_variable_str()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create fixed-length string type
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
hdf5_h.H5Tset_size(H5tid, 10);
|
|
|
|
int result = hdf5_h.H5Tis_variable_str(H5tid);
|
|
assertFalse("Fixed-length string should not be variable", result > 0);
|
|
|
|
// Close and create variable-length string type
|
|
hdf5_h.H5Tclose(H5tid);
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
hdf5_h.H5Tset_size(H5tid, -1); // H5T_VARIABLE
|
|
|
|
result = hdf5_h.H5Tis_variable_str(H5tid);
|
|
assertTrue("Variable-length string should be variable", result > 0);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_cset()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int cset = hdf5_h.H5Tget_cset(H5tid);
|
|
assertTrue("Character set should be valid", cset >= 0);
|
|
// H5T_CSET_ASCII = 0
|
|
assertEquals("Default character set should be ASCII", 0, cset);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tclose()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
int result = hdf5_h.H5Tclose(H5tid);
|
|
assertTrue("H5Tclose failed", isSuccess(result));
|
|
H5tid = hdf5_h.H5I_INVALID_HID();
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tvlen_create()
|
|
{
|
|
// Skip on Windows - FFM memory layout issue with variable-length types
|
|
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
|
|
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create variable-length type of integers
|
|
// Use H5T_STD_I32LE instead of H5T_NATIVE_INT for platform consistency
|
|
H5tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tvlen_create failed", isValidId(H5tid));
|
|
|
|
// Verify it's a variable-length type
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Should be H5T_VLEN class", hdf5_h.H5T_VLEN(), tclass);
|
|
|
|
// Get the base type
|
|
long base_type = hdf5_h.H5Tget_super(H5tid);
|
|
assertTrue("H5Tget_super should return valid type", isValidId(base_type));
|
|
|
|
// Verify base type is 32-bit integer
|
|
int equal = hdf5_h.H5Tequal(base_type, hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("Base type should be H5T_STD_I32LE", equal > 0);
|
|
|
|
hdf5_h.H5Tclose(base_type);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Topaque_operations()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create opaque type with 16 bytes
|
|
long size = 16;
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), size);
|
|
assertTrue("H5Tcreate opaque failed", isValidId(H5tid));
|
|
|
|
// Verify it's opaque
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Should be H5T_OPAQUE class", hdf5_h.H5T_OPAQUE(), tclass);
|
|
|
|
// Set tag for opaque type
|
|
String tag = "16-byte opaque data";
|
|
MemorySegment tagSegment = stringToSegment(arena, tag);
|
|
int result = hdf5_h.H5Tset_tag(H5tid, tagSegment);
|
|
assertTrue("H5Tset_tag failed", isSuccess(result));
|
|
|
|
// Get tag back
|
|
MemorySegment outTag = hdf5_h.H5Tget_tag(H5tid);
|
|
assertFalse("H5Tget_tag should return valid pointer", outTag.address() == 0);
|
|
|
|
String retrievedTag = outTag.getString(0);
|
|
assertEquals("Tag should match", tag, retrievedTag);
|
|
|
|
// Verify size
|
|
long retrievedSize = hdf5_h.H5Tget_size(H5tid);
|
|
assertEquals("Size should be 16", size, retrievedSize);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_sign_set_sign()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create integer type
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
// Get current sign
|
|
int sign = hdf5_h.H5Tget_sign(H5tid);
|
|
assertTrue("H5Tget_sign should succeed", sign >= 0);
|
|
|
|
// Set to unsigned
|
|
int result = hdf5_h.H5Tset_sign(H5tid, hdf5_h.H5T_SGN_NONE());
|
|
assertTrue("H5Tset_sign failed", isSuccess(result));
|
|
|
|
// Verify sign changed
|
|
int newSign = hdf5_h.H5Tget_sign(H5tid);
|
|
assertEquals("Sign should be H5T_SGN_NONE", hdf5_h.H5T_SGN_NONE(), newSign);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_offset_set_offset()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create integer type
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
// Get current offset
|
|
long offset = hdf5_h.H5Tget_offset(H5tid);
|
|
assertTrue("H5Tget_offset should succeed", offset >= 0);
|
|
|
|
// Set new offset (shift by 2 bits)
|
|
long newOffset = 2;
|
|
int result = hdf5_h.H5Tset_offset(H5tid, newOffset);
|
|
assertTrue("H5Tset_offset failed", isSuccess(result));
|
|
|
|
// Verify offset changed
|
|
long retrievedOffset = hdf5_h.H5Tget_offset(H5tid);
|
|
assertEquals("Offset should be 2", newOffset, retrievedOffset);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_pad_set_pad()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create integer type
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(H5tid));
|
|
|
|
// Get current padding
|
|
MemorySegment lsbSegment = allocateInt(arena);
|
|
MemorySegment msbSegment = allocateInt(arena);
|
|
int result = hdf5_h.H5Tget_pad(H5tid, lsbSegment, msbSegment);
|
|
assertTrue("H5Tget_pad failed", isSuccess(result));
|
|
|
|
// Set new padding (both to zero)
|
|
result = hdf5_h.H5Tset_pad(H5tid, hdf5_h.H5T_PAD_ZERO(), hdf5_h.H5T_PAD_ZERO());
|
|
assertTrue("H5Tset_pad failed", isSuccess(result));
|
|
|
|
// Verify padding changed
|
|
MemorySegment newLsbSegment = allocateInt(arena);
|
|
MemorySegment newMsbSegment = allocateInt(arena);
|
|
result = hdf5_h.H5Tget_pad(H5tid, newLsbSegment, newMsbSegment);
|
|
assertTrue("H5Tget_pad failed", isSuccess(result));
|
|
|
|
assertEquals("LSB padding should be ZERO", hdf5_h.H5T_PAD_ZERO(), getInt(newLsbSegment));
|
|
assertEquals("MSB padding should be ZERO", hdf5_h.H5T_PAD_ZERO(), getInt(newMsbSegment));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tconvert_basic()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create buffer with int values
|
|
int numElements = 5;
|
|
int[] intData = {1, 2, 3, 4, 5};
|
|
|
|
// Allocate buffer and copy int data
|
|
MemorySegment buffer = arena.allocate(numElements * 8); // Enough for doubles
|
|
for (int i = 0; i < numElements; i++) {
|
|
buffer.setAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, i, intData[i]);
|
|
}
|
|
|
|
// Convert int to double
|
|
long srcType = hdf5_h.H5T_STD_I32LE_g();
|
|
long dstType = hdf5_h.H5T_IEEE_F64LE_g();
|
|
int result = hdf5_h.H5Tconvert(srcType, dstType, numElements, buffer, MemorySegment.NULL,
|
|
hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Tconvert failed", isSuccess(result));
|
|
|
|
// Verify first converted value
|
|
double convertedValue = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_DOUBLE, 0);
|
|
assertEquals("First value should be 1.0", 1.0, convertedValue, 0.001);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tconvert_int_to_float()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create buffer with int values
|
|
int numElements = 3;
|
|
int[] intData = {10, 20, 30};
|
|
|
|
// Allocate separate buffers for in-place conversion
|
|
MemorySegment buffer = arena.allocate(numElements * 4); // 4 bytes per int/float
|
|
for (int i = 0; i < numElements; i++) {
|
|
buffer.setAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, i, intData[i]);
|
|
}
|
|
|
|
// Convert int to float in-place
|
|
int result = hdf5_h.H5Tconvert(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_IEEE_F32LE_g(), numElements,
|
|
buffer, MemorySegment.NULL, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Tconvert failed", isSuccess(result));
|
|
|
|
// Verify converted values
|
|
float val0 = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_FLOAT, 0);
|
|
float val1 = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_FLOAT, 1);
|
|
float val2 = buffer.getAtIndex(java.lang.foreign.ValueLayout.JAVA_FLOAT, 2);
|
|
|
|
assertEquals("First value should be 10.0", 10.0f, val0, 0.001f);
|
|
assertEquals("Second value should be 20.0", 20.0f, val1, 0.001f);
|
|
assertEquals("Third value should be 30.0", 30.0f, val2, 0.001f);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Treclaim_with_vlen_string()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create variable-length string type
|
|
long strType = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(strType));
|
|
|
|
int result = hdf5_h.H5Tset_size(strType, -1); // H5T_VARIABLE
|
|
assertTrue("H5Tset_size failed", isSuccess(result));
|
|
|
|
// Create simple 1D dataspace with 1 element
|
|
long[] dimsArray = {1};
|
|
MemorySegment dims = allocateLongArray(arena, 1);
|
|
copyToSegment(dims, dimsArray);
|
|
long space = hdf5_h.H5Screate_simple(1, dims, MemorySegment.NULL);
|
|
assertTrue("H5Screate_simple failed", isValidId(space));
|
|
|
|
// Allocate buffer for pointer to string
|
|
MemorySegment buffer = arena.allocate(8); // Pointer size
|
|
|
|
// Set to NULL initially (nothing to reclaim, but tests the API)
|
|
buffer.set(java.lang.foreign.ValueLayout.ADDRESS, 0, MemorySegment.NULL);
|
|
|
|
// Test H5Treclaim - should succeed even with NULL pointer
|
|
result = hdf5_h.H5Treclaim(strType, space, hdf5_h.H5P_DEFAULT(), buffer);
|
|
assertTrue("H5Treclaim should succeed", isSuccess(result));
|
|
|
|
// Cleanup
|
|
hdf5_h.H5Sclose(space);
|
|
hdf5_h.H5Tclose(strType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tfind_conversion_path()
|
|
{
|
|
// Skip on Windows - FFM memory layout issue with conversion functions
|
|
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
|
|
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Try to find conversion path from int to float
|
|
MemorySegment pcdata = arena.allocate(8); // Pointer to H5T_cdata_t*
|
|
pcdata.set(java.lang.foreign.ValueLayout.ADDRESS, 0, MemorySegment.NULL);
|
|
|
|
MemorySegment convFunc =
|
|
hdf5_h.H5Tfind(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_IEEE_F32LE_g(), pcdata);
|
|
|
|
// H5Tfind returns function pointer (can be NULL if no conversion exists)
|
|
// For standard types, conversion should exist
|
|
assertFalse("Conversion function should be found", convFunc.equals(MemorySegment.NULL));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tfind_same_type()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Find conversion path from type to itself (should be no-op conversion)
|
|
MemorySegment pcdata = arena.allocate(8);
|
|
pcdata.set(java.lang.foreign.ValueLayout.ADDRESS, 0, MemorySegment.NULL);
|
|
|
|
MemorySegment convFunc =
|
|
hdf5_h.H5Tfind(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_STD_I32LE_g(), pcdata);
|
|
|
|
// Conversion from type to itself should exist (no-op)
|
|
assertFalse("No-op conversion should be found", convFunc.equals(MemorySegment.NULL));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_fields()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create a copy of a floating point type
|
|
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(floatType));
|
|
|
|
// Get field positions for floating point type
|
|
MemorySegment spos = allocateLongArray(arena, 1); // sign position
|
|
MemorySegment epos = allocateLongArray(arena, 1); // exponent position
|
|
MemorySegment esize = allocateLongArray(arena, 1); // exponent size
|
|
MemorySegment mpos = allocateLongArray(arena, 1); // mantissa position
|
|
MemorySegment msize = allocateLongArray(arena, 1); // mantissa size
|
|
|
|
int result = hdf5_h.H5Tget_fields(floatType, spos, epos, esize, mpos, msize);
|
|
assertTrue("H5Tget_fields failed", isSuccess(result));
|
|
|
|
// Verify we got valid values (all should be >= 0)
|
|
long sposVal = getLong(spos);
|
|
long eposVal = getLong(epos);
|
|
long esizeVal = getLong(esize);
|
|
long mposVal = getLong(mpos);
|
|
long msizeVal = getLong(msize);
|
|
|
|
assertTrue("Sign position should be valid", sposVal >= 0);
|
|
assertTrue("Exponent position should be valid", eposVal >= 0);
|
|
assertTrue("Exponent size should be > 0", esizeVal > 0);
|
|
assertTrue("Mantissa position should be valid", mposVal >= 0);
|
|
assertTrue("Mantissa size should be > 0", msizeVal > 0);
|
|
|
|
hdf5_h.H5Tclose(floatType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_ebias()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Get exponent bias for double
|
|
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(floatType));
|
|
|
|
long ebias = hdf5_h.H5Tget_ebias(floatType);
|
|
assertTrue("Exponent bias should be > 0", ebias > 0);
|
|
|
|
// For IEEE 754 double, exponent bias is typically 1023
|
|
// We won't test exact value as it's platform-dependent, but it should be reasonable
|
|
assertTrue("Exponent bias should be reasonable", ebias < 10000);
|
|
|
|
hdf5_h.H5Tclose(floatType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_norm()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Get normalization type for floating point
|
|
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(floatType));
|
|
|
|
int norm = hdf5_h.H5Tget_norm(floatType);
|
|
assertTrue("Normalization should be valid", norm >= 0);
|
|
|
|
// Typical normalization types: IMPLIED (0), MSBSET (1), NONE (2)
|
|
assertTrue("Normalization should be in valid range", norm <= 2);
|
|
|
|
hdf5_h.H5Tclose(floatType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_inpad()
|
|
{
|
|
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Get internal padding type for floating point
|
|
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(floatType));
|
|
|
|
int inpad = hdf5_h.H5Tget_inpad(floatType);
|
|
assertTrue("Internal padding should be valid", inpad >= 0);
|
|
|
|
// Padding types: ZERO (0), ONE (1), BACKGROUND (2)
|
|
assertTrue("Internal padding should be in valid range", inpad <= 2);
|
|
|
|
hdf5_h.H5Tclose(floatType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_fields_and_ebias()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create a custom floating point type
|
|
long floatType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F32LE_g());
|
|
assertTrue("H5Tcopy failed", isValidId(floatType));
|
|
|
|
// Set custom field layout
|
|
// For 32-bit float: sign(1) + exponent(8) + mantissa(23) = 32 bits
|
|
long spos = 31; // Sign at bit 31
|
|
long epos = 23; // Exponent starts at bit 23
|
|
long esize = 8; // Exponent is 8 bits
|
|
long mpos = 0; // Mantissa starts at bit 0
|
|
long msize = 23; // Mantissa is 23 bits
|
|
|
|
int result = hdf5_h.H5Tset_fields(floatType, spos, epos, esize, mpos, msize);
|
|
assertTrue("H5Tset_fields failed", isSuccess(result));
|
|
|
|
// Set exponent bias (for 8-bit exponent, typical bias is 127)
|
|
result = hdf5_h.H5Tset_ebias(floatType, 127);
|
|
assertTrue("H5Tset_ebias failed", isSuccess(result));
|
|
|
|
// Verify the settings
|
|
long retrievedEbias = hdf5_h.H5Tget_ebias(floatType);
|
|
assertEquals("Exponent bias should match", 127, retrievedEbias);
|
|
|
|
hdf5_h.H5Tclose(floatType);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Array Datatype Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tarray_create_1D()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create 1D array of integers [10]
|
|
long[] dimValues = {10};
|
|
MemorySegment dims = allocateLongArray(arena, 1);
|
|
copyToSegment(dims, dimValues);
|
|
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 1, dims);
|
|
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
|
|
|
|
// Verify it's an array type
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Should be array type", hdf5_h.H5T_ARRAY(), tclass);
|
|
|
|
// Verify dimensions
|
|
int ndims = hdf5_h.H5Tget_array_ndims(H5tid);
|
|
assertEquals("Should be 1D array", 1, ndims);
|
|
|
|
MemorySegment retrievedDims = allocateLongArray(arena, 1);
|
|
int result = hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
|
|
assertEquals("H5Tget_array_dims2 should succeed", 1, result);
|
|
assertEquals("Dimension should be 10", 10, retrievedDims.get(ValueLayout.JAVA_LONG, 0));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tarray_create_2D()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create 2D array of floats [3][4]
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 3, 4);
|
|
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F32LE_g(), 2, dims);
|
|
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
|
|
|
|
// Verify dimensions
|
|
int ndims = hdf5_h.H5Tget_array_ndims(H5tid);
|
|
assertEquals("Should be 2D array", 2, ndims);
|
|
|
|
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 2);
|
|
hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
|
|
assertEquals("First dimension should be 3", 3,
|
|
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
|
|
assertEquals("Second dimension should be 4", 4,
|
|
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tarray_create_3D()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create 3D array of doubles [2][3][4]
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 2, 3, 4);
|
|
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F64LE_g(), 3, dims);
|
|
assertTrue("H5Tarray_create2 failed", isValidId(H5tid));
|
|
|
|
// Verify dimensions
|
|
int ndims = hdf5_h.H5Tget_array_ndims(H5tid);
|
|
assertEquals("Should be 3D array", 3, ndims);
|
|
|
|
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 3);
|
|
hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
|
|
assertEquals("First dimension should be 2", 2,
|
|
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
|
|
assertEquals("Second dimension should be 3", 3,
|
|
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
|
|
assertEquals("Third dimension should be 4", 4,
|
|
retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 2));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_array_ndims()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Test with different dimensionalities
|
|
MemorySegment dims1 = arena.allocateFrom(ValueLayout.JAVA_LONG, 10L);
|
|
long tid1 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 1, dims1);
|
|
assertEquals("Should be 1D", 1, hdf5_h.H5Tget_array_ndims(tid1));
|
|
hdf5_h.H5Tclose(tid1);
|
|
|
|
MemorySegment dims2 = arena.allocateFrom(ValueLayout.JAVA_LONG, 5L, 6L);
|
|
long tid2 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims2);
|
|
assertEquals("Should be 2D", 2, hdf5_h.H5Tget_array_ndims(tid2));
|
|
hdf5_h.H5Tclose(tid2);
|
|
|
|
MemorySegment dims3 = arena.allocateFrom(ValueLayout.JAVA_LONG, 2L, 3L, 4L);
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 3, dims3);
|
|
assertEquals("Should be 3D", 3, hdf5_h.H5Tget_array_ndims(H5tid));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_array_dims2()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create array with specific dimensions
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 7, 8, 9);
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I64LE_g(), 3, dims);
|
|
|
|
// Retrieve dimensions
|
|
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 3);
|
|
int result = hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
|
|
assertEquals("H5Tget_array_dims2 should return rank", 3, result);
|
|
|
|
// Verify each dimension
|
|
assertEquals("Dim 0 should be 7", 7, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
|
|
assertEquals("Dim 1 should be 8", 8, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
|
|
assertEquals("Dim 2 should be 9", 9, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 2));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tarray_with_compound_base()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create compound type
|
|
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
hdf5_h.H5Tinsert(compoundType, stringToSegment(arena, "x"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, stringToSegment(arena, "y"), 4, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, stringToSegment(arena, "z"), 8, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Create array of compound types [5]
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 5L);
|
|
H5tid = hdf5_h.H5Tarray_create2(compoundType, 1, dims);
|
|
assertTrue("H5Tarray_create2 with compound base failed", isValidId(H5tid));
|
|
|
|
// Verify array properties
|
|
assertEquals("Should be array type", hdf5_h.H5T_ARRAY(), hdf5_h.H5Tget_class(H5tid));
|
|
assertEquals("Should be 1D", 1, hdf5_h.H5Tget_array_ndims(H5tid));
|
|
|
|
// Get super type (base type)
|
|
long superType = hdf5_h.H5Tget_super(H5tid);
|
|
assertTrue("Should have valid super type", isValidId(superType));
|
|
assertEquals("Super type should be compound", hdf5_h.H5T_COMPOUND(),
|
|
hdf5_h.H5Tget_class(superType));
|
|
|
|
hdf5_h.H5Tclose(superType);
|
|
hdf5_h.H5Tclose(compoundType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_super_array()
|
|
{
|
|
// Skip on Windows - FFM memory layout issue with array dimensions
|
|
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
|
|
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create array type
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 10L);
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I16LE_g(), 1, dims);
|
|
|
|
// Get the base type
|
|
long superType = hdf5_h.H5Tget_super(H5tid);
|
|
assertTrue("H5Tget_super failed", isValidId(superType));
|
|
|
|
// Verify base type is short
|
|
int equal = hdf5_h.H5Tequal(superType, hdf5_h.H5T_STD_I16LE_g());
|
|
assertTrue("Base type should be H5T_STD_I16LE", equal > 0);
|
|
|
|
hdf5_h.H5Tclose(superType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tarray_size()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create array [5][10] of ints (4 bytes each)
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 5, 10);
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
|
|
|
|
// Get size - should be 5 * 10 * 4 = 200 bytes
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertEquals("Array size should be 200 bytes", 200, size);
|
|
|
|
// For doubles (8 bytes each): 5 * 10 * 8 = 400 bytes
|
|
long tid2 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F64LE_g(), 2, dims);
|
|
long size2 = hdf5_h.H5Tget_size(tid2);
|
|
assertEquals("Array size should be 400 bytes", 400, size2);
|
|
hdf5_h.H5Tclose(tid2);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Enum Datatype Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tenum_create()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("H5Tenum_create failed", isValidId(H5tid));
|
|
|
|
// Verify it's an enum type
|
|
int tclass = hdf5_h.H5Tget_class(H5tid);
|
|
assertEquals("Should be enum type", hdf5_h.H5T_ENUM(), tclass);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_insert()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert enum values
|
|
MemorySegment val0 = allocateInt(arena);
|
|
setInt(val0, 0);
|
|
int result = hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "RED"), val0);
|
|
assertEquals("H5Tenum_insert RED failed", 0, result);
|
|
|
|
MemorySegment val1 = allocateInt(arena);
|
|
setInt(val1, 1);
|
|
result = hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "GREEN"), val1);
|
|
assertEquals("H5Tenum_insert GREEN failed", 0, result);
|
|
|
|
MemorySegment val2 = allocateInt(arena);
|
|
setInt(val2, 2);
|
|
result = hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "BLUE"), val2);
|
|
assertEquals("H5Tenum_insert BLUE failed", 0, result);
|
|
|
|
// Verify member count
|
|
int nmembers = hdf5_h.H5Tget_nmembers(H5tid);
|
|
assertEquals("Should have 3 enum members", 3, nmembers);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_insert_multiple()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert multiple values
|
|
String[] names = {"NORTH", "SOUTH", "EAST", "WEST"};
|
|
for (int i = 0; i < names.length; i++) {
|
|
MemorySegment val = allocateInt(arena);
|
|
setInt(val, i * 10);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, names[i]), val);
|
|
}
|
|
|
|
assertEquals("Should have 4 members", 4, hdf5_h.H5Tget_nmembers(H5tid));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_nameof()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert enum values
|
|
MemorySegment val0 = allocateInt(arena);
|
|
setInt(val0, 100);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "ALPHA"), val0);
|
|
|
|
MemorySegment val1 = allocateInt(arena);
|
|
setInt(val1, 200);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "BETA"), val1);
|
|
|
|
// Get name for value 100
|
|
MemorySegment nameBuffer = arena.allocate(20);
|
|
MemorySegment queryVal = allocateInt(arena);
|
|
setInt(queryVal, 100);
|
|
int result = hdf5_h.H5Tenum_nameof(H5tid, queryVal, nameBuffer, 20);
|
|
assertEquals("H5Tenum_nameof failed", 0, result);
|
|
|
|
String name = nameBuffer.getString(0);
|
|
assertEquals("Name should be ALPHA", "ALPHA", name);
|
|
|
|
// Get name for value 200
|
|
setInt(queryVal, 200);
|
|
result = hdf5_h.H5Tenum_nameof(H5tid, queryVal, nameBuffer, 20);
|
|
assertEquals("H5Tenum_nameof failed", 0, result);
|
|
|
|
name = nameBuffer.getString(0);
|
|
assertEquals("Name should be BETA", "BETA", name);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_valueof()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert enum values
|
|
MemorySegment val0 = allocateInt(arena);
|
|
setInt(val0, 42);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "MAGIC"), val0);
|
|
|
|
MemorySegment val1 = allocateInt(arena);
|
|
setInt(val1, 99);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "SPECIAL"), val1);
|
|
|
|
// Get value for name "MAGIC"
|
|
MemorySegment retrievedVal = allocateInt(arena);
|
|
int result = hdf5_h.H5Tenum_valueof(H5tid, stringToSegment(arena, "MAGIC"), retrievedVal);
|
|
assertEquals("H5Tenum_valueof failed", 0, result);
|
|
assertEquals("Value should be 42", 42, getInt(retrievedVal));
|
|
|
|
// Get value for name "SPECIAL"
|
|
result = hdf5_h.H5Tenum_valueof(H5tid, stringToSegment(arena, "SPECIAL"), retrievedVal);
|
|
assertEquals("H5Tenum_valueof failed", 0, result);
|
|
assertEquals("Value should be 99", 99, getInt(retrievedVal));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_get_member_value()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert values
|
|
MemorySegment val0 = allocateInt(arena);
|
|
setInt(val0, 10);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "FIRST"), val0);
|
|
|
|
MemorySegment val1 = allocateInt(arena);
|
|
setInt(val1, 20);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "SECOND"), val1);
|
|
|
|
MemorySegment val2 = allocateInt(arena);
|
|
setInt(val2, 30);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "THIRD"), val2);
|
|
|
|
// Get member values by index
|
|
MemorySegment retrievedVal = allocateInt(arena);
|
|
|
|
hdf5_h.H5Tget_member_value(H5tid, 0, retrievedVal);
|
|
assertEquals("First member value should be 10", 10, getInt(retrievedVal));
|
|
|
|
hdf5_h.H5Tget_member_value(H5tid, 1, retrievedVal);
|
|
assertEquals("Second member value should be 20", 20, getInt(retrievedVal));
|
|
|
|
hdf5_h.H5Tget_member_value(H5tid, 2, retrievedVal);
|
|
assertEquals("Third member value should be 30", 30, getInt(retrievedVal));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_negative_values()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert negative values (for error codes, etc.)
|
|
MemorySegment valNeg1 = allocateInt(arena);
|
|
setInt(valNeg1, -1);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "ERROR"), valNeg1);
|
|
|
|
MemorySegment val0 = allocateInt(arena);
|
|
setInt(val0, 0);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "SUCCESS"), val0);
|
|
|
|
MemorySegment val1 = allocateInt(arena);
|
|
setInt(val1, 1);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "WARNING"), val1);
|
|
|
|
// Retrieve negative value
|
|
MemorySegment retrievedVal = allocateInt(arena);
|
|
hdf5_h.H5Tenum_valueof(H5tid, stringToSegment(arena, "ERROR"), retrievedVal);
|
|
assertEquals("Value should be -1", -1, getInt(retrievedVal));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_nmembers_enum()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Initially should have 0 members
|
|
assertEquals("Empty enum should have 0 members", 0, hdf5_h.H5Tget_nmembers(H5tid));
|
|
|
|
// Add members one by one and check count
|
|
for (int i = 0; i < 5; i++) {
|
|
MemorySegment val = allocateInt(arena);
|
|
setInt(val, i);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, "MEMBER_" + i), val);
|
|
assertEquals("Should have " + (i + 1) + " members", i + 1, hdf5_h.H5Tget_nmembers(H5tid));
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T String Datatype Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tcreate_string_variable()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy for string failed", isValidId(H5tid));
|
|
|
|
// Set to variable length
|
|
int result = hdf5_h.H5Tset_size(H5tid, hdf5_h.H5T_VARIABLE());
|
|
assertTrue("H5Tset_size to variable should succeed", isSuccess(result));
|
|
|
|
// Verify it's variable length (H5T_VARIABLE returns size_t max, which appears as -1 when signed)
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
// Variable length strings report their size as the size of hvl_t struct (16 bytes on 64-bit)
|
|
// Use H5Tis_variable_str to check if it's truly variable length
|
|
int isVar = hdf5_h.H5Tis_variable_str(H5tid);
|
|
assertTrue("Should be variable length string", isVar > 0);
|
|
|
|
// Verify it's a string type
|
|
assertEquals("Should be string class", hdf5_h.H5T_STRING(), hdf5_h.H5Tget_class(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcreate_string_fixed()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
|
|
// Set to fixed length of 50 characters
|
|
int result = hdf5_h.H5Tset_size(H5tid, 50);
|
|
assertEquals("H5Tset_size failed", 0, result);
|
|
|
|
// Verify size
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertEquals("String length should be 50", 50, size);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_strpad()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
hdf5_h.H5Tset_size(H5tid, 20);
|
|
|
|
// Test NULL padding
|
|
int result = hdf5_h.H5Tset_strpad(H5tid, hdf5_h.H5T_STR_NULLPAD());
|
|
assertEquals("H5Tset_strpad NULLPAD failed", 0, result);
|
|
assertEquals("Should be NULLPAD", hdf5_h.H5T_STR_NULLPAD(), hdf5_h.H5Tget_strpad(H5tid));
|
|
|
|
// Test NULL termination
|
|
result = hdf5_h.H5Tset_strpad(H5tid, hdf5_h.H5T_STR_NULLTERM());
|
|
assertEquals("H5Tset_strpad NULLTERM failed", 0, result);
|
|
assertEquals("Should be NULLTERM", hdf5_h.H5T_STR_NULLTERM(), hdf5_h.H5Tget_strpad(H5tid));
|
|
|
|
// Test SPACE padding
|
|
result = hdf5_h.H5Tset_strpad(H5tid, hdf5_h.H5T_STR_SPACEPAD());
|
|
assertEquals("H5Tset_strpad SPACEPAD failed", 0, result);
|
|
assertEquals("Should be SPACEPAD", hdf5_h.H5T_STR_SPACEPAD(), hdf5_h.H5Tget_strpad(H5tid));
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T VLen Advanced Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tvlen_create_nested()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Create vlen of vlen (nested variable length)
|
|
long innerVlen = hdf5_h.H5Tvlen_create(hdf5_h.H5T_STD_I32LE_g());
|
|
assertTrue("Inner vlen creation failed", isValidId(innerVlen));
|
|
|
|
H5tid = hdf5_h.H5Tvlen_create(innerVlen);
|
|
assertTrue("Outer vlen creation failed", isValidId(H5tid));
|
|
|
|
// Verify it's a vlen type
|
|
assertEquals("Should be vlen class", hdf5_h.H5T_VLEN(), hdf5_h.H5Tget_class(H5tid));
|
|
|
|
// Get super type
|
|
long superType = hdf5_h.H5Tget_super(H5tid);
|
|
assertTrue("Super type should be valid", isValidId(superType));
|
|
assertEquals("Super should be vlen", hdf5_h.H5T_VLEN(), hdf5_h.H5Tget_class(superType));
|
|
|
|
hdf5_h.H5Tclose(superType);
|
|
hdf5_h.H5Tclose(innerVlen);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tvlen_with_compound()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create compound type
|
|
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 16);
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("id"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("value"), 8, hdf5_h.H5T_IEEE_F64LE_g());
|
|
|
|
// Create vlen of compound
|
|
H5tid = hdf5_h.H5Tvlen_create(compoundType);
|
|
assertTrue("Vlen of compound creation failed", isValidId(H5tid));
|
|
|
|
// Verify base type is compound
|
|
long superType = hdf5_h.H5Tget_super(H5tid);
|
|
assertEquals("Super type should be compound", hdf5_h.H5T_COMPOUND(),
|
|
hdf5_h.H5Tget_class(superType));
|
|
|
|
hdf5_h.H5Tclose(superType);
|
|
hdf5_h.H5Tclose(compoundType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tvlen_is_variable()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tvlen_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Vlen types report their size as sizeof(hvl_t) which is 16 bytes on 64-bit
|
|
// The proper way to check is via the type class
|
|
assertEquals("Should be vlen class", hdf5_h.H5T_VLEN(), hdf5_h.H5Tget_class(H5tid));
|
|
|
|
// Verify the size is the hvl_t struct size (typically 16 bytes)
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertTrue("Vlen size should be positive (hvl_t struct)", size > 0);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Opaque Advanced Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Topaque_create()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Create opaque type of 128 bytes
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), 128);
|
|
assertTrue("Opaque creation failed", isValidId(H5tid));
|
|
|
|
assertEquals("Should be opaque class", hdf5_h.H5T_OPAQUE(), hdf5_h.H5Tget_class(H5tid));
|
|
assertEquals("Size should be 128", 128, hdf5_h.H5Tget_size(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Topaque_set_get_tag()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), 64);
|
|
|
|
// Set tag
|
|
String tag = "binary_blob_v1.0";
|
|
int result = hdf5_h.H5Tset_tag(H5tid, arena.allocateFrom(tag));
|
|
assertEquals("H5Tset_tag failed", 0, result);
|
|
|
|
// Get tag
|
|
MemorySegment tagPtr = hdf5_h.H5Tget_tag(H5tid);
|
|
assertNotNull("Tag pointer should not be null", tagPtr);
|
|
|
|
String retrievedTag = tagPtr.getString(0);
|
|
assertEquals("Tag should match", tag, retrievedTag);
|
|
|
|
hdf5_h.H5free_memory(tagPtr);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Topaque_different_sizes()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Test various opaque sizes
|
|
int[] sizes = {1, 16, 256, 1024};
|
|
|
|
for (int size : sizes) {
|
|
long tid = hdf5_h.H5Tcreate(hdf5_h.H5T_OPAQUE(), size);
|
|
assertTrue("Opaque creation failed for size " + size, isValidId(tid));
|
|
assertEquals("Size should match", size, hdf5_h.H5Tget_size(tid));
|
|
hdf5_h.H5Tclose(tid);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Bitfield Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tbitfield_create()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Bitfield types cannot be created with H5Tcreate, must copy from predefined type
|
|
// Copy from a standard bitfield type and resize
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B32LE_g());
|
|
assertTrue("Bitfield copy failed", isValidId(H5tid));
|
|
|
|
// Verify it's a bitfield type
|
|
assertEquals("Should be bitfield class", hdf5_h.H5T_BITFIELD(), hdf5_h.H5Tget_class(H5tid));
|
|
|
|
// Resize to 4 bytes if needed
|
|
int result = hdf5_h.H5Tset_size(H5tid, 4);
|
|
assertTrue("H5Tset_size should succeed", isSuccess(result));
|
|
assertEquals("Size should be 4", 4, hdf5_h.H5Tget_size(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tbitfield_predefined()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Test predefined bitfield types
|
|
long tid1 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B8LE_g());
|
|
assertTrue("H5T_STD_B8LE copy failed", isValidId(tid1));
|
|
assertEquals("Should be 1 byte", 1, hdf5_h.H5Tget_size(tid1));
|
|
hdf5_h.H5Tclose(tid1);
|
|
|
|
long tid2 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B16LE_g());
|
|
assertTrue("H5T_STD_B16LE copy failed", isValidId(tid2));
|
|
assertEquals("Should be 2 bytes", 2, hdf5_h.H5Tget_size(tid2));
|
|
hdf5_h.H5Tclose(tid2);
|
|
|
|
long tid3 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B32LE_g());
|
|
assertTrue("H5T_STD_B32LE copy failed", isValidId(tid3));
|
|
assertEquals("Should be 4 bytes", 4, hdf5_h.H5Tget_size(tid3));
|
|
hdf5_h.H5Tclose(tid3);
|
|
|
|
long tid4 = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_B64LE_g());
|
|
assertTrue("H5T_STD_B64LE copy failed", isValidId(tid4));
|
|
assertEquals("Should be 8 bytes", 8, hdf5_h.H5Tget_size(tid4));
|
|
hdf5_h.H5Tclose(tid4);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Complex Number Tests (HDF5 2.0 feature)
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tcomplex_float()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Create complex float type
|
|
H5tid = hdf5_h.H5Tcomplex_create(hdf5_h.H5T_IEEE_F32LE_g());
|
|
assertTrue("Complex float creation failed", isValidId(H5tid));
|
|
|
|
// Complex float should be 8 bytes (2 * 4-byte floats)
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertEquals("Complex float should be 8 bytes", 8, size);
|
|
|
|
// Complex types have their own class (H5T_COMPLEX = 11)
|
|
assertEquals("Should be complex class", hdf5_h.H5T_COMPLEX(), hdf5_h.H5Tget_class(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcomplex_double()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Create complex double type
|
|
H5tid = hdf5_h.H5Tcomplex_create(hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("Complex double creation failed", isValidId(H5tid));
|
|
|
|
// Complex double should be 16 bytes (2 * 8-byte doubles)
|
|
long size = hdf5_h.H5Tget_size(H5tid);
|
|
assertEquals("Complex double should be 16 bytes", 16, size);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcomplex_get_parts()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcomplex_create(hdf5_h.H5T_IEEE_F64LE_g());
|
|
|
|
// Get real and imaginary part types
|
|
long realType = hdf5_h.H5Tget_super(H5tid);
|
|
assertTrue("Real type should be valid", isValidId(realType));
|
|
|
|
// Verify it's a double
|
|
int equal = hdf5_h.H5Tequal(realType, hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("Real part should be double", equal > 0);
|
|
|
|
hdf5_h.H5Tclose(realType);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Type Conversion Advanced Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tconvert_with_buffer()
|
|
{
|
|
// Skip on Windows - FFM memory layout issue with conversion buffers
|
|
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
|
|
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Convert int array to float array
|
|
int nelem = 5;
|
|
MemorySegment intData = arena.allocateFrom(hdf5_h.C_INT, 10, 20, 30, 40, 50);
|
|
|
|
long srcType = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
long dstType = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F32LE_g());
|
|
|
|
// Convert in place
|
|
int result =
|
|
hdf5_h.H5Tconvert(srcType, dstType, nelem, intData, MemorySegment.NULL, hdf5_h.H5P_DEFAULT());
|
|
assertEquals("H5Tconvert failed", 0, result);
|
|
|
|
// Data should now be floats (we can't easily verify values due to overlay)
|
|
|
|
hdf5_h.H5Tclose(srcType);
|
|
hdf5_h.H5Tclose(dstType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tconvert_compound_subset()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create source compound: {int x, int y, int z}
|
|
long srcType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
hdf5_h.H5Tinsert(srcType, arena.allocateFrom("x"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(srcType, arena.allocateFrom("y"), 4, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(srcType, arena.allocateFrom("z"), 8, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Create dest compound: {int x, int z} - subset
|
|
long dstType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 8);
|
|
hdf5_h.H5Tinsert(dstType, arena.allocateFrom("x"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(dstType, arena.allocateFrom("z"), 4, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// This tests subset conversion capability
|
|
assertTrue("Source compound type valid", isValidId(srcType));
|
|
assertTrue("Dest compound type valid", isValidId(dstType));
|
|
|
|
hdf5_h.H5Tclose(srcType);
|
|
hdf5_h.H5Tclose(dstType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcompiler_conv()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Check if compiler conversion path exists between int and float
|
|
int result = hdf5_h.H5Tcompiler_conv(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_IEEE_F32LE_g());
|
|
// Result > 0 means compiler conversion exists, 0 means library conversion only
|
|
assertTrue("Conversion check should succeed", result >= 0);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Type Commit Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tcommit2()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create a test file
|
|
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_commit.h5"), hdf5_h.H5F_ACC_TRUNC(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("File creation failed", isValidId(file_id));
|
|
|
|
// Create compound type
|
|
H5tid = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
hdf5_h.H5Tinsert(H5tid, arena.allocateFrom("a"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(H5tid, arena.allocateFrom("b"), 4, hdf5_h.H5T_IEEE_F32LE_g());
|
|
hdf5_h.H5Tinsert(H5tid, arena.allocateFrom("c"), 8, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Commit the type
|
|
int result = hdf5_h.H5Tcommit2(file_id, arena.allocateFrom("mytype"), H5tid, hdf5_h.H5P_DEFAULT(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertEquals("H5Tcommit2 failed", 0, result);
|
|
|
|
// Verify it's committed
|
|
int committed = hdf5_h.H5Tcommitted(H5tid);
|
|
assertTrue("Type should be committed", committed > 0);
|
|
|
|
hdf5_h.H5Fclose(file_id);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tcommit_anon()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_commit_anon.h5"), hdf5_h.H5F_ACC_TRUNC(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
|
|
// Create enum type
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
MemorySegment val = arena.allocate(hdf5_h.C_INT, 0);
|
|
hdf5_h.H5Tenum_insert(H5tid, arena.allocateFrom("RED"), val);
|
|
|
|
// Commit anonymously (no name)
|
|
int result = hdf5_h.H5Tcommit_anon(file_id, H5tid, hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertEquals("H5Tcommit_anon failed", 0, result);
|
|
|
|
// Verify it's committed
|
|
assertTrue("Type should be committed", hdf5_h.H5Tcommitted(H5tid) > 0);
|
|
|
|
hdf5_h.H5Fclose(file_id);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Topen2()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_open.h5"), hdf5_h.H5F_ACC_TRUNC(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
|
|
// Create and commit a type
|
|
long tid1 = hdf5_h.H5Tcopy(hdf5_h.H5T_IEEE_F64LE_g());
|
|
hdf5_h.H5Tcommit2(file_id, arena.allocateFrom("double_type"), tid1, hdf5_h.H5P_DEFAULT(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
hdf5_h.H5Tclose(tid1);
|
|
|
|
// Open the committed type
|
|
H5tid = hdf5_h.H5Topen2(file_id, arena.allocateFrom("double_type"), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Topen2 failed", isValidId(H5tid));
|
|
|
|
// Verify it's committed
|
|
assertTrue("Opened type should be committed", hdf5_h.H5Tcommitted(H5tid) > 0);
|
|
|
|
// Verify it's equal to double
|
|
int equal = hdf5_h.H5Tequal(H5tid, hdf5_h.H5T_IEEE_F64LE_g());
|
|
assertTrue("Should be equal to double", equal > 0);
|
|
|
|
hdf5_h.H5Fclose(file_id);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_create_plist()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long file_id = hdf5_h.H5Fcreate(arena.allocateFrom("test_get_cplist.h5"), hdf5_h.H5F_ACC_TRUNC(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
|
|
// Create type with custom creation properties
|
|
long tcpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_DATATYPE_CREATE_ID_g());
|
|
assertTrue("TCPL creation failed", isValidId(tcpl));
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tcommit2(file_id, arena.allocateFrom("int_type"), H5tid, hdf5_h.H5P_DEFAULT(), tcpl,
|
|
hdf5_h.H5P_DEFAULT());
|
|
|
|
// Get creation property list
|
|
long retrieved_tcpl = hdf5_h.H5Tget_create_plist(H5tid);
|
|
assertTrue("H5Tget_create_plist failed", isValidId(retrieved_tcpl));
|
|
|
|
hdf5_h.H5Pclose(retrieved_tcpl);
|
|
hdf5_h.H5Pclose(tcpl);
|
|
hdf5_h.H5Fclose(file_id);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Type Detection and Query Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tdetect_class_in_compound()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create compound with int and float
|
|
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 12);
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("i"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("f"), 4, hdf5_h.H5T_IEEE_F32LE_g());
|
|
|
|
// Detect integer class
|
|
int hasInt = hdf5_h.H5Tdetect_class(compoundType, hdf5_h.H5T_INTEGER());
|
|
assertTrue("Should detect integer class", hasInt > 0);
|
|
|
|
// Detect float class
|
|
int hasFloat = hdf5_h.H5Tdetect_class(compoundType, hdf5_h.H5T_FLOAT());
|
|
assertTrue("Should detect float class", hasFloat > 0);
|
|
|
|
// Should not detect string class
|
|
int hasString = hdf5_h.H5Tdetect_class(compoundType, hdf5_h.H5T_STRING());
|
|
assertFalse("Should not detect string class", hasString > 0);
|
|
|
|
hdf5_h.H5Tclose(compoundType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tdetect_class_integer()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
int result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_INTEGER());
|
|
assertTrue("H5T_STD_I32LE should be integer class", result > 0);
|
|
|
|
result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_FLOAT());
|
|
assertFalse("H5T_STD_I32LE should not be float class", result > 0);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tdetect_class_float()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
int result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_IEEE_F64LE_g(), hdf5_h.H5T_FLOAT());
|
|
assertTrue("Native double should be float class", result > 0);
|
|
|
|
result = hdf5_h.H5Tdetect_class(hdf5_h.H5T_IEEE_F64LE_g(), hdf5_h.H5T_INTEGER());
|
|
assertFalse("Native double should not be integer class", result > 0);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Type Modification Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tpack_compound()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create compound with padding
|
|
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 16);
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("a"), 0, hdf5_h.H5T_STD_I8LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("b"), 4, hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
long sizeBefore = hdf5_h.H5Tget_size(compoundType);
|
|
|
|
// Pack to remove padding
|
|
int result = hdf5_h.H5Tpack(compoundType);
|
|
assertEquals("H5Tpack failed", 0, result);
|
|
|
|
long sizeAfter = hdf5_h.H5Tget_size(compoundType);
|
|
assertTrue("Size should be smaller after packing", sizeAfter <= sizeBefore);
|
|
// Should be 1 (char) + 4 (int) = 5 bytes
|
|
assertEquals("Packed size should be 5", 5, sizeAfter);
|
|
|
|
hdf5_h.H5Tclose(compoundType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tlock()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Lock the type
|
|
int result = hdf5_h.H5Tlock(H5tid);
|
|
assertEquals("H5Tlock failed", 0, result);
|
|
|
|
// Try to modify locked type - should fail
|
|
result = hdf5_h.H5Tset_size(H5tid, 8);
|
|
assertTrue("Modifying locked type should fail", result < 0);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T String Character Set Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tset_get_cset_ascii()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
|
|
// Set to ASCII
|
|
int result = hdf5_h.H5Tset_cset(H5tid, hdf5_h.H5T_CSET_ASCII());
|
|
assertEquals("H5Tset_cset ASCII failed", 0, result);
|
|
|
|
int cset = hdf5_h.H5Tget_cset(H5tid);
|
|
assertEquals("Character set should be ASCII", hdf5_h.H5T_CSET_ASCII(), cset);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_get_cset_utf8()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
|
|
// Set to UTF-8
|
|
int result = hdf5_h.H5Tset_cset(H5tid, hdf5_h.H5T_CSET_UTF8());
|
|
assertEquals("H5Tset_cset UTF8 failed", 0, result);
|
|
|
|
int cset = hdf5_h.H5Tget_cset(H5tid);
|
|
assertEquals("Character set should be UTF8", hdf5_h.H5T_CSET_UTF8(), cset);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Reference Type Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5T_STD_REF()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
long tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_REF_g());
|
|
assertTrue("H5T_STD_REF copy failed", isValidId(tid));
|
|
|
|
// Verify it's a reference type
|
|
assertEquals("Should be reference class", hdf5_h.H5T_REFERENCE(), hdf5_h.H5Tget_class(tid));
|
|
|
|
hdf5_h.H5Tclose(tid);
|
|
}
|
|
|
|
@Test
|
|
public void testH5T_reference_types()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Test object reference
|
|
long objRef = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_REF_OBJ_g());
|
|
assertTrue("Object reference copy failed", isValidId(objRef));
|
|
assertEquals("Should be reference", hdf5_h.H5T_REFERENCE(), hdf5_h.H5Tget_class(objRef));
|
|
hdf5_h.H5Tclose(objRef);
|
|
|
|
// Test dataset region reference
|
|
long regRef = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_REF_DSETREG_g());
|
|
assertTrue("Region reference copy failed", isValidId(regRef));
|
|
assertEquals("Should be reference", hdf5_h.H5T_REFERENCE(), hdf5_h.H5Tget_class(regRef));
|
|
hdf5_h.H5Tclose(regRef);
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Array Type Advanced Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tarray_equal()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 5, 10);
|
|
|
|
long tid1 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
|
|
long tid2 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
|
|
|
|
// Should be equal
|
|
int equal = hdf5_h.H5Tequal(tid1, tid2);
|
|
assertTrue("Identical arrays should be equal", equal > 0);
|
|
|
|
hdf5_h.H5Tclose(tid1);
|
|
hdf5_h.H5Tclose(tid2);
|
|
|
|
// Different dimensions should not be equal
|
|
MemorySegment dims2 = arena.allocateFrom(ValueLayout.JAVA_LONG, 5, 11);
|
|
long tid3 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims);
|
|
long tid4 = hdf5_h.H5Tarray_create2(hdf5_h.H5T_STD_I32LE_g(), 2, dims2);
|
|
|
|
equal = hdf5_h.H5Tequal(tid3, tid4);
|
|
assertFalse("Different dimension arrays should not be equal", equal > 0);
|
|
|
|
hdf5_h.H5Tclose(tid3);
|
|
hdf5_h.H5Tclose(tid4);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tarray_multidimensional_access()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create 4D array [2][3][4][5]
|
|
MemorySegment dims = arena.allocateFrom(ValueLayout.JAVA_LONG, 2, 3, 4, 5);
|
|
H5tid = hdf5_h.H5Tarray_create2(hdf5_h.H5T_IEEE_F64LE_g(), 4, dims);
|
|
|
|
// Verify rank
|
|
assertEquals("Should be 4D", 4, hdf5_h.H5Tget_array_ndims(H5tid));
|
|
|
|
// Get all dimensions
|
|
MemorySegment retrievedDims = arena.allocate(ValueLayout.JAVA_LONG, 4);
|
|
hdf5_h.H5Tget_array_dims2(H5tid, retrievedDims);
|
|
|
|
assertEquals("Dim[0]", 2, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 0));
|
|
assertEquals("Dim[1]", 3, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 1));
|
|
assertEquals("Dim[2]", 4, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 2));
|
|
assertEquals("Dim[3]", 5, retrievedDims.getAtIndex(ValueLayout.JAVA_LONG, 3));
|
|
|
|
// Size should be 2*3*4*5*8 = 960 bytes (8 bytes per double)
|
|
assertEquals("Size should be 960", 960, hdf5_h.H5Tget_size(H5tid));
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Enum Type Advanced Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tenum_with_different_base_types()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Enum based on byte
|
|
long enumByte = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I8LE_g());
|
|
MemorySegment val = arena.allocate(hdf5_h.C_CHAR, (byte)1);
|
|
hdf5_h.H5Tenum_insert(enumByte, arena.allocateFrom("ONE"), val);
|
|
assertEquals("Size should be 1", 1, hdf5_h.H5Tget_size(enumByte));
|
|
hdf5_h.H5Tclose(enumByte);
|
|
|
|
// Enum based on short
|
|
long enumShort = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I16LE_g());
|
|
MemorySegment val2 = arena.allocate(hdf5_h.C_SHORT, (short)1);
|
|
hdf5_h.H5Tenum_insert(enumShort, arena.allocateFrom("ONE"), val2);
|
|
assertEquals("Size should be 2", 2, hdf5_h.H5Tget_size(enumShort));
|
|
hdf5_h.H5Tclose(enumShort);
|
|
|
|
// Enum based on long
|
|
long enumLong = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I64LE_g());
|
|
MemorySegment val3 = arena.allocate(ValueLayout.JAVA_LONG, 1L);
|
|
hdf5_h.H5Tenum_insert(enumLong, arena.allocateFrom("ONE"), val3);
|
|
assertEquals("Size should be 8", 8, hdf5_h.H5Tget_size(enumLong));
|
|
hdf5_h.H5Tclose(enumLong);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tenum_get_member_index()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
H5tid = hdf5_h.H5Tenum_create(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Insert several members
|
|
String[] names = {"ALPHA", "BETA", "GAMMA", "DELTA"};
|
|
for (int i = 0; i < names.length; i++) {
|
|
MemorySegment val = allocateInt(arena);
|
|
setInt(val, i * 100);
|
|
hdf5_h.H5Tenum_insert(H5tid, stringToSegment(arena, names[i]), val);
|
|
}
|
|
|
|
// Get member index
|
|
int idx = hdf5_h.H5Tget_member_index(H5tid, stringToSegment(arena, "BETA"));
|
|
assertEquals("BETA should be at index 1", 1, idx);
|
|
|
|
idx = hdf5_h.H5Tget_member_index(H5tid, stringToSegment(arena, "DELTA"));
|
|
assertEquals("DELTA should be at index 3", 3, idx);
|
|
|
|
// Non-existent member
|
|
idx = hdf5_h.H5Tget_member_index(H5tid, stringToSegment(arena, "EPSILON"));
|
|
assertTrue("Non-existent member should return negative", idx < 0);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Compound Type Advanced Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tget_member_index_compound()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 16);
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("field1"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("field2"), 4, hdf5_h.H5T_IEEE_F32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("field3"), 8, hdf5_h.H5T_IEEE_F64LE_g());
|
|
|
|
int idx = hdf5_h.H5Tget_member_index(compoundType, arena.allocateFrom("field2"));
|
|
assertEquals("field2 should be at index 1", 1, idx);
|
|
|
|
idx = hdf5_h.H5Tget_member_index(compoundType, arena.allocateFrom("field3"));
|
|
assertEquals("field3 should be at index 2", 2, idx);
|
|
|
|
hdf5_h.H5Tclose(compoundType);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_member_class()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long compoundType = hdf5_h.H5Tcreate(hdf5_h.H5T_COMPOUND(), 13);
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("i"), 0, hdf5_h.H5T_STD_I32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("f"), 4, hdf5_h.H5T_IEEE_F32LE_g());
|
|
hdf5_h.H5Tinsert(compoundType, arena.allocateFrom("c"), 8, hdf5_h.H5T_STD_I8LE_g());
|
|
|
|
int class0 = hdf5_h.H5Tget_member_class(compoundType, 0);
|
|
assertEquals("Member 0 should be integer", hdf5_h.H5T_INTEGER(), class0);
|
|
|
|
int class1 = hdf5_h.H5Tget_member_class(compoundType, 1);
|
|
assertEquals("Member 1 should be float", hdf5_h.H5T_FLOAT(), class1);
|
|
|
|
int class2 = hdf5_h.H5Tget_member_class(compoundType, 2);
|
|
assertEquals("Member 2 should be integer (char)", hdf5_h.H5T_INTEGER(), class2);
|
|
|
|
hdf5_h.H5Tclose(compoundType);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// H5T Numeric Type Property Tests
|
|
// ============================================================================
|
|
|
|
@Test
|
|
public void testH5Tset_size_grow()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I16LE_g());
|
|
assertEquals("Short should be 2 bytes", 2, hdf5_h.H5Tget_size(H5tid));
|
|
|
|
// Grow to 8 bytes
|
|
int result = hdf5_h.H5Tset_size(H5tid, 8);
|
|
assertEquals("H5Tset_size grow failed", 0, result);
|
|
assertEquals("Size should be 8", 8, hdf5_h.H5Tget_size(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_size_shrink()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I64LE_g());
|
|
assertEquals("Long should be 8 bytes", 8, hdf5_h.H5Tget_size(H5tid));
|
|
|
|
// Shrink to 4 bytes
|
|
int result = hdf5_h.H5Tset_size(H5tid, 4);
|
|
assertEquals("H5Tset_size shrink failed", 0, result);
|
|
assertEquals("Size should be 4", 4, hdf5_h.H5Tget_size(H5tid));
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tset_precision_less_than_size()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
H5tid = hdf5_h.H5Tcopy(hdf5_h.H5T_STD_I32LE_g());
|
|
|
|
// Set precision to 24 bits (less than 32-bit int)
|
|
int result = hdf5_h.H5Tset_precision(H5tid, 24);
|
|
assertEquals("H5Tset_precision failed", 0, result);
|
|
|
|
long precision = hdf5_h.H5Tget_precision(H5tid);
|
|
assertEquals("Precision should be 24", 24, precision);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_native_type_integer()
|
|
{
|
|
// Skip on Windows - FFM memory layout issue with native type mapping
|
|
Assume.assumeFalse("Skipping on Windows - FFM limitation", IS_WINDOWS);
|
|
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Get native type for a standard type
|
|
long nativeType = hdf5_h.H5Tget_native_type(hdf5_h.H5T_STD_I32LE_g(), hdf5_h.H5T_DIR_ASCEND());
|
|
assertTrue("Native type should be valid", isValidId(nativeType));
|
|
assertEquals("Should be integer class", hdf5_h.H5T_INTEGER(), hdf5_h.H5Tget_class(nativeType));
|
|
hdf5_h.H5Tclose(nativeType);
|
|
}
|
|
|
|
@Test
|
|
public void testH5Tget_native_type_float()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
long nativeType = hdf5_h.H5Tget_native_type(hdf5_h.H5T_IEEE_F64LE_g(), hdf5_h.H5T_DIR_DESCEND());
|
|
assertTrue("Native type should be valid", isValidId(nativeType));
|
|
assertEquals("Should be float class", hdf5_h.H5T_FLOAT(), hdf5_h.H5Tget_class(nativeType));
|
|
hdf5_h.H5Tclose(nativeType);
|
|
}
|
|
}
|