name: Tests

on:
  pull_request:

  push:
    branches:
      - main

jobs:
  test:
    name: Run tests

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

    strategy:
      fail-fast: false

      matrix:
        os: [ubuntu-20.04]
        python-version: ["3.8", "3.12"]
        backend: [numpy, jax]

    env:
      PYOM2_DIR: /home/runner/pyom2
      PETSC_VERSION: "3.20.0"
      PETSC_DIR: /home/runner/petsc
      PETSC_ARCH: arch-linux-c-opt
      OMPI_MCA_rmaps_base_oversubscribe: "1"
      OMPI_MCA_mpi_yield_when_idle: "1"
      VEROS_REQUIRE_CYTHON_EXT: "1"

    steps:
      - uses: actions/checkout@v2

      # make sure tags are fetched so we can get a version
      - run: git fetch --prune --unshallow --tags

      - name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}

      - name: Restore pip cache
        uses: actions/cache@v2
        id: pip-cache
        with:
          path: ~/.cache/pip
          key: ${{ matrix.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/requirements*.txt') }}
          restore-keys: |
            ${{ matrix.os }}-pip-${{ matrix.python-version }}-

      - name: Restore PyOM2 build cache
        uses: actions/cache@v2
        id: pyom2-cache
        with:
          path: ${{ env.PYOM2_DIR }}/py_src/*.so
          key: ${{ matrix.os }}-${{ matrix.python-version }}-${{ hashFiles('vendor/pyom2/**/*') }}-${{ hashFiles('requirements.txt') }}

      - name: Restore PETSc build cache
        uses: actions/cache@v2
        id: petsc-cache
        with:
          path: ${{ env.PETSC_DIR }}
          key: ${{ matrix.os }}-${{ env.PETSC_VERSION }}

      - name: Setup Python environment
        run: |
          python -m pip install --upgrade pip
          pip install setuptools wheel
          pip install cython

      - name: Install system requirements
        run: |
          sudo apt-get update
          sudo apt-get install libopenmpi-dev liblapack-dev libblas-dev

      - name: Build PETSc
        if: steps.petsc-cache.outputs.cache-hit != 'true'
        run: |
          git clone -b v$PETSC_VERSION --depth 1 https://gitlab.com/petsc/petsc.git $PETSC_DIR
          pushd $PETSC_DIR
          ./configure --with-debugging=0 -with-shared-libraries --with-precision=double
          make all
          popd

      - name: Install Veros
        run: |
          pip install mpi4py
          if [ ${{ matrix.backend }} == "jax" ]
          then
            pip install mpi4jax
            pip install -e .[test,jax]
          else
            pip install -e .[test]
          fi
          pip install petsc4py==$PETSC_VERSION --no-deps --no-build-isolation

      # Build PyOM2 after Veros to make sure we have compatible versions of NumPy / f2py
      - name: Build PyOM2
        if: steps.pyom2-cache.outputs.cache-hit != 'true'
        run: |
          mkdir -p $PYOM2_DIR
          cp -r vendor/pyom2/* $PYOM2_DIR
          pushd $PYOM2_DIR
          if [ ${{ matrix.python-version }} == "3.8" ]
          then
            mv pyOM2_site_specific_distutils site_specific.mk_
          else
            pip install meson ninja
            mv pyOM2_site_specific_meson site_specific.mk_
          fi
          tar xzf pyOM2.1.0.tar.gz
          git init
          for patchfile in ./patches/*.patch; do
            git apply --whitespace=fix $patchfile
          done
          make -C py_src -j 4
          popd

      - name: Export paths
        run: |
          echo "PYOM2_LIB=$(readlink -f $PYOM2_DIR/py_src/pyOM_code.*.so)" >> $GITHUB_ENV
          echo "PYOM2_LIB_MPI=$(readlink -f $PYOM2_DIR/py_src/pyOM_code_MPI.*.so)" >> $GITHUB_ENV

      - name: Run tests
        run: |
          pytest . -v --cov --pyom2-lib $PYOM2_LIB --backend ${{ matrix.backend }}

      - name: Upload coverage
        uses: codecov/codecov-action@v1
