feat(legal): license #126
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |