Arctic Project Guide - adoptium/aqa-tests GitHub Wiki

Section 1: Introduction

Some Text To Go Here!

Section 2: Installation

Setting Up and Building the Corretto Arctic Project

This guide provides step-by-step instructions for setting up your environment, downloading and installing an appropriate Temurin JDK 17 binary, configuring environment variables, and building the Corretto Arctic project from the command line.

Prerequisites

  • A Git client installed on your system.
  • Administrative privileges (where necessary).

Step 1: Clone the Repository

To get started, clone the GitHub repository to your local machine. Open a terminal and run:

git clone https://github.com/corretto/arctic.git
cd arctic

This command downloads the repository and navigates into the arctic directory.


Step 2: Download and Install Temurin JDK 17

The Temurin JDK 17 binary needs to be installed for your platform. Below are instructions for Linux, Windows, and macOS.

Linux

curl -L -o temurin.tar.gz "https://api.adoptium.net/v3/binary/latest/17/ga/linux/x64/jdk/hotspot/normal/eclipse"
tar -xzf temurin.tar.gz
mv jdk-* temurin-jdk17

Windows (PowerShell)

Invoke-WebRequest -Uri "https://api.adoptium.net/v3/binary/latest/17/ga/windows/x64/jdk/hotspot/normal/eclipse" -OutFile "temurin.zip"
Expand-Archive -Path "temurin.zip" -DestinationPath "temurin-jdk17"

macOS

curl -L -o temurin.tar.gz "https://api.adoptium.net/v3/binary/latest/17/ga/mac/x64/jdk/hotspot/normal/eclipse"
tar -xzf temurin.tar.gz
mv jdk-* temurin-jdk17

Step 3: Configure Environment Variables

Linux/macOS

In the shell, set the environment variables for JAVA_HOME & PATH

export JAVA_HOME=$(pwd)/temurin-jdk17
export PATH=$JAVA_HOME/bin:$PATH

Apply the changes:

source ~/.bashrc  # or source ~/.zshrc

Windows (PowerShell)

$env:JAVA_HOME = "$(Get-Location)\temurin-jdk17"
$env:Path += ";$env:JAVA_HOME\bin"

To make these changes permanent, update the system environment variables manually:

  1. Open System Properties > Advanced > Environment Variables.
  2. Add a new variable JAVA_HOME pointing to the extracted temurin-jdk17 folder.
  3. Append %JAVA_HOME%\bin to the Path variable.

Step 4: Verify Java Installation

Confirm that the correct JDK version is installed:

java -version

The output should indicate JDK 17 from Eclipse Temurin:

openjdk version "17.0.x" 202x-xx-xx

Step 5: Build the Project with Gradle

Navigate to the project root directory:

cd ..  # Move to the project root

Run the Gradle build command:

./gradlew build  # Linux/macOS
.\gradlew.bat build  # Windows

This will download dependencies and build the project.


Conclusion

You have successfully cloned the repository, installed the Temurin JDK 17, set up environment variables, and built the project using Gradle. The built Arctic.jar should be in the build/Jars subdirectory of the base arctic directory.


Building Arctic on Windows ARM64

Arctic depends on com.github.kwhat:jnativehook:2.2.2 for global keyboard and mouse capture. The pre-built JAR from Maven Central does not include a Windows ARM64 native DLL, so it must be compiled from source and substituted into the Arctic fat-JAR before use on ARM64 machines.

Run all commands in Windows Command Prompt (cmd.exe), not PowerShell or Cygwin. CMake's Visual Studio generator does not work correctly from PowerShell or MSYS shells.

Additional prerequisites for ARM64

In addition to the standard prerequisites above, install:

Tool Notes
Windows 11 ARM64 Native ARM64 machine or VM
JDK 17 for Windows ARM64 e.g. Eclipse Temurin ARM64. Set JAVA_HOME to the JDK directory.
Apache Maven 3.6+ Binary ZIP from maven.apache.org; add bin\ to PATH. No ARM64-specific build needed.
CMake 3.20+ Use the native Windows ARM64 installer from cmake.org. Add to PATH ahead of any Cygwin or MSYS installation.
Visual Studio 2022 Build Tools In Visual Studio Installer select Desktop development with C++, including MSVC v143 ARM64/ARM64EC build tools and a Windows SDK.

