Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
40 changes: 40 additions & 0 deletions .github/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Runs the Release tests with full optimization, from the repository root.
# DISABLE Comma-separated DOTNET_Enable<name> switches to turn off; Vector512 caps vectors at 256 bits instead.
# SDE_PATH Intel SDE kit; the tests run under "sde64 -spr" when SDE adds instruction sets this runner lacks.
set -eo pipefail

export DOTNET_TieredCompilation=0

for feature in ${DISABLE//,/ }; do
case $feature in
Vector512) export DOTNET_PreferredVectorBitWidth=256 ;;
*) export "DOTNET_Enable$feature=0" ;;
esac
done

runner=(dotnet)

if [[ -n $SDE_PATH ]]; then
sde=("$SDE_PATH/sde64" -spr --)
probe=artifacts/bin/InstructionSets/InstructionSets.dll
dotnet build .github/InstructionSets.cs -c Release -o "${probe%/*}" -v q
native=$(dotnet "$probe")
emulated=$(DOTNET_EnableDiagnostics=0 "${sde[@]}" dotnet "$probe")
missing=$(LC_ALL=C comm -13 <(echo "$native") <(echo "$emulated") | paste -sd ' ')
echo "CPU:$(grep -m1 'model name' /proc/cpuinfo | cut -d: -f2); SDE adds: ${missing:-nothing}"

if [[ -n $missing ]]; then
runner=("${sde[@]}" dotnet)
export DOTNET_EnableDiagnostics=0
# SDE loses emulated vector registers across signal handlers:
# https://web.archive.org/web/20260113162404/https://community.intel.com/t5/Intel-ISA-Extensions/SDE-signal-handling-bug/td-p/1646699
# The runtime signals threads to suspend them for GC; make GC wait for them to poll instead.
export DOTNET_INTERNAL_ThreadSuspendInjection=0
# Keep glibc and OpenSSL off emulated AVX-512, which is slow and exposed to the same bug.
export GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX512F,-AVX512VL,-AVX512BW,-AVX512DQ,-AVX512CD
export OPENSSL_ia32cap=:~0x600C0230000
fi
fi

"${runner[@]}" artifacts/bin/CryptoBase.Tests/release/CryptoBase.Tests.dll --minimum-expected-tests 1
183 changes: 48 additions & 135 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,56 +9,69 @@ on:
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_NOLOGO: 1
DOTNET_GENERATE_ASPNET_CERTIFICATE: false
NET_VERSION: 10.0.x
TUNIT_DISABLE_LOGO: 1

jobs:
check_format:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-dotnet@v6
with:
dotnet-version: ${{ env.NET_VERSION }}

# Test jobs build only the test project, so the whole solution, benchmarks included, is built here.
- name: Build
run: dotnet build -c Release

- name: Check .NET format
run: dotnet format -v diag --verify-no-changes
run: dotnet format --no-restore -v diag --verify-no-changes

test:
name: test (${{ matrix.os }}${{ matrix.disable && format(', no {0}', matrix.disable) }})
runs-on: ${{ matrix.os }}
timeout-minutes: 30
defaults:
run:
shell: bash
working-directory: test/CryptoBase.Tests
strategy:
fail-fast: false
matrix:
os:
- windows-latest
- macos-latest
include:
- os: ubuntu-latest
- os: ubuntu-latest
disable: AVX512v2
- os: ubuntu-latest
disable: AVX512
- os: ubuntu-latest
disable: VAES
- os: ubuntu-latest
disable: GFNI
- os: ubuntu-latest
disable: AVX2
- os: ubuntu-latest
disable: AVX
- os: ubuntu-latest
disable: SSE42
- os: ubuntu-latest
disable: AES
- os: ubuntu-latest
disable: HWIntrinsic
# Linux x64 covers every x86 instruction-set level, under Intel SDE where the runner lacks one (see test.sh).
- { os: ubuntu-latest }
- { os: ubuntu-latest, disable: AVX512v2 }
- { os: ubuntu-latest, disable: Vector512 }
- { os: ubuntu-latest, disable: VAES }
- { os: ubuntu-latest, disable: GFNI }
- { os: ubuntu-latest, disable: AVX512 }
- { os: ubuntu-latest, disable: 'AVX512,GFNI,VAES' }
- { os: ubuntu-latest, disable: AVX2 }
- { os: ubuntu-latest, disable: AVX }
- { os: ubuntu-latest, disable: SSE42 }
- { os: ubuntu-latest, disable: AES }
- { os: ubuntu-latest, disable: HWIntrinsic }
# Linux ARM64 covers the ARM64 switches.
- { os: ubuntu-26.04-arm }
- { os: ubuntu-26.04-arm, disable: Arm64Aes }
- { os: ubuntu-26.04-arm, disable: Arm64Crc32 }
- { os: ubuntu-26.04-arm, disable: Arm64Sha1 }
- { os: ubuntu-26.04-arm, disable: Arm64Sha256 }
- { os: ubuntu-26.04-arm, disable: HWIntrinsic }
# Other platforms: default dispatch and the portable path.
- { os: windows-latest }
- { os: windows-latest, disable: HWIntrinsic }
- { os: macos-latest }

steps:
- uses: actions/checkout@v7
Expand All @@ -68,120 +81,20 @@ jobs:
with:
dotnet-version: ${{ env.NET_VERSION }}
- uses: petarpetrovt/setup-sde@v6.0
if: runner.os == 'Linux' && matrix.disable != 'HWIntrinsic'

