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.
423 lines
16 KiB
Java
423 lines
16 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.Before;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.rules.TestName;
|
|
|
|
/**
|
|
* FFM-only tests for HDF5 Plugin (H5PL) operations.
|
|
*
|
|
* NOTE: These tests focus on plugin path management and loading state control.
|
|
* Actual plugin loading requires external plugin libraries and specialized setup.
|
|
*/
|
|
public class TestH5PLffm {
|
|
@Rule
|
|
public TestName testname = new TestName();
|
|
|
|
// Store initial state to restore after tests
|
|
private int initialPluginState;
|
|
private int initialPathCount;
|
|
|
|
@Before
|
|
public void setUp()
|
|
{
|
|
System.out.print(testname.getMethodName());
|
|
|
|
// Save initial plugin loading state
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment stateSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
int result = hdf5_h.H5PLget_loading_state(stateSeg);
|
|
if (result >= 0) {
|
|
initialPluginState = stateSeg.get(ValueLayout.JAVA_INT, 0);
|
|
}
|
|
}
|
|
|
|
// Save initial path count
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
int result = hdf5_h.H5PLsize(countSeg);
|
|
if (result >= 0) {
|
|
initialPathCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
@After
|
|
public void tearDown()
|
|
{
|
|
// Restore initial plugin loading state
|
|
hdf5_h.H5PLset_loading_state(initialPluginState);
|
|
|
|
// Remove any paths added during testing (in reverse order)
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int currentCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
|
|
// Remove paths added by tests
|
|
while (currentCount > initialPathCount) {
|
|
hdf5_h.H5PLremove(currentCount - 1);
|
|
currentCount--;
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
/**
|
|
* Test H5PLset_loading_state and H5PLget_loading_state
|
|
*/
|
|
@Test
|
|
public void testH5PLset_and_get_loading_state()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment stateSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Get initial state
|
|
int result = hdf5_h.H5PLget_loading_state(stateSeg);
|
|
assertEquals("H5PLget_loading_state should succeed", 0, result);
|
|
int originalState = stateSeg.get(ValueLayout.JAVA_INT, 0);
|
|
|
|
// Enable all plugins
|
|
result = hdf5_h.H5PLset_loading_state(hdf5_h.H5PL_ALL_PLUGIN());
|
|
assertEquals("H5PLset_loading_state should succeed", 0, result);
|
|
|
|
result = hdf5_h.H5PLget_loading_state(stateSeg);
|
|
assertEquals("H5PLget_loading_state should succeed", 0, result);
|
|
int allState = stateSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("All plugins should be enabled", hdf5_h.H5PL_ALL_PLUGIN(), allState);
|
|
|
|
// Enable only filter plugins
|
|
result = hdf5_h.H5PLset_loading_state(hdf5_h.H5PL_FILTER_PLUGIN());
|
|
assertEquals("H5PLset_loading_state should succeed", 0, result);
|
|
|
|
result = hdf5_h.H5PLget_loading_state(stateSeg);
|
|
assertEquals("H5PLget_loading_state should succeed", 0, result);
|
|
int filterState = stateSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("Only filter plugins should be enabled", hdf5_h.H5PL_FILTER_PLUGIN(), filterState);
|
|
|
|
// Disable all plugins
|
|
result = hdf5_h.H5PLset_loading_state(0);
|
|
assertEquals("H5PLset_loading_state should succeed", 0, result);
|
|
|
|
result = hdf5_h.H5PLget_loading_state(stateSeg);
|
|
assertEquals("H5PLget_loading_state should succeed", 0, result);
|
|
int disabledState = stateSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("All plugins should be disabled", 0, disabledState);
|
|
|
|
// Restore original state
|
|
hdf5_h.H5PLset_loading_state(originalState);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLsize - get number of plugin search paths
|
|
*/
|
|
@Test
|
|
public void testH5PLsize()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
int result = hdf5_h.H5PLsize(countSeg);
|
|
assertEquals("H5PLsize should succeed", 0, result);
|
|
|
|
int pathCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertTrue("Path count should be non-negative", pathCount >= 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLappend - add path to end of search list
|
|
*/
|
|
@Test
|
|
public void testH5PLappend()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Get initial count
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int initialCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
|
|
// Append a test path
|
|
MemorySegment testPath = stringToSegment(arena, "/tmp/test_plugin_path");
|
|
int result = hdf5_h.H5PLappend(testPath);
|
|
assertEquals("H5PLappend should succeed", 0, result);
|
|
|
|
// Verify count increased
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int newCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("Path count should increase by 1", initialCount + 1, newCount);
|
|
|
|
// Verify the path was added at the end
|
|
long size = hdf5_h.H5PLget(newCount - 1, MemorySegment.NULL, 0);
|
|
assertTrue("Should get path size", size > 0);
|
|
|
|
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
|
|
size = hdf5_h.H5PLget(newCount - 1, pathBuf, size + 1);
|
|
String retrievedPath = segmentToString(pathBuf);
|
|
assertEquals("Retrieved path should match", "/tmp/test_plugin_path", retrievedPath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLprepend - add path to beginning of search list
|
|
*/
|
|
@Test
|
|
public void testH5PLprepend()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Get initial count
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int initialCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
|
|
// Prepend a test path
|
|
MemorySegment testPath = stringToSegment(arena, "/tmp/test_prepend_path");
|
|
int result = hdf5_h.H5PLprepend(testPath);
|
|
assertEquals("H5PLprepend should succeed", 0, result);
|
|
|
|
// Verify count increased
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int newCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("Path count should increase by 1", initialCount + 1, newCount);
|
|
|
|
// Verify the path was added at the beginning (index 0)
|
|
long size = hdf5_h.H5PLget(0, MemorySegment.NULL, 0);
|
|
assertTrue("Should get path size", size > 0);
|
|
|
|
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
|
|
size = hdf5_h.H5PLget(0, pathBuf, size + 1);
|
|
String retrievedPath = segmentToString(pathBuf);
|
|
assertEquals("Retrieved path should match", "/tmp/test_prepend_path", retrievedPath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLinsert - insert path at specific index
|
|
*/
|
|
@Test
|
|
public void testH5PLinsert()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Add two paths first
|
|
MemorySegment path1 = stringToSegment(arena, "/tmp/path1");
|
|
MemorySegment path2 = stringToSegment(arena, "/tmp/path2");
|
|
hdf5_h.H5PLappend(path1);
|
|
hdf5_h.H5PLappend(path2);
|
|
|
|
// Get count before insert
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int beforeCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
|
|
// Insert path at index 1 (between path1 and path2)
|
|
MemorySegment insertPath = stringToSegment(arena, "/tmp/path_inserted");
|
|
int result = hdf5_h.H5PLinsert(insertPath, beforeCount - 1);
|
|
assertEquals("H5PLinsert should succeed", 0, result);
|
|
|
|
// Verify count increased
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int afterCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("Path count should increase by 1", beforeCount + 1, afterCount);
|
|
|
|
// Verify the path was inserted at correct position
|
|
long size = hdf5_h.H5PLget(beforeCount - 1, MemorySegment.NULL, 0);
|
|
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
|
|
hdf5_h.H5PLget(beforeCount - 1, pathBuf, size + 1);
|
|
String retrievedPath = segmentToString(pathBuf);
|
|
assertEquals("Retrieved path should match", "/tmp/path_inserted", retrievedPath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLreplace - replace path at specific index
|
|
*/
|
|
@Test
|
|
public void testH5PLreplace()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Add a test path
|
|
MemorySegment originalPath = stringToSegment(arena, "/tmp/original_path");
|
|
hdf5_h.H5PLappend(originalPath);
|
|
|
|
// Get count and index of last path
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int count = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
int lastIdx = count - 1;
|
|
|
|
// Replace the last path
|
|
MemorySegment replacePath = stringToSegment(arena, "/tmp/replacement_path");
|
|
int result = hdf5_h.H5PLreplace(replacePath, lastIdx);
|
|
assertEquals("H5PLreplace should succeed", 0, result);
|
|
|
|
// Verify count unchanged
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int newCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("Path count should remain the same", count, newCount);
|
|
|
|
// Verify the path was replaced
|
|
long size = hdf5_h.H5PLget(lastIdx, MemorySegment.NULL, 0);
|
|
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
|
|
hdf5_h.H5PLget(lastIdx, pathBuf, size + 1);
|
|
String retrievedPath = segmentToString(pathBuf);
|
|
assertEquals("Retrieved path should be replacement", "/tmp/replacement_path", retrievedPath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLremove - remove path at specific index
|
|
*/
|
|
@Test
|
|
public void testH5PLremove()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Add a test path
|
|
MemorySegment testPath = stringToSegment(arena, "/tmp/path_to_remove");
|
|
hdf5_h.H5PLappend(testPath);
|
|
|
|
// Get count before removal
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int beforeCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
|
|
// Remove the last path
|
|
int result = hdf5_h.H5PLremove(beforeCount - 1);
|
|
assertEquals("H5PLremove should succeed", 0, result);
|
|
|
|
// Verify count decreased
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int afterCount = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("Path count should decrease by 1", beforeCount - 1, afterCount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLget - retrieve path at specific index
|
|
*/
|
|
@Test
|
|
public void testH5PLget()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment countSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Add a known test path
|
|
String knownPath = "/tmp/test_get_path";
|
|
MemorySegment testPath = stringToSegment(arena, knownPath);
|
|
hdf5_h.H5PLappend(testPath);
|
|
|
|
// Get the index of the path we just added
|
|
hdf5_h.H5PLsize(countSeg);
|
|
int count = countSeg.get(ValueLayout.JAVA_INT, 0);
|
|
int lastIdx = count - 1;
|
|
|
|
// First call to get size (with NULL buffer)
|
|
long size = hdf5_h.H5PLget(lastIdx, MemorySegment.NULL, 0);
|
|
assertTrue("Should return path length", size > 0);
|
|
|
|
// Second call to get actual path
|
|
MemorySegment pathBuf = arena.allocate(ValueLayout.JAVA_BYTE, (int)size + 1);
|
|
long actualSize = hdf5_h.H5PLget(lastIdx, pathBuf, size + 1);
|
|
assertEquals("Sizes should match", size, actualSize);
|
|
|
|
String retrievedPath = segmentToString(pathBuf);
|
|
assertEquals("Retrieved path should match", knownPath, retrievedPath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test H5PLget with invalid index
|
|
*/
|
|
@Test
|
|
public void testH5PLget_invalid_index()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
// Try to get path at very large invalid index
|
|
long size = hdf5_h.H5PLget(99999, MemorySegment.NULL, 0);
|
|
|
|
// Should return negative value or zero for invalid index
|
|
assertTrue("Should return error for invalid index", size <= 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test plugin type constants
|
|
*/
|
|
@Test
|
|
public void testH5PL_plugin_type_constants()
|
|
{
|
|
// Verify plugin type flag constants exist and have expected values
|
|
int filterPlugin = hdf5_h.H5PL_FILTER_PLUGIN();
|
|
int volPlugin = hdf5_h.H5PL_VOL_PLUGIN();
|
|
int vfdPlugin = hdf5_h.H5PL_VFD_PLUGIN();
|
|
int allPlugin = hdf5_h.H5PL_ALL_PLUGIN();
|
|
|
|
// Filter plugin should be bit 0
|
|
assertEquals("H5PL_FILTER_PLUGIN should be 0x0001", 0x0001, filterPlugin);
|
|
|
|
// VOL plugin should be bit 1
|
|
assertEquals("H5PL_VOL_PLUGIN should be 0x0002", 0x0002, volPlugin);
|
|
|
|
// VFD plugin should be bit 2
|
|
assertEquals("H5PL_VFD_PLUGIN should be 0x0004", 0x0004, vfdPlugin);
|
|
|
|
// All plugins should be 0xFFFF
|
|
assertEquals("H5PL_ALL_PLUGIN should be 0xFFFF", 0xFFFF, allPlugin);
|
|
}
|
|
|
|
/**
|
|
* Test multiple plugin types enabled simultaneously
|
|
*/
|
|
@Test
|
|
public void testH5PL_multiple_plugin_types()
|
|
{
|
|
try (Arena arena = Arena.ofConfined()) {
|
|
MemorySegment stateSeg = arena.allocate(ValueLayout.JAVA_INT);
|
|
|
|
// Enable filter and VOL plugins
|
|
int combinedMask = hdf5_h.H5PL_FILTER_PLUGIN() | hdf5_h.H5PL_VOL_PLUGIN();
|
|
int result = hdf5_h.H5PLset_loading_state(combinedMask);
|
|
assertEquals("H5PLset_loading_state should succeed", 0, result);
|
|
|
|
// Verify state
|
|
hdf5_h.H5PLget_loading_state(stateSeg);
|
|
int state = stateSeg.get(ValueLayout.JAVA_INT, 0);
|
|
assertEquals("State should match combined mask", combinedMask, state);
|
|
|
|
// Verify individual bits are set
|
|
assertTrue("Filter plugin should be enabled", (state & hdf5_h.H5PL_FILTER_PLUGIN()) != 0);
|
|
assertTrue("VOL plugin should be enabled", (state & hdf5_h.H5PL_VOL_PLUGIN()) != 0);
|
|
assertFalse("VFD plugin should not be enabled", (state & hdf5_h.H5PL_VFD_PLUGIN()) != 0);
|
|
}
|
|
}
|
|
}
|