3131env :
3232 # Specify build type either according to the tag release or manual override
3333 BUILD_TYPE : ${{ inputs.buildType != '' && inputs.buildType || startsWith(github.ref, 'refs/tags') && 'Release' || 'Debug' }}
34- CTEST_PARALLEL_LEVEL : 40
3534
3635jobs :
3736 Windows :
@@ -129,6 +128,12 @@ jobs:
129128 steps :
130129 - uses : actions/checkout@v4
131130
131+ - name : ' Determine test parallelism'
132+ shell : pwsh
133+ run : |
134+ "CTEST_PARALLEL_LEVEL=$([Environment]::ProcessorCount)" |
135+ Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
136+
132137 - name : ' 🛠️ Win MINGW setup'
133138 if : contains(matrix.config.mingw, 'MINGW')
134139 uses : msys2/setup-msys2@v2
@@ -168,7 +173,7 @@ jobs:
168173 -DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
169174 cmake --build . --config ${{ env.BUILD_TYPE }}
170175 cmake --install . --strip --config ${{ env.BUILD_TYPE }}
171- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
176+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
172177 # vctip.exe (MSVC telemetry) and antivirus scans may transiently hold
173178 # handles inside the build directory and make the rename fail, so
174179 # retry for a while, killing vctip on each attempt
@@ -204,7 +209,7 @@ jobs:
204209 -DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
205210 cmake --build . --config ${{ env.BUILD_TYPE }}
206211 cmake --install . --strip --config ${{ env.BUILD_TYPE }}
207- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
212+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
208213 # vctip.exe (MSVC telemetry) and antivirus scans may transiently hold
209214 # handles inside the build directory and make the rename fail, so
210215 # retry for a while, killing vctip on each attempt
@@ -242,7 +247,7 @@ jobs:
242247 -DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
243248 cmake --build . --config ${{ env.BUILD_TYPE }}
244249 cmake --install . --strip
245- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
250+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
246251
247252 - name : ' 📦 Pack artifact'
248253 if : always()
@@ -331,6 +336,9 @@ jobs:
331336 compiler : [ gcc ]
332337 steps :
333338 - uses : actions/checkout@v4
339+ - name : ' Determine test parallelism'
340+ shell : bash
341+ run : echo "CTEST_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu)" >> "$GITHUB_ENV"
334342 - name : ' 🚧 Mac build'
335343 if : contains(matrix.config.name, 'macos')
336344 shell : bash
@@ -350,7 +358,7 @@ jobs:
350358 -DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
351359 cmake --build . --config ${{ env.BUILD_TYPE }}
352360 cmake --install . --strip
353- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
361+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
354362
355363 - name : ' 🚧 Android x86_64 build'
356364 if : contains(matrix.config.name, 'android')
@@ -499,6 +507,9 @@ jobs:
499507 compiler : [ gcc ]
500508 steps :
501509 - uses : actions/checkout@v4
510+ - name : ' Determine test parallelism'
511+ shell : bash
512+ run : echo "CTEST_PARALLEL_LEVEL=$(getconf _NPROCESSORS_ONLN)" >> "$GITHUB_ENV"
502513 - name : ' 🚧 Linux x64/x86 build'
503514 if : contains(matrix.config.arch, 'x64') || contains(matrix.config.arch, 'x86')
504515 shell : bash
@@ -524,7 +535,7 @@ jobs:
524535 -DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
525536 cmake --build . --config ${{ env.BUILD_TYPE }}
526537 cmake --install . --strip
527- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
538+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
528539
529540 - name : ' 🚧 Linux aarch64 build'
530541 if : contains(matrix.config.arch, 'aarch64')
@@ -542,7 +553,7 @@ jobs:
542553 -DCMAKE_INSTALL_PREFIX:PATH=instdir
543554 cmake --build . --config ${{ env.BUILD_TYPE }}
544555 cmake --install . --strip
545- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
556+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
546557
547558 - name : ' 🚧 Linux ppc64le build'
548559 if : contains(matrix.config.arch, 'ppc64le')
@@ -568,7 +579,7 @@ jobs:
568579 -DCMAKE_INSTALL_PREFIX:PATH=/instdir
569580 cmake --build . --config ${{ env.BUILD_TYPE }}
570581 cmake --install . --strip
571- ctest --parallel ${{ env.CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
582+ ctest --parallel "$(getconf _NPROCESSORS_ONLN)" --output-on-failure -C ${{ env.BUILD_TYPE }}
572583
573584 - name : ' 📦 Pack artifact'
574585 if : always()
@@ -597,6 +608,133 @@ jobs:
597608 compression-level : 0
598609 overwrite : true
599610
611+ PythonRegressions :
612+ if : github.event_name == 'pull_request'
613+ runs-on : ubuntu-latest
614+ name : ' python regressions'
615+ steps :
616+ - uses : actions/checkout@v4
617+ - uses : actions/setup-python@v5
618+ with :
619+ python-version : ' 3.12'
620+ - name : ' Build current Python binding library'
621+ shell : bash
622+ run : |
623+ workers=$(getconf _NPROCESSORS_ONLN)
624+ python_executable=$(python -c 'import sys; print(sys.executable)')
625+ python -m pip install --disable-pip-version-check capstone==6.0.0a2
626+ cmake \
627+ -S . \
628+ -B build-python-regressions \
629+ -G Ninja \
630+ -DCMAKE_BUILD_TYPE=Release \
631+ -DBUILD_SHARED_LIBS=ON \
632+ -DPYTHON_EXECUTABLE="$python_executable" \
633+ -DUNICORN_TEST_PYTHON_REGRESSIONS=ON
634+ cmake --build build-python-regressions \
635+ --target unicorn --parallel "$workers"
636+ ctest \
637+ --test-dir build-python-regressions \
638+ --label-regex python-regression \
639+ --parallel "$workers" \
640+ --no-tests=error \
641+ --output-on-failure
642+
643+ FuzzSanitizers :
644+ if : github.event_name == 'pull_request'
645+ runs-on : ubuntu-latest
646+ name : ' clang asan ubsan libfuzzer'
647+ env :
648+ ASAN_OPTIONS : detect_leaks=1:abort_on_error=1
649+ UBSAN_OPTIONS : halt_on_error=1:print_stacktrace=1
650+ steps :
651+ - uses : actions/checkout@v4
652+ - name : ' Build fuzz targets'
653+ shell : bash
654+ run : |
655+ workers=$(getconf _NPROCESSORS_ONLN)
656+ sanitizer_flags='-fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer'
657+ cmake \
658+ -S . \
659+ -B build-fuzz \
660+ -G Ninja \
661+ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
662+ -DCMAKE_C_COMPILER=clang \
663+ -DCMAKE_C_FLAGS="$sanitizer_flags" \
664+ -DCMAKE_EXE_LINKER_FLAGS='-fsanitize=address,undefined' \
665+ -DCMAKE_SHARED_LINKER_FLAGS='-fsanitize=address,undefined' \
666+ -DUNICORN_BUILD_TESTS=OFF \
667+ -DUNICORN_FUZZ=ON \
668+ -DUNICORN_FUZZ_LIBFUZZER=ON \
669+ -DUNICORN_INSTALL=OFF
670+ cmake --build build-fuzz --parallel "$workers"
671+ - name : ' Run nested timeout sanitizer regression'
672+ shell : bash
673+ run : |
674+ workers=$(getconf _NPROCESSORS_ONLN)
675+ sanitizer_flags='-fsanitize=address,undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer'
676+ cmake \
677+ -S . \
678+ -B build-sanitizer-tests \
679+ -G Ninja \
680+ -DCMAKE_BUILD_TYPE=RelWithDebInfo \
681+ -DCMAKE_C_COMPILER=clang \
682+ -DCMAKE_C_FLAGS="$sanitizer_flags" \
683+ -DCMAKE_EXE_LINKER_FLAGS='-fsanitize=address,undefined' \
684+ -DCMAKE_SHARED_LINKER_FLAGS='-fsanitize=address,undefined' \
685+ -DUNICORN_ARCH=x86 \
686+ -DUNICORN_BUILD_TESTS=ON \
687+ -DUNICORN_FUZZ=OFF \
688+ -DUNICORN_INSTALL=OFF
689+ cmake --build build-sanitizer-tests \
690+ --target test_ctl --parallel "$workers"
691+ ctest \
692+ --test-dir build-sanitizer-tests \
693+ --show-only \
694+ --tests-regex '^unit[.]test_ctl[.]test_uc_nested_timeout$'
695+ timeout --signal=TERM --kill-after=5s 60s ctest \
696+ --test-dir build-sanitizer-tests \
697+ --tests-regex '^unit[.]test_ctl[.]test_uc_nested_timeout$' \
698+ --no-tests=error \
699+ --output-on-failure
700+ - name : ' Run fuzz'
701+ shell : bash
702+ run : |
703+ cp -R tests/fuzz/corpus/fuzz_uc_api build-fuzz/corpus-api
704+ mkdir -p build-fuzz/artifacts
705+ for target_path in build-fuzz/fuzz_emu_*; do
706+ if [ ! -x "$target_path" ]; then
707+ continue
708+ fi
709+ target=$(basename "$target_path")
710+ artifact_dir="build-fuzz/artifacts/$target/"
711+ corpus_dir=$(mktemp -d "build-fuzz/corpus-$target.XXXXXX")
712+ cp -R tests/fuzz/corpus/raw/. "$corpus_dir"
713+ mkdir -p "$artifact_dir"
714+ "$target_path" \
715+ -runs=64 \
716+ -timeout=5 \
717+ -max_len=4096 \
718+ -artifact_prefix="$artifact_dir" \
719+ -dict=tests/fuzz/corpus/fuzz_emu.dict \
720+ "$corpus_dir"
721+ done
722+ mkdir -p build-fuzz/artifacts/fuzz_uc_api
723+ build-fuzz/fuzz_uc_api \
724+ -runs=128 \
725+ -timeout=5 \
726+ -max_len=4096 \
727+ -artifact_prefix=build-fuzz/artifacts/fuzz_uc_api/ \
728+ -dict=tests/fuzz/corpus/fuzz_uc_api.dict \
729+ build-fuzz/corpus-api
730+ - name : ' 📤 Upload fuzz artifacts'
731+ if : failure()
732+ uses : actions/upload-artifact@v4
733+ with :
734+ name : fuzz-sanitizer-artifacts
735+ path : build-fuzz/artifacts
736+ if-no-files-found : ignore
737+
600738 AlpineLinux :
601739 runs-on : ${{ matrix.config.os }}
602740 name : ${{ matrix.config.name }} - ${{ matrix.compiler }}
@@ -662,6 +800,10 @@ jobs:
662800 steps :
663801 - uses : actions/checkout@v4
664802
803+ - name : ' Determine test parallelism'
804+ shell : bash
805+ run : echo "CTEST_PARALLEL_LEVEL=$(getconf _NPROCESSORS_ONLN)" >> "$GITHUB_ENV"
806+
665807 - name : ' Bootstrap Alpine apk-tools'
666808 shell : bash
667809 env :
@@ -715,7 +857,7 @@ jobs:
715857 -DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
716858 cmake --build . --config ${{ env.BUILD_TYPE }}
717859 cmake --install . --strip
718- ctest --parallel ${{ env. CTEST_PARALLEL_LEVEL }} --output-on-failure -C ${{ env.BUILD_TYPE }}
860+ ctest --parallel "$ CTEST_PARALLEL_LEVEL" --output-on-failure -C ${{ env.BUILD_TYPE }}
719861
720862 - name : ' 📦 Pack artifact'
721863 if : always()
0 commit comments