- name: Build (Release)
working-directory: .
run: dotnet build -c Release
if: runner.os == 'Linux' && runner.arch == 'X64'

- name: Build instruction set probe
if: runner.os == 'Linux' && matrix.disable != 'HWIntrinsic'
run: dotnet build ../../.github/InstructionSets.cs -c Release -o ../../artifacts/bin/InstructionSets
- name: Build
run: dotnet build test/CryptoBase.Tests -c Release

- name: Run tests (Release)
if: ${{ !matrix.disable }}
run: &run-tests |
export DOTNET_TieredCompilation=0
test_runner=(dotnet)
if [[ -n "${SDE_PATH:-}" && "${DOTNET_EnableHWIntrinsic:-1}" != 0 ]]; then
probe=../../artifacts/bin/InstructionSets/InstructionSets.dll
native=$(dotnet "$probe")
emulated=$(DOTNET_EnableDiagnostics=0 "$SDE_PATH/sde64" -spr -- dotnet "$probe")
missing=$(LC_ALL=C comm -13 <(printf '%s\n' "$native") <(printf '%s\n' "$emulated") | paste -sd,)
if [[ -n "$missing" ]]; then
test_runner=("$SDE_PATH/sde64" -spr -- dotnet)
export DOTNET_EnableDiagnostics=0
echo "Runner: SDE; missing: ${missing//,/, }"
else
echo "Runner: native"
fi
else
echo "Runner: native"
fi
"${test_runner[@]}" ../../artifacts/bin/CryptoBase.Tests/release/CryptoBase.Tests.dll --disable-logo --minimum-expected-tests 1
- name: Test (Release)
run: bash .github/test.sh
env:
DISABLE: ${{ matrix.disable }}

- name: Run tests (Release, tiered compilation)
- name: Test (Release, tiered compilation)
if: ${{ !matrix.disable }}
run: dotnet ../../artifacts/bin/CryptoBase.Tests/release/CryptoBase.Tests.dll --disable-logo --minimum-expected-tests 1
run: dotnet artifacts/bin/CryptoBase.Tests/release/CryptoBase.Tests.dll --minimum-expected-tests 1

- name: Run tests (Debug)
- name: Test (Debug)
if: ${{ !matrix.disable }}
run: dotnet test -c Debug --no-restore --disable-logo --minimum-expected-tests 1

- name: Run tests (Disable AVX512v2)
if: matrix.os == 'windows-latest' || matrix.disable == 'AVX512v2'
run: *run-tests
env:
DOTNET_EnableAVX512v2: 0

- name: Run tests (Disable AVX512)
if: matrix.os == 'windows-latest' || matrix.disable == 'AVX512'
run: *run-tests
env:
DOTNET_EnableAVX512: 0

- name: Run tests (Disable VAES)
if: matrix.os == 'windows-latest' || matrix.disable == 'VAES'
run: *run-tests
env:
DOTNET_EnableVAES: 0

- name: Run tests (Disable GFNI)
if: matrix.os == 'windows-latest' || matrix.disable == 'GFNI'
run: *run-tests
env:
DOTNET_EnableGFNI: 0

- name: Run tests (Disable AVX2)
if: matrix.os == 'windows-latest' || matrix.disable == 'AVX2'
run: *run-tests
env:
DOTNET_EnableAVX2: 0

- name: Run tests (Disable AVX)
if: matrix.os == 'windows-latest' || matrix.disable == 'AVX'
run: *run-tests
env:
DOTNET_EnableAVX: 0

- name: Run tests (Disable x86-64-v2 intrinsics)
if: matrix.os == 'windows-latest' || matrix.disable == 'SSE42'
run: *run-tests
env:
DOTNET_EnableSSE42: 0

- name: Run tests (Disable AES)
if: matrix.os == 'windows-latest' || matrix.disable == 'AES'
run: *run-tests
env:
DOTNET_EnableAES: 0

- name: Run tests (Disable ARM64 AES)
if: matrix.os == 'macos-latest'
run: *run-tests
env:
DOTNET_EnableArm64Aes: 0

- name: Run tests (Disable ARM64 CRC32)
if: matrix.os == 'macos-latest'
run: *run-tests
env:
DOTNET_EnableArm64Crc32: 0

- name: Run tests (Disable ARM64 SHA1)
if: matrix.os == 'macos-latest'
run: *run-tests
env:
DOTNET_EnableArm64Sha1: 0

- name: Run tests (Disable ARM64 SHA256)
if: matrix.os == 'macos-latest'
run: *run-tests
env:
DOTNET_EnableArm64Sha256: 0

- name: Run tests (Disable HWIntrinsic)
if: runner.os != 'Linux' || matrix.disable == 'HWIntrinsic'
run: *run-tests
env:
DOTNET_EnableHWIntrinsic: 0
run: dotnet test --project test/CryptoBase.Tests -c Debug --minimum-expected-tests 1
2 changes: 2 additions & 0 deletions CryptoBase.slnx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<Solution>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
<File Path=".gitattributes" />
<File Path=".gitignore" />
<File Path="Directory.Build.props" />
<File Path="LICENSE" />
<File Path="NuGet.Config" />
<File Path="README.md" />
<File Path=".github\renovate.json" />
<File Path=".github\test.sh" />
<File Path=".github\workflows\CI.yml" />
<File Path=".github\workflows\release.yml" />
<File Path="Directory.Packages.props" />
Expand Down
Loading