Skip to content

feat(legal): license #126

feat(legal): license

feat(legal): license #126

Workflow file for this run

name: Tests
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
# Unit tests - stub-based, platform-independent (run on Linux only for speed)
unit-tests:
name: Unit Tests (Stub-based)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential nlohmann-json3-dev
- name: Configure CMake
working-directory: tests
run: |
# Use system-installed nlohmann-json
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DNLOHMANN_JSON_DIR=/usr/include
- name: Build tests
working-directory: tests
run: cmake --build build --config Release
- name: Run unit tests
working-directory: tests
run: ./build/TestRunner --success
# Sanitizer tests - Linux only (ASan + UBSan + LeakSan)
# macOS ARM has limited sanitizer support, Linux catches same bugs
sanitizer-tests:
name: Sanitizer Tests (ASan + UBSan + LeakSan)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential nlohmann-json3-dev
- name: Configure CMake with sanitizers
working-directory: tests
run: |
cmake -S . -B build_san \
-DCMAKE_BUILD_TYPE=Debug \
-DLLOYAL_ENABLE_SANITIZERS=ON \
-DNLOHMANN_JSON_DIR=/usr/include
- name: Build tests with sanitizers
working-directory: tests
run: cmake --build build_san --config Debug
- name: Run tests with ASan + UBSan + LeakSan
working-directory: tests
env:
ASAN_OPTIONS: detect_leaks=1
run: |
set -o pipefail
echo "Running with AddressSanitizer, UBSan, Integer, Float, and LeakSanitizer..."
./build_san/TestRunner --success 2>&1 | tee sanitizer_output.txt
# Check for any runtime errors (warnings are ok, errors are not)
if grep -q "ERROR: " sanitizer_output.txt; then
echo "❌ Sanitizer found errors!"
exit 1
fi
echo "✅ No sanitizer errors"
integration-tests:
name: Integration Tests (Linux)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential nlohmann-json3-dev
- name: Read llama.cpp version
id: llama_version
run: |
LLAMA_VERSION=$(grep -v '^#' .llama-cpp-version | head -n1 | tr -d '[:space:]')
echo "version=$LLAMA_VERSION" >> $GITHUB_OUTPUT
echo "Using llama.cpp version: $LLAMA_VERSION"
- name: Checkout llama.cpp
run: |
git clone --depth 1 --branch ${{ steps.llama_version.outputs.version }} https://github.com/ggml-org/llama.cpp
echo "Checked out llama.cpp at:"
cd llama.cpp && git log -1 --oneline
- name: Cache llama.cpp build
uses: actions/cache@v4
with:
path: llama.cpp/build
key: llama-linux-${{ runner.arch }}-${{ steps.llama_version.outputs.version }}
restore-keys: |
llama-linux-${{ runner.arch }}-
- name: Build llama.cpp
run: |
chmod +x .github/scripts/build-llama.sh
LLAMA_DIR=llama.cpp .github/scripts/build-llama.sh
- name: Cache test models
uses: actions/cache@v4
with:
path: tests/fixtures
key: test-models-v2-${{ hashFiles('.github/workflows/tests.yml') }}
restore-keys: |
test-models-v2-
- name: Download test models
working-directory: tests
run: |
mkdir -p fixtures
# Download SmolLM2-1.7B (1GB) for all integration tests
if [ ! -f fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf ]; then
echo "Downloading SmolLM2-1.7B-Instruct-Q4_K_M.gguf (1GB)..."
curl -fsSL --retry 3 --retry-delay 2 \
"https://huggingface.co/HuggingFaceTB/SmolLM2-1.7B-Instruct-GGUF/resolve/main/smollm2-1.7b-instruct-q4_k_m.gguf" \
-o fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf
echo "Verifying SmolLM2-1.7B-Instruct-Q4_K_M.gguf..."
if ! head -c 4 fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf | grep -q "GGUF"; then
echo "ERROR: Downloaded file is not a valid GGUF file"
head -c 32 fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf | xxd
rm -f fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf
exit 1
fi
echo "✓ SmolLM2-1.7B-Instruct-Q4_K_M.gguf verified"
else
echo "✓ Using cached SmolLM2-1.7B-Instruct-Q4_K_M.gguf"
fi
# Download nomic-embed-text-v1.5 (67MB) for embedding tests
if [ ! -f fixtures/nomic-embed-text-v1.5.Q4_K_M.gguf ]; then
echo "Downloading nomic-embed-text-v1.5.Q4_K_M.gguf (67MB)..."
curl -fsSL --retry 3 --retry-delay 2 \
"https://huggingface.co/nomic-ai/nomic-embed-text-v1.5-GGUF/resolve/main/nomic-embed-text-v1.5.Q4_K_M.gguf" \
-o fixtures/nomic-embed-text-v1.5.Q4_K_M.gguf
echo "Verifying nomic-embed-text-v1.5.Q4_K_M.gguf..."
if ! head -c 4 fixtures/nomic-embed-text-v1.5.Q4_K_M.gguf | grep -q "GGUF"; then
echo "ERROR: Downloaded file is not a valid GGUF file"
head -c 32 fixtures/nomic-embed-text-v1.5.Q4_K_M.gguf | xxd
rm -f fixtures/nomic-embed-text-v1.5.Q4_K_M.gguf
exit 1
fi
echo "✓ nomic-embed-text-v1.5.Q4_K_M.gguf verified"
else
echo "✓ Using cached nomic-embed-text-v1.5.Q4_K_M.gguf"
fi
echo "All test models ready"
- name: Configure CMake for integration tests
working-directory: tests
run: |
cmake -S . -B build_integration \
-DLLOYAL_BUILD_INTEGRATION_TESTS=ON \
-DLLAMA_CPP_DIR=${{ github.workspace }}/llama.cpp \
-DNLOHMANN_JSON_DIR=/usr/include \
-DCMAKE_BUILD_TYPE=Release
- name: Build integration tests
working-directory: tests
run: cmake --build build_integration --config Release
- name: Run integration tests
working-directory: tests
env:
LLAMA_TEST_MODEL: ${{ github.workspace }}/tests/fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf
run: |
set -o pipefail
echo "Running integration tests with SmolLM2-1.7B..."
echo "Model path: $LLAMA_TEST_MODEL"
ls -lh "$LLAMA_TEST_MODEL"
./build_integration/IntegrationRunner --success \
--test-case-exclude="*Embedding*" 2>&1 | tee test_output.txt
# Fail if no tests actually executed (all filtered/skipped)
if grep -qE "test cases:.*\| 0 passed \| 0 failed \|" test_output.txt; then
echo "::error::No tests executed — all were skipped or filtered out"
exit 1
fi
- name: Run embedding tests
working-directory: tests
env:
LLAMA_TEST_MODEL: ${{ github.workspace }}/tests/fixtures/SmolLM2-1.7B-Instruct-Q4_K_M.gguf
LLAMA_EMBED_MODEL: ${{ github.workspace }}/tests/fixtures/nomic-embed-text-v1.5.Q4_K_M.gguf
run: |
set -o pipefail
echo "Running embedding tests with nomic-embed-text-v1.5..."
echo "Embed model path: $LLAMA_EMBED_MODEL"
ls -lh "$LLAMA_EMBED_MODEL"
./build_integration/IntegrationRunner --success \
--test-case="*Embedding*" 2>&1 | tee test_output.txt
# Fail if no tests actually executed (all filtered/skipped)
if grep -qE "test cases:.*\| 0 passed \| 0 failed \|" test_output.txt; then
echo "::error::No tests executed — all were skipped or filtered out"
exit 1
fi
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: integration-test-results-macos
path: tests/build_integration/
lint:
name: Code Style Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install clang-format
run: sudo apt-get update && sudo apt-get install -y clang-format
- name: Check formatting
run: |
# Exclude build artifacts from formatting checks
find include/ tests/ \( -name '*.hpp' -o -name '*.cpp' \) \
-not -path '*/build/*' \
-not -path '*/build_*/*' \
-not -path '*/_deps/*' \
-not -path '*/lib/*' \
-exec clang-format --dry-run --Werror {} \; || exit 1
summary:
name: Test Summary
runs-on: ubuntu-latest
needs: [unit-tests, sanitizer-tests, integration-tests, lint]
if: always()
steps:
- name: Check test results
run: |
echo "=== Test Results ==="
echo "Unit Tests: ${{ needs.unit-tests.result }}"
echo "Sanitizer Tests: ${{ needs.sanitizer-tests.result }}"
echo "Integration Tests (Linux): ${{ needs.integration-tests.result }}"
echo "Lint: ${{ needs.lint.result }}"
FAILED=0
if [ "${{ needs.unit-tests.result }}" != "success" ]; then
echo "❌ Unit tests failed"
FAILED=1
fi
if [ "${{ needs.sanitizer-tests.result }}" != "success" ]; then
echo "❌ Sanitizer tests failed (memory bugs, UB, leaks, or overflow detected)"
FAILED=1
fi
if [ "${{ needs.integration-tests.result }}" != "success" ]; then
echo "❌ Integration tests failed"
FAILED=1
fi
if [ "${{ needs.lint.result }}" != "success" ]; then
echo "❌ Lint failed (code style issues)"
FAILED=1
fi
if [ "$FAILED" = "1" ]; then
exit 1
else
echo "✅ All tests passed"
fi