name: Test

on:
  push:
    branches: ["master"]
  pull_request:
    branches: ["master"]

permissions:
  contents: read

jobs:
  unit-test:
    name: "Unit Tests (${{ matrix.os.friendly }})"
    strategy:
      matrix:
        os:
          - runner: "ubuntu-22.04"
            sys: "linux"
            arch: "x64"
            friendly: "Linux"
          - runner: "macos-14"
            sys: "darwin"
            arch: "arm64"
            friendly: "macOS"
          - runner: "windows-2022"
            sys: "windows"
            arch: "x64"
            friendly: "Windows"
      fail-fast: false

    runs-on: ${{ matrix.os.runner }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Install the latest version of uv
        uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
        with:
          python-version: "3.13"
          cache-dependency-glob: "**/*.py.lock"

      - name: Restore cached libclang
        id: cache-libclang-restore
        uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
        with:
          path: lib/libclang
          key: libclang-${{ matrix.os.runner }}-${{ matrix.os.arch }}-${{ hashFiles('scripts/libclang.json') }}

      - name: Download libclang
        if: steps.cache-libclang-restore.outputs.cache-hit != 'true'
        run: uv run scripts/download.py

      - name: Setup Go
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: 1.24
          cache: true

      - name: Setup Cangjie
        uses: Zxilly/setup-cangjie@91463316b1c359f216c2ac49e35900f9341c1571 # v3.2.0
        with:
          channel: "nightly"
          version: "1.1.0-alpha.20260603010036"

      - name: Setup MSYS2
        if: matrix.os.sys == 'windows'
        uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2.31.0
        with:
          msystem: CLANG64
          update: true
          install: >-
            mingw-w64-clang-x86_64-clang
          path-type: inherit

      - name: "Test: cjbind_token"
        run: cjpm test -m cjbind_token -V

      - name: "Test: cjbind (Unix)"
        if: matrix.os.sys != 'windows'
        run: uv run scripts/cjpm.py --static test -m cjbind -V

      - name: "Test: cjbind (Windows)"
        if: matrix.os.sys == 'windows'
        shell: msys2 {0}
        run: uv run python scripts/cjpm.py --static test -m cjbind -V

      - name: Save libclang cache
        if: always() && steps.cache-libclang-restore.outputs.cache-hit != 'true'
        uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
        with:
          key: ${{ steps.cache-libclang-restore.outputs.cache-primary-key }}
          path: lib/libclang

  integration-test:
    name: "Integration Tests (${{ matrix.os.friendly }})"
    strategy:
      matrix:
        os:
          - runner: "ubuntu-22.04"
            sys: "linux"
            arch: "x64"
            friendly: "Linux"
          - runner: "macos-14"
            sys: "darwin"
            arch: "arm64"
            friendly: "macOS"
          - runner: "windows-2022"
            sys: "windows"
            arch: "x64"
            friendly: "Windows"
      fail-fast: false

    runs-on: ${{ matrix.os.runner }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

      - name: Install the latest version of uv
        uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
        with:
          python-version: "3.13"
          cache-dependency-glob: "**/*.py.lock"

      - name: Restore cached libclang
        id: cache-libclang-restore
        uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
        with:
          path: lib/libclang
          key: libclang-${{ matrix.os.runner }}-${{ matrix.os.arch }}-${{ hashFiles('scripts/libclang.json') }}

      - name: Download libclang
        if: steps.cache-libclang-restore.outputs.cache-hit != 'true'
        run: uv run scripts/download.py

      - name: Setup Go
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: 1.24
          cache: true

      - name: Setup Cangjie
        uses: Zxilly/setup-cangjie@91463316b1c359f216c2ac49e35900f9341c1571 # v3.2.0
        with:
          channel: "nightly"
          version: "1.1.0-alpha.20260603010036"

      - name: Setup MSYS2
        if: matrix.os.sys == 'windows'
        uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2.31.0
        with:
          msystem: CLANG64
          update: true
          install: >-
            mingw-w64-clang-x86_64-clang
          path-type: inherit

      - name: "Test: cjbind_test (Unix)"
        if: matrix.os.sys != 'windows'
        run: uv run scripts/cjpm.py --static test -m cjbind_test -V

      - name: "Test: cjbind_test (Windows)"
        if: matrix.os.sys == 'windows'
        shell: msys2 {0}
        run: uv run python scripts/cjpm.py --static test -m cjbind_test -V

      - name: "Smoke: generated bindings compile"
        if: matrix.os.sys == 'linux'
        run: uv run python scripts/compile_generated.py

      - name: Save libclang cache
        if: always() && steps.cache-libclang-restore.outputs.cache-hit != 'true'
        uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
        with:
          key: ${{ steps.cache-libclang-restore.outputs.cache-primary-key }}
          path: lib/libclang