Files
hdf5/HDF5Examples/JAVA/test-maven-ffm.sh

586 lines
20 KiB
Bash
Executable File

#!/bin/bash
#
# test-maven-ffm.sh - Test HDF5 FFM examples against Maven artifacts
#
# Usage: ./test-maven-ffm.sh [VERSION] [REPOSITORY_URL] [BUILD_DIR]
#
# Examples:
# ./test-maven-ffm.sh 2.0.1-SNAPSHOT
# ./test-maven-ffm.sh 2.0.1
# ./test-maven-ffm.sh 2.0.1-SNAPSHOT https://maven.pkg.github.com/HDFGroup/hdf5
# ./test-maven-ffm.sh 2.0.1-SNAPSHOT https://maven.pkg.github.com/HDFGroup/hdf5 /tmp/maven-test-ffm
#
# Determine source directory (where this script lives)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Default values
VERSION="${1:-2.0.1-SNAPSHOT}"
REPOSITORY_URL="${2:-https://maven.pkg.github.com/HDFGroup/hdf5}"
BUILD_DIR="${3:-${SCRIPT_DIR}/build/maven-test-ffm}"
ARTIFACT_ID="hdf5-java-ffm"
IMPLEMENTATION="FFM"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Create build directory
mkdir -p "${BUILD_DIR}"
# Print header
echo "============================================"
echo "HDF5 Maven ${IMPLEMENTATION} Examples Test"
echo "============================================"
echo "Version: ${VERSION}"
echo "Repository: ${REPOSITORY_URL}"
echo "Artifact: org.hdfgroup:${ARTIFACT_ID}"
echo "Source: ${SCRIPT_DIR}"
echo "Build: ${BUILD_DIR}"
echo "============================================"
echo ""
# Check prerequisites
log_info "Checking prerequisites..."
# Check Java version
if ! command -v java &> /dev/null; then
log_error "Java not found. Please install Java 25 or later."
exit 1
fi
JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | cut -d'.' -f1)
log_info "Java version: $(java -version 2>&1 | head -1)"
if [ "$JAVA_VERSION" -lt 25 ]; then
log_error "Java 25 or later required for FFM. Current version: $JAVA_VERSION"
log_info "FFM uses Foreign Function & Memory API available in Java 25+"
exit 1
fi
# Check Maven
if ! command -v mvn &> /dev/null; then
log_error "Maven not found. Please install Maven 3.6.0 or later."
exit 1
fi
log_info "Maven version: $(mvn -version | head -1)"
# Check GitHub authentication (if using GitHub Packages)
if [[ "$REPOSITORY_URL" == *"github.com"* ]]; then
log_info "Checking GitHub authentication..."
if command -v gh &> /dev/null; then
if gh auth status &> /dev/null; then
log_success "GitHub CLI authenticated"
GITHUB_TOKEN=$(gh auth token)
else
log_warning "GitHub CLI not authenticated. Checking ~/.m2/settings.xml..."
fi
fi
# Check if Maven settings exist and create/update as needed
NEED_UPDATE=false
if [ ! -f ~/.m2/settings.xml ]; then
NEED_UPDATE=true
log_info "Maven settings.xml not found, will create it..."
elif ! grep -q "${REPOSITORY_URL}" ~/.m2/settings.xml 2>/dev/null; then
NEED_UPDATE=true
log_warning "Maven settings.xml has incorrect repository URL, will update it..."
fi
if [ "$NEED_UPDATE" = true ]; then
if [ -z "$GITHUB_TOKEN" ]; then
log_error "No GitHub authentication found. Please run 'gh auth login' or set GITHUB_TOKEN"
exit 1
else
log_info "Creating ~/.m2/settings.xml with GitHub token..."
# Use GITHUB_ACTOR if available, otherwise fall back to git config
GITHUB_USERNAME="${GITHUB_ACTOR:-$(git config user.name || echo "user")}"
mkdir -p ~/.m2
cat > ~/.m2/settings.xml <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>github-hdfgroup-hdf5</id>
<username>${GITHUB_USERNAME}</username>
<password>${GITHUB_TOKEN}</password>
</server>
</servers>
<profiles>
<profile>
<id>github-packages</id>
<repositories>
<repository>
<id>github-hdfgroup-hdf5</id>
<url>${REPOSITORY_URL}</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>github-packages</activeProfile>
</activeProfiles>
</settings>
EOF
log_success "Created/updated ~/.m2/settings.xml"
fi
else
log_success "Found ~/.m2/settings.xml with correct repository URL"
fi
fi
log_success "Prerequisites check passed"
echo ""
# Detect platform classifier (needed for POM generation)
log_info "Detecting platform..."
OS_NAME=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "${OS_NAME}" in
linux*)
PLATFORM="linux"
;;
darwin*)
PLATFORM="macos"
;;
mingw*|msys*|cygwin*)
PLATFORM="windows"
;;
*)
log_error "Unsupported OS: ${OS_NAME}"
exit 1
;;
esac
case "${ARCH}" in
x86_64|amd64)
PLATFORM_ARCH="x86_64"
;;
aarch64|arm64)
PLATFORM_ARCH="aarch64"
;;
*)
log_error "Unsupported architecture: ${ARCH}"
exit 1
;;
esac
PLATFORM_CLASSIFIER="${PLATFORM}-${PLATFORM_ARCH}"
log_info "Platform classifier: ${PLATFORM_CLASSIFIER}"
echo ""
# Generate pom-examples.xml in build directory
log_info "Generating pom-examples.xml for ${IMPLEMENTATION}..."
cat > "${BUILD_DIR}/pom-examples.xml" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hdfgroup</groupId>
<artifactId>hdf5-java-examples-test</artifactId>
<version>1.0.0-TEST</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<hdf5.version>${VERSION}</hdf5.version>
</properties>
<repositories>
<repository>
<id>github-hdfgroup-hdf5</id>
<url>${REPOSITORY_URL}</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.hdfgroup</groupId>
<artifactId>${ARTIFACT_ID}</artifactId>
<version>\${hdf5.version}</version>
<classifier>${PLATFORM_CLASSIFIER}</classifier>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<executions>
<execution>
<id>compile-test-example</id>
<phase>compile</phase>
<goals><goal>compile</goal></goals>
<configuration>
<compileSourceRoots>
<compileSourceRoot>${SCRIPT_DIR}/compat/H5D</compileSourceRoot>
<compileSourceRoot>${SCRIPT_DIR}/compat/H5G</compileSourceRoot>
<compileSourceRoot>${SCRIPT_DIR}/compat/H5T</compileSourceRoot>
<compileSourceRoot>${SCRIPT_DIR}/compat/TUTR</compileSourceRoot>
</compileSourceRoots>
<excludes>
<exclude>**/110/**</exclude>
<exclude>**/112/**</exclude>
<exclude>**/18/**</exclude>
<exclude>**/tfiles/**</exclude>
<!-- FFM callback examples not yet adapted -->
<exclude>**/H5Ex_G_Visit.java</exclude>
<exclude>**/H5Ex_G_Intermediate.java</exclude>
<exclude>**/H5Ex_G_Traverse.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<!-- Enable native access for FFM -->
<arguments>
<argument>--enable-native-access=ALL-UNNAMED</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
EOF
log_success "Generated pom-examples.xml"
echo ""
# Clean previous builds
log_info "Cleaning previous builds..."
mvn clean -f "${BUILD_DIR}/pom-examples.xml" -q
rm -f "${BUILD_DIR}"/*.h5 2>/dev/null || true
log_success "Clean complete"
echo ""
# Clear cached SNAPSHOT to force fresh download
if [[ "$VERSION" == *"SNAPSHOT"* ]]; then
log_info "Clearing cached SNAPSHOT from local repository..."
rm -rf ~/.m2/repository/org/hdfgroup/${ARTIFACT_ID}/${VERSION}
fi
# Download dependencies and verify artifact
log_info "Downloading Maven artifact: org.hdfgroup:${ARTIFACT_ID}:${VERSION} with classifier ${PLATFORM_CLASSIFIER}..."
# For SNAPSHOT versions, download directly using curl to work around maven-metadata.xml classifier issues
if [[ "$VERSION" == *"SNAPSHOT"* ]]; then
log_info "SNAPSHOT version detected - using direct download..."
METADATA_URL="${REPOSITORY_URL}/org/hdfgroup/${ARTIFACT_ID}/${VERSION}/maven-metadata.xml"
# Download metadata
TEMP_METADATA=$(mktemp) || {
log_error "Failed to create temporary file for metadata"
exit 1
}
trap "rm -f '$TEMP_METADATA'" EXIT
if ! curl -u "${GITHUB_ACTOR:-$USER}:${GITHUB_TOKEN}" -fsSL "$METADATA_URL" -o "$TEMP_METADATA"; then
log_error "Failed to download maven-metadata.xml from ${METADATA_URL}"
log_error "Check repository URL and authentication"
exit 1
fi
# Extract timestamped version from metadata
# Note: Maven may truncate long classifiers, so we search for partial matches
# e.g., "linux-x86_64" may be stored as classifier="linux-x" extension="6_64.jar"
# Maven removes suffixes: 86_64, _64, or 64
TRUNCATED_CLASSIFIER=$(echo "$PLATFORM_CLASSIFIER" | sed -E 's/(86_64|_64|64)$//')
# Parse XML using awk (xmllint may not be available)
# Format XML (GitHub Packages returns minified XML on one line)
# Look for snapshotVersion blocks with matching classifier and jar extension
log_info "Searching for classifier: ${TRUNCATED_CLASSIFIER}"
TIMESTAMPED_VERSION=$(sed 's/></>\n</g' "$TEMP_METADATA" | awk -v search_classifier="${TRUNCATED_CLASSIFIER}" '
/<snapshotVersion>/ { in_block=1; classifier=""; extension=""; value="" }
/<\/snapshotVersion>/ {
if (in_block && classifier == search_classifier && extension ~ /jar/) {
print value
exit
}
in_block=0
}
in_block && /<classifier>/ { gsub(/.*<classifier>|<\/classifier>.*/, ""); classifier=$0 }
in_block && /<extension>/ { gsub(/.*<extension>|<\/extension>.*/, ""); extension=$0 }
in_block && /<value>/ { gsub(/.*<value>|<\/value>.*/, ""); value=$0 }
')
if [ -z "$TIMESTAMPED_VERSION" ]; then
log_error "Could not extract SNAPSHOT version from metadata"
log_error "Searched for classifier starting with: ${TRUNCATED_CLASSIFIER}"
cat "$TEMP_METADATA"
exit 1
fi
log_info "Latest SNAPSHOT version: ${TIMESTAMPED_VERSION}"
JAR_FILENAME="${ARTIFACT_ID}-${TIMESTAMPED_VERSION}-${PLATFORM_CLASSIFIER}.jar"
POM_FILENAME="${ARTIFACT_ID}-${TIMESTAMPED_VERSION}.pom"
# Download JAR and POM
JAR_URL="${REPOSITORY_URL}/org/hdfgroup/${ARTIFACT_ID}/${VERSION}/${JAR_FILENAME}"
POM_URL="${REPOSITORY_URL}/org/hdfgroup/${ARTIFACT_ID}/${VERSION}/${POM_FILENAME}"
TEMP_DIR=$(mktemp -d) || {
log_error "Failed to create temporary directory"
exit 1
}
trap "rm -rf '$TEMP_DIR' '$TEMP_METADATA'" EXIT
log_info "Downloading JAR: ${JAR_FILENAME}"
if ! curl -u "${GITHUB_ACTOR:-$USER}:${GITHUB_TOKEN}" -fsSL "$JAR_URL" -o "$TEMP_DIR/${JAR_FILENAME}"; then
log_error "Failed to download JAR from ${JAR_URL}"
exit 1
fi
log_info "Downloading POM: ${POM_FILENAME}"
if ! curl -u "${GITHUB_ACTOR:-$USER}:${GITHUB_TOKEN}" -fsSL "$POM_URL" -o "$TEMP_DIR/${POM_FILENAME}"; then
log_error "Failed to download POM from ${POM_URL}"
exit 1
fi
# Install to local Maven repository
log_info "Installing artifact to local repository..."
if mvn install:install-file \
-Dfile="$TEMP_DIR/${JAR_FILENAME}" \
-DpomFile="$TEMP_DIR/${POM_FILENAME}" \
-DgroupId=org.hdfgroup \
-DartifactId=${ARTIFACT_ID} \
-Dversion=${VERSION} \
-Dpackaging=jar \
-Dclassifier=${PLATFORM_CLASSIFIER} \
-q; then
log_success "Artifact installed successfully"
else
log_error "Failed to install artifact"
exit 1
fi
else
# Release version - use standard Maven download
if mvn dependency:get \
-Dartifact=org.hdfgroup:${ARTIFACT_ID}:${VERSION} \
-Dclassifier=${PLATFORM_CLASSIFIER} \
-q; then
log_success "Artifact downloaded successfully"
else
log_error "Failed to download artifact. Check version and repository URL."
exit 1
fi
fi
echo ""
# Verify JAR contents
log_info "Verifying JAR contents..."
JAR_PATH=$(find ~/.m2/repository/org/hdfgroup/${ARTIFACT_ID}/${VERSION} -name "*.jar" ! -name "*sources*" ! -name "*javadoc*" | head -1)
if [ -z "$JAR_PATH" ]; then
log_error "Could not find downloaded JAR file"
exit 1
fi
log_info "JAR location: ${JAR_PATH}"
log_info "JAR size: $(du -h "$JAR_PATH" | cut -f1)"
# Check for HDF5 FFM classes
if jar tf "$JAR_PATH" | grep -q "org/hdfgroup/javahdf5/hdf5_h.class"; then
log_success "JAR contains HDF5 FFM classes (org.hdfgroup.javahdf5.*)"
else
log_error "JAR does not contain HDF5 FFM classes! Only contains:"
jar tf "$JAR_PATH" | head -20
log_error "This indicates the Maven artifact was built incorrectly."
exit 1
fi
# Count classes that should be present
CLASS_COUNT=$(jar tf "$JAR_PATH" | grep "org/hdfgroup/javahdf5.*\.class" | wc -l)
log_info "Found $CLASS_COUNT HDF5 FFM classes in JAR"
echo ""
# Compile test example (single known-good example for verification)
log_info "Compiling test example (H5Ex_D_ReadWrite)..."
if mvn compile -f "${BUILD_DIR}/pom-examples.xml" -U; then
log_success "Test example compiled successfully"
else
log_error "Compilation failed"
exit 1
fi
echo ""
# Verify compiled example file
if [ -f "${BUILD_DIR}/target/classes/H5Ex_D_ReadWrite.class" ]; then
log_success "Test example class file created"
else
log_warning "Expected class file not found, but compilation succeeded"
fi
echo ""
# Check for native HDF5 libraries
log_info "Checking for native HDF5 libraries..."
HAVE_NATIVE_LIBS=false
# Check common library locations and HDF5_HOME
if [ -n "${HDF5_HOME:-}" ]; then
log_info "HDF5_HOME is set: ${HDF5_HOME}"
if [ -d "${HDF5_HOME}/lib" ]; then
export LD_LIBRARY_PATH="${HDF5_HOME}/lib:${LD_LIBRARY_PATH:-}"
log_success "Added ${HDF5_HOME}/lib to LD_LIBRARY_PATH"
HAVE_NATIVE_LIBS=true
fi
elif ldconfig -p 2>/dev/null | grep -q "libhdf5.so"; then
log_success "Found libhdf5.so in system libraries"
HAVE_NATIVE_LIBS=true
elif [ -f /usr/lib/x86_64-linux-gnu/libhdf5.so ] || [ -f /usr/lib/libhdf5.so ] || [ -f /usr/local/lib/libhdf5.so ]; then
log_success "Found libhdf5.so in standard location"
HAVE_NATIVE_LIBS=true
else
log_warning "Native HDF5 libraries not found"
log_info "To run examples, install HDF5 libraries or set HDF5_HOME"
log_info " Ubuntu/Debian: sudo apt-get install libhdf5-dev"
log_info " Fedora/RHEL: sudo dnf install hdf5-devel"
log_info " macOS: brew install hdf5"
log_info " Or set: export HDF5_HOME=/path/to/hdf5/installation"
fi
echo ""
# Run comprehensive test examples (change to build directory so .h5 files are created there)
if [ "$HAVE_NATIVE_LIBS" = true ]; then
log_info "Running comprehensive test examples..."
echo ""
# Define test examples covering major HDF5 features
TEST_EXAMPLES=(
# Dataset operations
"H5Ex_D_ReadWrite:Basic dataset read/write"
"H5Ex_D_Chunk:Chunked dataset storage"
"H5Ex_D_Gzip:GZIP compression"
"H5Ex_D_Hyperslab:Hyperslab selection"
"H5Ex_D_Alloc:Dataset allocation"
# Group operations
"H5Ex_G_Create:Group creation"
"H5Ex_G_Iterate:Group iteration"
# Datatype operations
"H5Ex_T_String:String datatype"
"H5Ex_T_Array:Array datatype"
"H5Ex_T_Compound:Compound datatype"
# Tutorials
"HDF5FileCreate:File creation tutorial"
"HDF5DatasetCreate:Dataset creation tutorial"
)
PASSED=0
FAILED=0
FAILED_EXAMPLES=()
for example_spec in "${TEST_EXAMPLES[@]}"; do
IFS=':' read -r example_name description <<< "$example_spec"
printf " Testing %-30s " "$example_name..."
if (cd "${BUILD_DIR}" && mvn exec:java -Dexec.mainClass="$example_name" -f pom-examples.xml -q 2>&1 | grep -v "^\["); then
echo -e "\033[0;32m✓\033[0m $description"
((PASSED++))
else
echo -e "\033[0;31m✗\033[0m $description"
((FAILED++))
FAILED_EXAMPLES+=("$example_name")
fi
done
echo ""
log_info "Test Results: $PASSED passed, $FAILED failed out of ${#TEST_EXAMPLES[@]} tests"
if [ $FAILED -gt 0 ]; then
log_warning "Failed examples:"
for failed in "${FAILED_EXAMPLES[@]}"; do
echo " - $failed"
done
log_warning "Some examples failed, but Maven artifact verification succeeded"
log_info "Failures may be due to optional dependencies (e.g., SZIP, GZIP)"
else
log_success "All test examples executed successfully!"
fi
# Check for created HDF5 files
H5_COUNT=$(find "${BUILD_DIR}" -name "*.h5" 2>/dev/null | wc -l)
if [ "$H5_COUNT" -gt 0 ]; then
log_success "Created $H5_COUNT HDF5 file(s) in ${BUILD_DIR}"
fi
else
log_warning "Skipping execution test - native HDF5 libraries not available"
log_info "Maven artifact download, installation, and compilation verified successfully"
log_info "To test execution, install native HDF5 libraries or set HDF5_HOME"
fi
echo ""
# Final summary
echo "============================================"
echo " TEST SUMMARY"
echo "============================================"
log_success "All tests passed!"
echo ""
echo "Summary:"
echo " - Artifact: org.hdfgroup:${ARTIFACT_ID}:${VERSION}"
echo " - Platform: ${PLATFORM_CLASSIFIER}"
echo " - JAR Size: $(du -h "$JAR_PATH" | cut -f1)"
echo " - Classes: $CLASS_COUNT HDF5 FFM classes"
if [ "$HAVE_NATIVE_LIBS" = true ]; then
echo " - Test: H5Ex_D_ReadWrite compiled and executed successfully"
else
echo " - Test: H5Ex_D_ReadWrite compiled successfully (execution skipped - no native libs)"
fi
echo "============================================"
echo ""
log_info "Build directory: ${BUILD_DIR}"
echo ""
log_info "To run more examples:"
echo " cd \"${BUILD_DIR}\" && mvn exec:java -Dexec.mainClass=\"EXAMPLE_NAME\" -f pom-examples.xml"
echo ""
log_info "To clean up test files:"
echo " mvn clean -f \"${BUILD_DIR}/pom-examples.xml\" && rm -rf \"${BUILD_DIR}\""