Verify the environment before starting:

java -version
mvn -version
git --version
where cmake
cmake --version
cmake --help | findstr /i "Visual Studio"

Confirm that cmake --help lists Visual Studio 17 2022 as an available generator and that where cmake returns a path under Program Files\CMake, not Cygwin or MSYS2.

Set the environment for the current session (adjust paths to your installations):

set "JAVA_HOME=C:\Tools\jdk-17"
set "PATH=%JAVA_HOME%\bin;C:\Tools\apache-maven\bin;C:\Program Files\CMake\bin;%PATH%"

Step A: Clone jNativeHook and initialise the submodule

mkdir C:\arctic-dev\jnativehook
cd /d C:\arctic-dev\jnativehook
git clone --branch 2.2 https://github.com/kwhat/jnativehook.git
cd jnativehook

Initialise the libuiohook submodule using HTTPS (avoids needing an SSH key):

git submodule init
git config submodule.libuiohook.url https://github.com/kwhat/libuiohook.git
git submodule update --init --recursive

Verify the submodule is present:

dir src\external\libuiohook\CMakeLists.txt

Use a full git clone, not a source ZIP. The ZIP does not include the submodule and the build will fail at the CMake configure step.

Step B: Generate Java classes and JNI headers

mvn clean compile

Confirm the generated header exists:

dir target\include\com_github_kwhat_jnativehook_GlobalScreen.h

Edit the root CMakeLists.txt. Find the target_include_directories(jnativehook ...) block and replace it with the following to add the Maven-generated header directory:

target_include_directories(jnativehook
    PUBLIC
        $<BUILD_INTERFACE:${JNI_INCLUDE_DIRS}>

    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni
        ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni/include
        "${CMAKE_CURRENT_SOURCE_DIR}/target/include"
)

Do not run mvn clean again after this point. It deletes target\, removing the native build outputs and generated JNI headers. Use mvn compile if you only need to regenerate headers.

Step C: Build the native dependency (libuiohook)

Run each command from the repository root as a single line:

cmake -S src/external/libuiohook -B target/build/libuiohook-arm64 -G "Visual Studio 17 2022" -A ARM64 "-DCMAKE_INSTALL_PREFIX=%CD%/target/native-arm64" -DBUILD_SHARED_LIBS=OFF

cmake --build target/build/libuiohook-arm64 --config RelWithDebInfo --parallel 2

cmake --install target/build/libuiohook-arm64 --config RelWithDebInfo

This compiles libuiohook as a static library that will be linked into the DLL.

Step D: Build and install the DLL

cmake -S . -B target/build/jni-arm64 -G "Visual Studio 17 2022" -A ARM64 "-DCMAKE_PREFIX_PATH=%CD%/target/native-arm64" -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_SYSTEM_PROCESSOR=arm64

cmake --build target/build/jni-arm64 --config RelWithDebInfo --parallel 2

cmake --install target/build/jni-arm64 --config RelWithDebInfo

The compiled DLL is at:

C:\arctic-dev\jnativehook\jnativehook\target\build\jni-arm64\RelWithDebInfo\JNativeHook.dll

The install step also copies it to the JAR resource path:

C:\arctic-dev\jnativehook\jnativehook\src\main\resources\com\github\kwhat\jnativehook\lib\windows\arm64\JNativeHook.dll

Step E: Package the jNativeHook JAR

mvn package
jar tf target\jnativehook-2.2-SNAPSHOT.jar | findstr /i "JNativeHook.dll"

The listing must include:

com/github/kwhat/jnativehook/lib/windows/arm64/JNativeHook.dll

Step F: Substitute the DLL into the Arctic fat-JAR

Arctic is distributed as a single fat-JAR (Arctic.jar) that bundles jNativeHook inside it. Replace the bundled DLL with the ARM64 one you just built:

cd /d C:\arctic-dev\jnativehook\jnativehook
jar uf <path-to>\Arctic.jar -C src\main\resources .

Verify the replacement:

jar tf <path-to>\Arctic.jar | findstr /i "JNativeHook.dll"

The path com/github/kwhat/jnativehook/lib/windows/arm64/JNativeHook.dll must appear.

Troubleshooting (ARM64 build)

