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.
1045 lines
42 KiB
Java
1045 lines
42 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 COPYING 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.H5A_info_t;
|
|
import org.hdfgroup.javahdf5.H5A_operator2_t;
|
|
import org.hdfgroup.javahdf5.hdf5_h;
|
|
import org.junit.After;
|
|
import org.junit.Before;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.rules.TestName;
|
|
|
|
/**
|
|
* TestH5Affm - FFM-based tests for HDF5 Attribute operations.
|
|
* Tests the H5A* API using Foreign Function & Memory (FFM) bindings.
|
|
*/
|
|
public class TestH5Affm {
|
|
private static final String H5_FILE = "testA.h5";
|
|
private static final int DIM_X = 4;
|
|
private static final int DIM_Y = 6;
|
|
private static final int RANK = 2;
|
|
|
|
@Rule
|
|
public TestName testname = new TestName();
|
|
|
|
long H5fid = hdf5_h.H5I_INVALID_HID();
|
|
long H5did = hdf5_h.H5I_INVALID_HID();
|
|
long H5sid = hdf5_h.H5I_INVALID_HID();
|
|
long H5aid = hdf5_h.H5I_INVALID_HID();
|
|
|
|
@Before
|
|
public void createH5file() throws Exception
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create file
|
|
MemorySegment fileName = stringToSegment(arena, H5_FILE);
|
|
H5fid = hdf5_h.H5Fcreate(fileName, hdf5_h.H5F_ACC_TRUNC(), hdf5_h.H5P_DEFAULT(),
|
|
hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Fcreate failed", isValidId(H5fid));
|
|
|
|
// Create dataspace
|
|
long[] dims = {DIM_X, DIM_Y};
|
|
MemorySegment dimsSegment = allocateLongArray(arena, RANK);
|
|
copyToSegment(dimsSegment, dims);
|
|
H5sid = hdf5_h.H5Screate_simple(RANK, dimsSegment, MemorySegment.NULL);
|
|
assertTrue("H5Screate_simple failed", isValidId(H5sid));
|
|
|
|
// Create dataset for attaching attributes
|
|
MemorySegment dsetName = stringToSegment(arena, "dset");
|
|
H5did = hdf5_h.H5Dcreate2(H5fid, dsetName, hdf5_h.H5T_NATIVE_INT_g(), H5sid, hdf5_h.H5P_DEFAULT(),
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Dcreate2 failed", isValidId(H5did));
|
|
}
|
|
}
|
|
|
|
@After
|
|
public void deleteH5file() throws Exception
|
|
{
|
|
closeQuietly(H5aid, hdf5_h::H5Aclose);
|
|
closeQuietly(H5did, hdf5_h::H5Dclose);
|
|
closeQuietly(H5sid, hdf5_h::H5Sclose);
|
|
closeQuietly(H5fid, hdf5_h::H5Fclose);
|
|
|
|
H5aid = hdf5_h.H5I_INVALID_HID();
|
|
H5did = hdf5_h.H5I_INVALID_HID();
|
|
H5sid = hdf5_h.H5I_INVALID_HID();
|
|
H5fid = hdf5_h.H5I_INVALID_HID();
|
|
}
|
|
|
|
static
|
|
{
|
|
try {
|
|
System.loadLibrary("hdf5");
|
|
hdf5_h.H5open();
|
|
}
|
|
catch (UnsatisfiedLinkError e) {
|
|
System.err.println("Failed to load HDF5 library: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Acreate()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create scalar attribute space
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
assertTrue("H5Screate scalar failed", isValidId(attr_sid));
|
|
|
|
// Create attribute
|
|
MemorySegment attrName = stringToSegment(arena, "attr1");
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Awrite_read()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute with array dataspace
|
|
long[] attr_dims = {3};
|
|
MemorySegment attrDimsSegment = allocateLongArray(arena, 1);
|
|
attrDimsSegment.setAtIndex(ValueLayout.JAVA_LONG, 0, attr_dims[0]);
|
|
|
|
long attr_sid = hdf5_h.H5Screate_simple(1, attrDimsSegment, MemorySegment.NULL);
|
|
assertTrue("H5Screate_simple failed", isValidId(attr_sid));
|
|
|
|
MemorySegment attrName = stringToSegment(arena, "int_array_attr");
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
// Write data
|
|
int[] write_data = {10, 20, 30};
|
|
MemorySegment writeSegment = allocateIntArray(arena, 3);
|
|
copyToSegment(writeSegment, write_data);
|
|
|
|
int result = hdf5_h.H5Awrite(H5aid, hdf5_h.H5T_NATIVE_INT_g(), writeSegment);
|
|
assertTrue("H5Awrite failed", isSuccess(result));
|
|
|
|
// Read back
|
|
MemorySegment readSegment = allocateIntArray(arena, 3);
|
|
result = hdf5_h.H5Aread(H5aid, hdf5_h.H5T_NATIVE_INT_g(), readSegment);
|
|
assertTrue("H5Aread failed", isSuccess(result));
|
|
|
|
// Verify
|
|
int[] read_data = new int[3];
|
|
copyFromSegment(readSegment, read_data);
|
|
assertArrayEquals("Data mismatch", write_data, read_data);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aopen()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute first
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, "test_attr");
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Open attribute
|
|
H5aid = hdf5_h.H5Aopen(H5did, attrName, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aopen failed", isValidId(H5aid));
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aclose()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, "temp_attr");
|
|
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
int result = hdf5_h.H5Aclose(H5aid);
|
|
assertTrue("H5Aclose failed", isSuccess(result));
|
|
|
|
H5aid = hdf5_h.H5I_INVALID_HID();
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
String expectedName = "my_attribute";
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, expectedName);
|
|
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
// Get name size
|
|
long nameSize = hdf5_h.H5Aget_name(H5aid, 0, MemorySegment.NULL);
|
|
assertTrue("H5Aget_name size query failed", nameSize > 0);
|
|
|
|
// Get name
|
|
MemorySegment nameBuffer = arena.allocate(nameSize + 1);
|
|
hdf5_h.H5Aget_name(H5aid, nameSize + 1, nameBuffer);
|
|
|
|
String retrievedName = nameBuffer.getString(0);
|
|
assertEquals("Attribute name mismatch", expectedName, retrievedName);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_space()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute with specific dimensions
|
|
long[] dims = {5, 3};
|
|
MemorySegment dimsSegment = allocateLongArray(arena, 2);
|
|
copyToSegment(dimsSegment, dims);
|
|
|
|
long attr_sid = hdf5_h.H5Screate_simple(2, dimsSegment, MemorySegment.NULL);
|
|
MemorySegment attrName = stringToSegment(arena, "array_attr");
|
|
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
// Get dataspace
|
|
long retrieved_sid = hdf5_h.H5Aget_space(H5aid);
|
|
assertTrue("H5Aget_space failed", isValidId(retrieved_sid));
|
|
|
|
// Verify dimensions
|
|
MemorySegment retrievedDims = allocateLongArray(arena, 2);
|
|
hdf5_h.H5Sget_simple_extent_dims(retrieved_sid, retrievedDims, MemorySegment.NULL);
|
|
|
|
long[] readDims = new long[2];
|
|
copyFromSegment(retrievedDims, readDims);
|
|
assertArrayEquals("Dimensions mismatch", dims, readDims);
|
|
|
|
hdf5_h.H5Sclose(retrieved_sid);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_type()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, "type_attr");
|
|
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_DOUBLE_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
// Get type
|
|
long retrieved_tid = hdf5_h.H5Aget_type(H5aid);
|
|
assertTrue("H5Aget_type failed", isValidId(retrieved_tid));
|
|
|
|
// Verify it's a double type
|
|
int equal = hdf5_h.H5Tequal(retrieved_tid, hdf5_h.H5T_NATIVE_DOUBLE_g());
|
|
assertTrue("Type should be H5T_NATIVE_DOUBLE", equal > 0);
|
|
|
|
hdf5_h.H5Tclose(retrieved_tid);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aexists()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment existingName = stringToSegment(arena, "existing_attr");
|
|
MemorySegment missingName = stringToSegment(arena, "missing_attr");
|
|
|
|
// Create one attribute
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
long aid = hdf5_h.H5Acreate2(H5did, existingName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Check existing
|
|
int exists = hdf5_h.H5Aexists(H5did, existingName);
|
|
assertTrue("Attribute should exist", exists > 0);
|
|
|
|
// Check non-existing
|
|
exists = hdf5_h.H5Aexists(H5did, missingName);
|
|
assertEquals("Attribute should not exist", 0, exists);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Adelete()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment attrName = stringToSegment(arena, "deletable_attr");
|
|
|
|
// Create attribute
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Verify it exists
|
|
int exists = hdf5_h.H5Aexists(H5did, attrName);
|
|
assertTrue("Attribute should exist before delete", exists > 0);
|
|
|
|
// Delete
|
|
int result = hdf5_h.H5Adelete(H5did, attrName);
|
|
assertTrue("H5Adelete failed", isSuccess(result));
|
|
|
|
// Verify it's gone
|
|
exists = hdf5_h.H5Aexists(H5did, attrName);
|
|
assertEquals("Attribute should not exist after delete", 0, exists);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_storage_size()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute with 10 integers
|
|
long[] attr_dims = {10};
|
|
MemorySegment attrDimsSegment = allocateLongArray(arena, 1);
|
|
attrDimsSegment.setAtIndex(ValueLayout.JAVA_LONG, 0, attr_dims[0]);
|
|
|
|
long attr_sid = hdf5_h.H5Screate_simple(1, attrDimsSegment, MemorySegment.NULL);
|
|
MemorySegment attrName = stringToSegment(arena, "storage_attr");
|
|
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
// Write data
|
|
int[] data = new int[10];
|
|
MemorySegment dataSegment = allocateIntArray(arena, 10);
|
|
copyToSegment(dataSegment, data);
|
|
hdf5_h.H5Awrite(H5aid, hdf5_h.H5T_NATIVE_INT_g(), dataSegment);
|
|
|
|
// Get storage size
|
|
long storage_size = hdf5_h.H5Aget_storage_size(H5aid);
|
|
assertEquals("Storage size should be 10 * sizeof(int)", 40L, storage_size);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Awrite_readStr()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
String testString = "Hello HDF5 Attributes!";
|
|
|
|
// Create string type
|
|
long str_tid = hdf5_h.H5Tcopy(hdf5_h.H5T_C_S1_g());
|
|
assertTrue("H5Tcopy failed", isValidId(str_tid));
|
|
|
|
hdf5_h.H5Tset_size(str_tid, testString.length() + 1);
|
|
hdf5_h.H5Tset_strpad(str_tid, hdf5_h.H5T_STR_NULLTERM());
|
|
|
|
// Create attribute
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, "str_attr");
|
|
|
|
H5aid = hdf5_h.H5Acreate2(H5did, attrName, str_tid, attr_sid, hdf5_h.H5P_DEFAULT(),
|
|
hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(H5aid));
|
|
|
|
// Write string
|
|
MemorySegment writeData = stringToSegment(arena, testString);
|
|
int writeResult = hdf5_h.H5Awrite(H5aid, str_tid, writeData);
|
|
assertTrue("H5Awrite failed", isSuccess(writeResult));
|
|
|
|
// Read string back
|
|
MemorySegment readData = arena.allocate(testString.length() + 1);
|
|
int readResult = hdf5_h.H5Aread(H5aid, str_tid, readData);
|
|
assertTrue("H5Aread failed", isSuccess(readResult));
|
|
|
|
String retrievedString = readData.getString(0);
|
|
assertEquals("String mismatch", testString, retrievedString);
|
|
|
|
hdf5_h.H5Tclose(str_tid);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Arename()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment oldName = stringToSegment(arena, "old_name");
|
|
MemorySegment newName = stringToSegment(arena, "new_name");
|
|
|
|
// Create attribute
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
long aid = hdf5_h.H5Acreate2(H5did, oldName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Verify old name exists
|
|
int exists = hdf5_h.H5Aexists(H5did, oldName);
|
|
assertTrue("Old name should exist", exists > 0);
|
|
|
|
// Rename
|
|
int result = hdf5_h.H5Arename(H5did, oldName, newName);
|
|
assertTrue("H5Arename failed", isSuccess(result));
|
|
|
|
// Verify new name exists and old doesn't
|
|
exists = hdf5_h.H5Aexists(H5did, newName);
|
|
assertTrue("New name should exist", exists > 0);
|
|
|
|
exists = hdf5_h.H5Aexists(H5did, oldName);
|
|
assertEquals("Old name should not exist", 0, exists);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_num_attrs()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create 3 attributes
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
MemorySegment attrName = stringToSegment(arena, "attr_" + i);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for attr_" + i, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Get number of attributes
|
|
int num_attrs = hdf5_h.H5Aget_num_attrs(H5did);
|
|
assertTrue("Should have at least 3 attributes", num_attrs >= 3);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
// =========================
|
|
// Phase 1: Essential Query Operations
|
|
// =========================
|
|
|
|
@Test
|
|
public void testH5Aget_info()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute with scalar dataspace
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, "info_test_attr");
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
|
|
// Write some data
|
|
MemorySegment data = allocateInt(arena);
|
|
setInt(data, 42);
|
|
int writeResult = hdf5_h.H5Awrite(aid, hdf5_h.H5T_NATIVE_INT_g(), data);
|
|
assertTrue("H5Awrite failed", isSuccess(writeResult));
|
|
|
|
// Get attribute info
|
|
MemorySegment info = H5A_info_t.allocate(arena);
|
|
int result = hdf5_h.H5Aget_info(aid, info);
|
|
assertTrue("H5Aget_info failed", isSuccess(result));
|
|
|
|
// Verify info fields
|
|
long data_size = H5A_info_t.data_size(info);
|
|
assertEquals("Data size should be 4 bytes (sizeof int)", 4L, data_size);
|
|
|
|
// corder_valid may be false if creation order tracking is not enabled
|
|
boolean corder_valid = H5A_info_t.corder_valid(info);
|
|
// Just verify we can read it (no assertion on value)
|
|
assertNotNull("corder_valid should be readable", Boolean.valueOf(corder_valid));
|
|
|
|
// cset should be ASCII by default
|
|
int cset = H5A_info_t.cset(info);
|
|
assertEquals("Character set should be ASCII", hdf5_h.H5T_CSET_ASCII(), cset);
|
|
|
|
hdf5_h.H5Aclose(aid);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_info_by_idx()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create multiple attributes to test indexing
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
|
|
String[] attrNames = {"first_attr", "second_attr", "third_attr"};
|
|
for (String name : attrNames) {
|
|
MemorySegment attrName = stringToSegment(arena, name);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_DOUBLE_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Get info for the second attribute (index 1) by name order
|
|
MemorySegment objName = stringToSegment(arena, ".");
|
|
MemorySegment info = H5A_info_t.allocate(arena);
|
|
|
|
int result = hdf5_h.H5Aget_info_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(),
|
|
hdf5_h.H5_ITER_INC(), 1, info, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aget_info_by_idx failed", isSuccess(result));
|
|
|
|
// Verify we got valid info
|
|
long data_size = H5A_info_t.data_size(info);
|
|
assertEquals("Data size should be 8 bytes (sizeof double)", 8L, data_size);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_info_by_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute on dataset
|
|
String attrNameStr = "named_info_attr";
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, attrNameStr);
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_FLOAT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Get info by name from the file (using dataset path)
|
|
MemorySegment objName = stringToSegment(arena, "dset");
|
|
MemorySegment info = H5A_info_t.allocate(arena);
|
|
|
|
int result = hdf5_h.H5Aget_info_by_name(H5fid, objName, attrName, info, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aget_info_by_name failed", isSuccess(result));
|
|
|
|
// Verify info
|
|
long data_size = H5A_info_t.data_size(info);
|
|
assertEquals("Data size should be 4 bytes (sizeof float)", 4L, data_size);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_name_by_idx()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create multiple attributes with known names
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
String[] attrNames = {"alpha", "beta", "gamma"};
|
|
String[] sortedNames = {"alpha", "beta", "gamma"}; // Already sorted alphabetically
|
|
|
|
for (String name : attrNames) {
|
|
MemorySegment attrName = stringToSegment(arena, name);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Get name of each attribute by index (alphabetical order)
|
|
MemorySegment objName = stringToSegment(arena, ".");
|
|
|
|
for (int i = 0; i < sortedNames.length; i++) {
|
|
// Get name size first
|
|
long nameSize =
|
|
hdf5_h.H5Aget_name_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), i,
|
|
MemorySegment.NULL, 0, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aget_name_by_idx size query failed for index " + i, nameSize > 0);
|
|
|
|
// Get actual name
|
|
MemorySegment nameBuffer = arena.allocate(nameSize + 1);
|
|
long result =
|
|
hdf5_h.H5Aget_name_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), i,
|
|
nameBuffer, nameSize + 1, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aget_name_by_idx failed for index " + i, result > 0);
|
|
|
|
String retrievedName = nameBuffer.getString(0);
|
|
assertEquals("Name at index " + i + " should match", sortedNames[i], retrievedName);
|
|
}
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aget_create_plist()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute creation property list with specific settings
|
|
long acpl = hdf5_h.H5Pcreate(hdf5_h.H5P_CLS_ATTRIBUTE_CREATE_ID_g());
|
|
assertTrue("H5Pcreate acpl failed", isValidId(acpl));
|
|
|
|
// Set character encoding to UTF-8
|
|
int setResult = hdf5_h.H5Pset_char_encoding(acpl, hdf5_h.H5T_CSET_UTF8());
|
|
assertTrue("H5Pset_char_encoding failed", isSuccess(setResult));
|
|
|
|
// Create attribute with this property list
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, "plist_attr");
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid, acpl,
|
|
hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
|
|
// Get the creation property list back
|
|
long retrieved_acpl = hdf5_h.H5Aget_create_plist(aid);
|
|
assertTrue("H5Aget_create_plist failed", isValidId(retrieved_acpl));
|
|
|
|
// Verify the encoding is UTF-8
|
|
MemorySegment encoding = allocateInt(arena);
|
|
int getResult = hdf5_h.H5Pget_char_encoding(retrieved_acpl, encoding);
|
|
assertTrue("H5Pget_char_encoding failed", isSuccess(getResult));
|
|
|
|
int retrievedEncoding = getInt(encoding);
|
|
assertEquals("Character encoding should be UTF-8", hdf5_h.H5T_CSET_UTF8(), retrievedEncoding);
|
|
|
|
hdf5_h.H5Pclose(retrieved_acpl);
|
|
hdf5_h.H5Pclose(acpl);
|
|
hdf5_h.H5Aclose(aid);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aexists_by_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute on dataset
|
|
String existingAttrName = "existing_by_name";
|
|
String nonExistingAttrName = "nonexistent_by_name";
|
|
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, existingAttrName);
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Check existence from file using dataset path
|
|
MemorySegment objName = stringToSegment(arena, "dset");
|
|
MemorySegment existingAttrNameSeg = stringToSegment(arena, existingAttrName);
|
|
MemorySegment missingAttrNameSeg = stringToSegment(arena, nonExistingAttrName);
|
|
|
|
// Should exist
|
|
int exists = hdf5_h.H5Aexists_by_name(H5fid, objName, existingAttrNameSeg, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("Attribute should exist", exists > 0);
|
|
|
|
// Should not exist
|
|
exists = hdf5_h.H5Aexists_by_name(H5fid, objName, missingAttrNameSeg, hdf5_h.H5P_DEFAULT());
|
|
assertEquals("Attribute should not exist", 0, exists);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
// =========================
|
|
// Phase 2: Advanced Operations
|
|
// =========================
|
|
|
|
@Test
|
|
public void testH5Aopen_by_idx()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create multiple attributes with known names
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
String[] attrNames = {"apple", "banana", "cherry"};
|
|
String[] sortedNames = {"apple", "banana", "cherry"}; // Already sorted
|
|
|
|
for (String name : attrNames) {
|
|
MemorySegment attrName = stringToSegment(arena, name);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Open second attribute by index (index 1)
|
|
MemorySegment objName = stringToSegment(arena, ".");
|
|
long aid = hdf5_h.H5Aopen_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), 1,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aopen_by_idx failed", isValidId(aid));
|
|
|
|
// Verify we opened the correct attribute by checking its name
|
|
long nameSize = hdf5_h.H5Aget_name(aid, 0, MemorySegment.NULL);
|
|
MemorySegment nameBuf = arena.allocate(nameSize + 1);
|
|
hdf5_h.H5Aget_name(aid, nameSize + 1, nameBuf);
|
|
String retrievedName = nameBuf.getString(0);
|
|
assertEquals("Should have opened 'banana' (index 1)", sortedNames[1], retrievedName);
|
|
|
|
hdf5_h.H5Aclose(aid);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Adelete_by_idx()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create 3 attributes
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
String[] attrNames = {"first", "second", "third"};
|
|
|
|
for (String name : attrNames) {
|
|
MemorySegment attrName = stringToSegment(arena, name);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Delete middle attribute (index 1 = "second")
|
|
MemorySegment objName = stringToSegment(arena, ".");
|
|
int result = hdf5_h.H5Adelete_by_idx(H5did, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(),
|
|
1, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Adelete_by_idx failed", isSuccess(result));
|
|
|
|
// Verify "second" is gone
|
|
MemorySegment secondName = stringToSegment(arena, "second");
|
|
int exists = hdf5_h.H5Aexists(H5did, secondName);
|
|
assertEquals("'second' should not exist after deletion", 0, exists);
|
|
|
|
// Verify others still exist
|
|
MemorySegment firstName = stringToSegment(arena, "first");
|
|
MemorySegment thirdName = stringToSegment(arena, "third");
|
|
exists = hdf5_h.H5Aexists(H5did, firstName);
|
|
assertTrue("'first' should still exist", exists > 0);
|
|
exists = hdf5_h.H5Aexists(H5did, thirdName);
|
|
assertTrue("'third' should still exist", exists > 0);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Adelete_by_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute on dataset
|
|
String attrNameStr = "deletable_by_name";
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment attrName = stringToSegment(arena, attrNameStr);
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Verify it exists
|
|
int exists = hdf5_h.H5Aexists(H5did, attrName);
|
|
assertTrue("Attribute should exist before delete", exists > 0);
|
|
|
|
// Delete by name from file using dataset path
|
|
MemorySegment objName = stringToSegment(arena, "dset");
|
|
int result = hdf5_h.H5Adelete_by_name(H5fid, objName, attrName, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Adelete_by_name failed", isSuccess(result));
|
|
|
|
// Verify it's gone
|
|
exists = hdf5_h.H5Aexists(H5did, attrName);
|
|
assertEquals("Attribute should not exist after delete", 0, exists);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Arename_by_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute on dataset
|
|
String oldNameStr = "old_name_by_path";
|
|
String newNameStr = "new_name_by_path";
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment oldName = stringToSegment(arena, oldNameStr);
|
|
MemorySegment newName = stringToSegment(arena, newNameStr);
|
|
|
|
long aid = hdf5_h.H5Acreate2(H5did, oldName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed", isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Verify old name exists
|
|
int exists = hdf5_h.H5Aexists(H5did, oldName);
|
|
assertTrue("Old name should exist", exists > 0);
|
|
|
|
// Rename by name from file using dataset path
|
|
MemorySegment objName = stringToSegment(arena, "dset");
|
|
int result = hdf5_h.H5Arename_by_name(H5fid, objName, oldName, newName, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Arename_by_name failed", isSuccess(result));
|
|
|
|
// Verify new name exists and old doesn't
|
|
exists = hdf5_h.H5Aexists(H5did, newName);
|
|
assertTrue("New name should exist", exists > 0);
|
|
|
|
exists = hdf5_h.H5Aexists(H5did, oldName);
|
|
assertEquals("Old name should not exist", 0, exists);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aiterate2()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create multiple attributes
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
String[] attrNames = {"attr_A", "attr_B", "attr_C", "attr_D"};
|
|
|
|
for (String name : attrNames) {
|
|
MemorySegment attrName = stringToSegment(arena, name);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Create iteration callback
|
|
final int[] count = {0};
|
|
final String[] names = new String[10];
|
|
H5A_operator2_t.Function cb = (loc_id, attr_name, ainfo, op_data) ->
|
|
{
|
|
try {
|
|
String name = attr_name.getString(0);
|
|
names[count[0]] = name;
|
|
count[0]++;
|
|
return 0; // Continue iteration
|
|
}
|
|
catch (Exception e) {
|
|
return -1; // Stop on error
|
|
}
|
|
};
|
|
|
|
MemorySegment callback = H5A_operator2_t.allocate(cb, arena);
|
|
MemorySegment idx = allocateLong(arena);
|
|
setLong(idx, 0);
|
|
|
|
// Iterate
|
|
int result = hdf5_h.H5Aiterate2(H5did, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), idx,
|
|
callback, MemorySegment.NULL);
|
|
assertTrue("H5Aiterate2 failed", isSuccess(result));
|
|
|
|
// Verify we iterated all attributes (at least the 4 we created)
|
|
assertTrue("Should have iterated at least 4 attributes", count[0] >= 4);
|
|
|
|
// Verify all our attributes were seen
|
|
boolean foundA = false, foundB = false, foundC = false, foundD = false;
|
|
for (int i = 0; i < count[0]; i++) {
|
|
if ("attr_A".equals(names[i]))
|
|
foundA = true;
|
|
if ("attr_B".equals(names[i]))
|
|
foundB = true;
|
|
if ("attr_C".equals(names[i]))
|
|
foundC = true;
|
|
if ("attr_D".equals(names[i]))
|
|
foundD = true;
|
|
}
|
|
assertTrue("Should have found attr_A", foundA);
|
|
assertTrue("Should have found attr_B", foundB);
|
|
assertTrue("Should have found attr_C", foundC);
|
|
assertTrue("Should have found attr_D", foundD);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aiterate_by_name()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attributes on dataset
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
String[] attrNames = {"iter_1", "iter_2", "iter_3"};
|
|
|
|
for (String name : attrNames) {
|
|
MemorySegment attrName = stringToSegment(arena, name);
|
|
long aid = hdf5_h.H5Acreate2(H5did, attrName, hdf5_h.H5T_NATIVE_INT_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate2 failed for " + name, isValidId(aid));
|
|
hdf5_h.H5Aclose(aid);
|
|
}
|
|
|
|
// Create iteration callback
|
|
final int[] count = {0};
|
|
H5A_operator2_t.Function cb = (loc_id, attr_name, ainfo, op_data) ->
|
|
{
|
|
count[0]++;
|
|
return 0; // Continue
|
|
};
|
|
|
|
MemorySegment callback = H5A_operator2_t.allocate(cb, arena);
|
|
MemorySegment idx = allocateLong(arena);
|
|
setLong(idx, 0);
|
|
|
|
// Iterate from file using dataset path
|
|
MemorySegment objName = stringToSegment(arena, "dset");
|
|
int result =
|
|
hdf5_h.H5Aiterate_by_name(H5fid, objName, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), idx,
|
|
callback, MemorySegment.NULL, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aiterate_by_name failed", isSuccess(result));
|
|
|
|
// Verify we iterated at least our 3 attributes
|
|
assertTrue("Should have iterated at least 3 attributes", count[0] >= 3);
|
|
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Acreate_by_name_comprehensive()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Create attribute on dataset using path from file
|
|
String attrNameStr = "created_by_path_comprehensive";
|
|
long attr_sid = hdf5_h.H5Screate(hdf5_h.H5S_SCALAR());
|
|
MemorySegment objName = stringToSegment(arena, "dset");
|
|
MemorySegment attrName = stringToSegment(arena, attrNameStr);
|
|
|
|
long aid =
|
|
hdf5_h.H5Acreate_by_name(H5fid, objName, attrName, hdf5_h.H5T_NATIVE_DOUBLE_g(), attr_sid,
|
|
hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT(), hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Acreate_by_name failed", isValidId(aid));
|
|
|
|
// Write data
|
|
MemorySegment data = allocateDoubleArray(arena, 1);
|
|
data.setAtIndex(ValueLayout.JAVA_DOUBLE, 0, 3.14159);
|
|
int writeResult = hdf5_h.H5Awrite(aid, hdf5_h.H5T_NATIVE_DOUBLE_g(), data);
|
|
assertTrue("H5Awrite failed", isSuccess(writeResult));
|
|
|
|
hdf5_h.H5Aclose(aid);
|
|
|
|
// Verify attribute is accessible from dataset
|
|
MemorySegment attrNameCheck = stringToSegment(arena, attrNameStr);
|
|
int exists = hdf5_h.H5Aexists(H5did, attrNameCheck);
|
|
assertTrue("Attribute should exist on dataset", exists > 0);
|
|
|
|
// Open and read back to verify data
|
|
long aid2 = hdf5_h.H5Aopen(H5did, attrNameCheck, hdf5_h.H5P_DEFAULT());
|
|
assertTrue("H5Aopen failed", isValidId(aid2));
|
|
|
|
MemorySegment readData = allocateDoubleArray(arena, 1);
|
|
int readResult = hdf5_h.H5Aread(aid2, hdf5_h.H5T_NATIVE_DOUBLE_g(), readData);
|
|
assertTrue("H5Aread failed", isSuccess(readResult));
|
|
|
|
double value = readData.getAtIndex(ValueLayout.JAVA_DOUBLE, 0);
|
|
assertEquals("Data should match", 3.14159, value, 0.00001);
|
|
|
|
hdf5_h.H5Aclose(aid2);
|
|
hdf5_h.H5Sclose(attr_sid);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testH5Aiterate()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment idx = allocateLongArray(arena, 1);
|
|
copyToSegment(idx, new long[] {0});
|
|
|
|
// Just verify the API works, iteration callback complex for FFM
|
|
long result = hdf5_h.H5Aiterate2(H5did, hdf5_h.H5_INDEX_NAME(), hdf5_h.H5_ITER_INC(), idx,
|
|
MemorySegment.NULL, MemorySegment.NULL);
|
|
assertTrue("H5Aiterate2 should complete", result >= 0);
|
|
}
|
|
}
|
|
}
|