Arctic Project Guide - adoptium/aqa-tests GitHub Wiki
Section 1: Introduction
Some Text To Go Here!
Section 2: Installation
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.
- A Git client installed on your system.
- Administrative privileges (where necessary).
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 arcticThis command downloads the repository and navigates into the arctic directory.
The Temurin JDK 17 binary needs to be installed for your platform. Below are instructions for Linux, Windows, and macOS.
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-jdk17Invoke-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"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-jdk17In the shell, set the environment variables for JAVA_HOME & PATH
export JAVA_HOME=$(pwd)/temurin-jdk17
export PATH=$JAVA_HOME/bin:$PATHApply the changes:
source ~/.bashrc # or source ~/.zshrc$env:JAVA_HOME = "$(Get-Location)\temurin-jdk17"
$env:Path += ";$env:JAVA_HOME\bin"To make these changes permanent, update the system environment variables manually:
- Open System Properties > Advanced > Environment Variables.
- Add a new variable
JAVA_HOMEpointing to the extractedtemurin-jdk17folder. - Append
%JAVA_HOME%\binto thePathvariable.
Confirm that the correct JDK version is installed:
java -versionThe output should indicate JDK 17 from Eclipse Temurin:
openjdk version "17.0.x" 202x-xx-xx
Navigate to the project root directory:
cd .. # Move to the project rootRun the Gradle build command:
./gradlew build # Linux/macOS.\gradlew.bat build # WindowsThis will download dependencies and build the project.
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.
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.
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%"mkdir C:\arctic-dev\jnativehook
cd /d C:\arctic-dev\jnativehook
git clone --branch 2.2 https://github.com/kwhat/jnativehook.git
cd jnativehookInitialise 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 --recursiveVerify the submodule is present:
dir src\external\libuiohook\CMakeLists.txtUse 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.
mvn clean compileConfirm the generated header exists:
dir target\include\com_github_kwhat_jnativehook_GlobalScreen.hEdit 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 cleanagain after this point. It deletestarget\, removing the native build outputs and generated JNI headers. Usemvn compileif you only need to regenerate headers.
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 RelWithDebInfoThis compiles libuiohook as a static library that will be linked into 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 RelWithDebInfoThe 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
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
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.
| 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.
- System Settings -> Privacy and Security -> Accessibility :
Section 4: Recording A Test
- 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 - Start Arctic "recorder" CLI
java -jar build/jars/Arctic.jar -r- 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 = 500NOTE: 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, 42then re-run to actually start recording
- Workbench window should now have been opened and sent to "background" behind your test case
- Move "Shade" to the side out of "Workbench"
- Tell Arctic CLI the group and test case name : test start mytests test1
- Select Arctic "workbench" window as focus
- Start recording : <Modifiers>-Z
- Interact with test case and take screen shots at appropriate check points... : <Modifiers>-X
- On completion of interaction, stop recording : <Modifiers>-Z
- Quit Arctic recorder CLI : "Quit"
- The recordings will be saved under:
./arctic_tests/default/<group_name>/<test_name>
Section 5: Playing Back A Test Manually (non-RMI mode)
- Start "Test case" initial window and ensure in center of the screen
- Start Arctic "player" CLI
java -Darctic.logLevel=TRACE -jar build/jars/Arctic.jar -p- 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 = 500then re-run to actually start playback
- Workbench window should now have been opened and sent to "background" behind your test case
- Tell Arctic CLI to start "playing" your group and test case : test start mytests test1
- Arctic will now interact in "real time" with the test case window using the recordings and verify the screenshots
- 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- To manually confirm the test run, type command:
test finish mytests test1 true- If some error/failure/missmatch has occurred during playback message like the following will appear:
FINISHED: mytests:test1 with ABORTEDIn 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":

- Quit Arctic recorder CLI : "Quit"
- The failed playback images are saved to folder
failures/mytests/test1
Section 6: Playing Back A Test via Scripting or RMI mode
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:
- 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.
- 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:
- 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. - Make sure recording and playback processes are using the same version of Java, otherwise image encoding may differ.
- Display settings need to match between recording and playback, eg. screen size and OS visual enhancements, for example:
- On MacOS, disable "True Tone"
- VNC session "mouse pointer" can cause failures due to mouse artifact in the recording, seems intermittent, just re-record when it happens.
- 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.