Error Fix
Cannot create generator "Visual Studio 17 2022" Run where cmake. Place native Windows CMake ahead of Cygwin/MSYS2 on PATH, then recheck cmake --help.
Visual Studio instance, ARM64 compiler or SDK not found Open Visual Studio Installer, modify Build Tools, and add C++ ARM64/ARM64EC build tools and a Windows SDK.
src/external/libuiohook has no CMakeLists.txt The submodule was not initialised. Repeat the git submodule init / git config / git submodule update sequence from Step A.
Cannot open com_github_kwhat_jnativehook_GlobalScreen.h Run mvn compile, verify the header exists under target\include\, and confirm the target_include_directories edit in CMakeLists.txt was applied.
JNI or Java include path not found Confirm JAVA_HOME points to a full ARM64 JDK (not a JRE), then rerun the Step D CMake configure command.
Extra path warning about blank character Remove non-breaking spaces from pasted commands.
Section 3: Configuration

In order to successfully "Record" and "Playback", on some platforms require OS Permission settings to enable screen capture and mouse interaction:

  • MacOS:
    • System Settings -> Privacy and Security -> Accessibility :
      • Add both "Terminal" and "Java" (selecting your jdk Contents/Home/bin/java). Then restart your machine.
Section 4: Recording A Test

Making an Arctic recording

  1. Start "Test case" and ensure in center of the screen. Note: If you are running tests using the JTharness on Windows, that you can ensure repeatable ordered test execution for multi-tests by specifying the JVM system property -Dmultitest.testcaseOrder=sorted
  2. Start Arctic "recorder" CLI
java -jar build/jars/Arctic.jar -r
  1. The first time this is run it will just generate the "recording.properties" file, edit this to adjust these recommended values:
arctic.common.repository.json.path = ./arctic_tests
arctic.recorder.pre.init.timings.startDelayMs = 500
arctic.recorder.pre.init.timings.scDelayMs = 500
arctic.recorder.pre.firstSc.delay = 500

NOTE: If running from a Mac, you will probably need to change the Arctic "modifier" keys to avoid clash with Mac's suspend process cmd, eg. change to "Ctrl-Shift" (keys ref: https://github.com/kwhat/jnativehook/blob/2.2/src/main/java/com/github/kwhat/jnativehook/keyboard/NativeKeyEvent.java):

# Ctrl-Shift
arctic.recorder.control.jnh.modifiers = 29, 42

then re-run to actually start recording

  1. Workbench window should now have been opened and sent to "background" behind your test case
  2. Move "Shade" to the side out of "Workbench"
  3. Tell Arctic CLI the group and test case name : test start mytests test1
  4. Select Arctic "workbench" window as focus
  5. Start recording : <Modifiers>-Z
  6. Interact with test case and take screen shots at appropriate check points... : <Modifiers>-X
  7. On completion of interaction, stop recording : <Modifiers>-Z
  8. Quit Arctic recorder CLI : "Quit"
  9. The recordings will be saved under: ./arctic_tests/default/<group_name>/<test_name>
Section 5: Playing Back A Test Manually (non-RMI mode)
  1. Start "Test case" initial window and ensure in center of the screen
  2. Start Arctic "player" CLI
java -Darctic.logLevel=TRACE -jar build/jars/Arctic.jar -p
  1. The first time this is run it will just generate the "player.properties" file, edit this to adjust these recommended values:
arctic.common.repository.json.path = ./arctic_tests
# Some slower systems need lower strict pixel confidence
arctic.player.backend.sc.pixel.confidence.min = 0.5
# Fuzzy check RGB component tolerance needs relaxing slightly to be reliable
arctic.player.backend.sc.pixel.fuzzy.tolerance = 12
# Screenshot delays need slight increase for slower systems
arctic.player.pre.firstTestDelay.wait = 500
arctic.player.pre.scValidator.wait.focus = 500

then re-run to actually start playback

  1. Workbench window should now have been opened and sent to "background" behind your test case
  2. Tell Arctic CLI to start "playing" your group and test case : test start mytests test1
  3. Arctic will now interact in "real time" with the test case window using the recordings and verify the screenshots
  4. If all is successful Arctic CLI will output the following. "Unconfirmed" means no manual human check has been performed on the playback:
FINISHED: mytests:test1 with UNCONFIRMED
  1. To manually confirm the test run, type command:
test finish mytests test1 true
  1. If some error/failure/missmatch has occurred during playback message like the following will appear:
FINISHED: mytests:test1 with ABORTED

In this situation you can debug the problem using the "sc review" command in the CLI, this will open the failed screen review window, pressing the ">>" icon repeatedly can be used to visually see what differs between the "current" image and the "recorded" image. If the additional bottom left checkboxes are enabled, you can view the "strict/fuzzy/cluster" difference images which will show the areas that fail the "strict/fuzzy/cluster" comparison, the top row checkboxes can also be enabled to show "strict/fuzzy/cluster" "hints":

Screenshot 2025-03-19 at 10 00 52

  1. Quit Arctic recorder CLI : "Quit"
  2. The failed playback images are saved to folder failures/mytests/test1
Section 6: Playing Back A Test via Scripting or RMI mode

Automated Arctic Playback

The Arctic CLI can be started in local RMI mode using local loopback RMI, this enables CLI commands to be posted via RMI to the CLI.

To enable RMI local mode only:

  1. Edit player.properties:
arctic.common.repository.json.path = ./arctic_tests
arctic.common.cmd.rmi.enabled = local_only
arctic.common.cmd.console.enabled = false  # NOTE: missing ".enabled" in default property name!
arctic.player.confirmation.mode = false    # Test passes after successful playback without need for manual "confirmation"

arctic.player.confirmation.mode must be "false" if no async confirmation detection is being performed, ie. Arctic post-processing will commence after the playback has completed with status being "UNCONFIRMED".

arctic.player.confirmation.mode must be "true" if async confirmation detection is being performed, eg. via a test harness "observer" which sends a "test finish" command. Arctic processing will remain "RUNNING"/"STARTING" until async observer confirmation has been received, after which the status will become "CONFIRMED" and post-processing then completes.

  1. Script to playback an example "mytests/test1":
testgroup="mytests"
testcase="test1"

echo "Starting player in background with RMI..."
java -Darctic.logLevel=TRACE -jar build/jars/Arctic.jar -p &
rc=$?
if [[ $rc -ne 0 ]]; then
   echo "Unable to start Arctic player, rc=$rc"
   exit $rc
fi

# Allow 3 seconds for RMI server to start...
sleep 3

java -jar build/jars/Arctic.jar -c test start "${testgroup}" "${testcase}"
rc=$?
if [[ $rc -ne 0 ]]; then
   echo "Unable to start playback for testcase ${testgroup}/${testcase}, rc=$rc"
   exit $rc
fi

sleep 3
result=$(java -jar build/jars/Arctic.jar -c test list ${testgroup}/${testcase})
rc=$?
status=$(echo $result | tr -s ' ' | cut -d' ' -f2)
echo "==>" $status
while [[ $rc -eq 0 ]] && { [[ "$status" == "RUNNING" ]] || [[ "$status" == "STARTING" ]]; };
do
  sleep 3
  result=$(java -jar build/jars/Arctic.jar -c test list ${testgroup}/${testcase})
  rc=$?
  status=$(echo $result | tr -s ' ' | cut -d' ' -f2)
  echo "==>" $status
done

echo "Terminating Arctic CLI..."
java -jar build/jars/Arctic.jar -c terminate

echo "Completed playback of ${testgroup}/${testcase} status: ${status}"
Section 7: Troubleshooting Tips & Tricks

Some useful tips:

  1. Debugging can be controlled by passing property "-Darctic.logLevel=TRACE|DEBUG" to the java process. Log output will then output to the Java process stdout/err.
  2. Make sure recording and playback processes are using the same version of Java, otherwise image encoding may differ.
  3. Display settings need to match between recording and playback, eg. screen size and OS visual enhancements, for example:
    • On MacOS, disable "True Tone"
  4. VNC session "mouse pointer" can cause failures due to mouse artifact in the recording, seems intermittent, just re-record when it happens.
  5. On "Linux" intermittent X11 AWT "hangs" are seen during playback when "re-size" window operations are recorded, ie. right-click on resize title bar icon & drag operations. So avoid re-sizing windows on Linux recordings, try and use original window size.
⚠️ **GitHub.com Fallback** ⚠️