name: C++ Tests

on:
  workflow_call:
    inputs:
      safe-checkout:
        required: true
        description: "The SHA key for the commit we want to run over"
        type: string

jobs:
  linux:
    strategy:
      fail-fast: false   # Don't cancel all jobs if one fails.
      matrix:
        config:
          - { name: Optimized, flags: --config=opt }
          - { name: Debug, flags: --config=dbg }
          - { name: ASAN, flags: --config=asan }
          - { name: MSAN, flags: --config=kokoro-msan }
          - { name: TSAN, flags: --config=tsan }
          - { name: UBSAN, flags: --config=ubsan }
          - { name: No-RTTI, flags: --cxxopt=-fno-rtti }
        include:
          # Set defaults
          - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize@sha256:dbd2f15fb69734d72c3fd10cb819bbe2ce4890acf49e9a2f9403983fe48e8807
          - targets: //pkg/... //src/... @com_google_protobuf_examples//...

          # Override cases with custom images
          - config: { name: "TCMalloc" }
            image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc@sha256:9d975616c3fd44d5a091aeb60ee94f37e22fb367d471d258fc18cb4a2387c943"
            targets: "//src/..."
          - config: { name: "aarch64" }
            targets: "//src/... //src/google/protobuf/compiler:protoc_aarch64_test"
            image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-e863f8ec6b1dfe41f7dc573bac9c8072a0a68b1b"
          - config: { name: "Bazel4" }
            targets: "//src/..."
            image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:4.2.3-3b71de326b62f67bf754c4dc4016d6a2fa9dd664"
    name: Linux ${{ matrix.config.name }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout pending changes
        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
        with:
          ref: ${{ inputs.safe-checkout }}
      - name: Run tests
        uses: ./.github/actions/bazel-docker
        with:
          image: ${{ matrix.image }}
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          bazel-cache: cpp_linux/${{ matrix.config.name }}
          bazel: test ${{ matrix.targets }} ${{ matrix.config.flags }} --distinct_host_configuration=false

  linux-cmake:
    strategy:
      fail-fast: false   # Don't cancel all jobs if one fails.
      matrix:
        include:
          - command: >-
              /test.sh
              -Dprotobuf_BUILD_CONFORMANCE=ON
              -Dprotobuf_BUILD_EXAMPLES=ON
              -DCMAKE_CXX_STANDARD=14
          - name: Ninja
            command: >-
              /test.sh
              -G Ninja
              -Dprotobuf_BUILD_CONFORMANCE=ON
              -DCMAKE_CXX_STANDARD=14
          - name: Shared
            command: >-
              /test.sh
              -Dprotobuf_BUILD_CONFORMANCE=ON
              -Dprotobuf_BUILD_SHARED_LIBS=ON
              -DCMAKE_CXX_STANDARD=14

    name: Linux CMake ${{ matrix.name}}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout pending changes
        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
        with:
          submodules: recursive
          ref: ${{ inputs.safe-checkout }}

      - name: Setup ccache
        uses: ./.github/actions/ccache
        with:
          cache-prefix: linux-cmake-${{ matrix.name }}

      - name: Run tests
        uses: ./.github/actions/docker
        with:
          image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake@sha256:e8282f42b1c1c0e6227d746e861954fd6fad0bd2e7424e6ceb23c249289a4016
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          command: ${{ matrix.command }} ${{ env.CCACHE_CMAKE_FLAGS }}

  linux-cmake-install:
    name: Linux CMake Install
    runs-on: ubuntu-latest
    steps:
      - name: Checkout pending changes
        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
        with:
          submodules: recursive
          ref: ${{ inputs.safe-checkout }}

      - name: Setup ccache
        uses: ./.github/actions/ccache
        with:
          cache-prefix: linux-cmake-install

      - name: Run tests
        uses: ./.github/actions/docker
        with:
          image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake@sha256:e8282f42b1c1c0e6227d746e861954fd6fad0bd2e7424e6ceb23c249289a4016
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          command: >-
            /install.sh -DCMAKE_CXX_STANDARD=14 ${{ env.CCACHE_CMAKE_FLAGS }} \&\&
            /test.sh
            ${{ env.CCACHE_CMAKE_FLAGS }}
            -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON
            -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF
            -Dprotobuf_BUILD_CONFORMANCE=ON
            -DCMAKE_CXX_STANDARD=14

  linux-cmake-32-bit:
    name: Linux CMake 32-bit
    runs-on: ubuntu-latest
    steps:
      - name: Checkout pending changes
        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
        with:
          submodules: recursive
          ref: ${{ inputs.safe-checkout }}

      - name: Setup ccache
        uses: ./.github/actions/ccache
        with:
          cache-prefix: linux-cmake-32-bit

      - name: Run tests
        uses: ./.github/actions/docker
        with:
          image: us-docker.pkg.dev/protobuf-build/containers/test/linux/32bit@sha256:f99f051daa8b12f4ebad5927f389bc71372f771ab080290ab451cbaf1648f9ea
          platform: linux/386
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          command: >-
              /bin/bash -c '
              cd /workspace;
              ccache -z;
              cmake . -DCMAKE_CXX_STANDARD=14 ${{ env.CCACHE_CMAKE_FLAGS }};
              cmake --build . --parallel 20;
              ctest --verbose --parallel 20;
              ccache -s'

  non-linux:
    strategy:
      fail-fast: false   # Don't cancel all jobs if one fails.
      matrix:
        include:
          - name: MacOS
            os: macos-12
            bazel: //src/...
          - name: Windows
            os: windows-2019
            bazel: //src/...  @com_google_protobuf_examples//... --test_tag_filters=-conformance --build_tag_filters=-conformance
    name: ${{ matrix.name }} Bazel
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout pending changes
        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
        with:
          ref: ${{ inputs.safe-checkout }}
      - name: Run tests
        uses: ./.github/actions/bazel
        with:
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          bazel: test ${{ matrix.bazel }}
          bazel-cache: cpp_${{ matrix.os }}

  non-linux-cmake:
    strategy:
      fail-fast: false   # Don't cancel all jobs if one fails.
      matrix:
        include:
          - name: MacOS CMake
            os: macos-12
            flags: -DCMAKE_CXX_STANDARD=14
          - name: Windows CMake
            os: windows-2019
            flags: >-
              -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
              -Dprotobuf_BUILD_SHARED_LIBS=OFF
              -Dprotobuf_BUILD_EXAMPLES=ON
          - name: Windows CMake Shared
            os: windows-2019
            flags: >-
              -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
              -Dprotobuf_BUILD_SHARED_LIBS=ON
          - name: Windows CMake Install
            os: windows-2019
            install-flags: -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_TESTS=OFF
            flags: >-
              -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
              -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON
              -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout pending changes
        uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
        with:
          submodules: recursive
          ref: ${{ inputs.safe-checkout }}

      - name: Setup ccache
        uses: ./.github/actions/ccache
        with:
          cache-prefix: ${{ matrix.name }}

      # Install phase.
      - name: Configure CMake for install
        if: matrix.install-flags
        uses: ./.github/actions/bash
        with:
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          command: cmake . ${{ matrix.install-flags }} ${{ env.CCACHE_CMAKE_FLAGS }}
      - name: Build for install
        if: matrix.install-flags
        shell: bash
        run: VERBOSE=1 cmake --build . --parallel 20
      - name: Install
        if: matrix.install-flags
        shell: bash
        run: cmake --build . --target install
      - name: Report and clear ccache stats
        if: matrix.install-flags
        shell: bash
        run: ccache -s -v && ccache -z
      - name: Clear CMake cache
        if: matrix.install-flags
        shell: bash
        run: cmake --build . --target clean && rm CMakeCache.txt

      - name: Configure CMake
        uses: ./.github/actions/bash
        with:
          credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
          command: cmake . ${{ matrix.flags }} ${{ env.CCACHE_CMAKE_FLAGS }}

      - name: Build
        shell: bash
        run: VERBOSE=1 cmake --build . --parallel 20

      - name: Test
        shell: bash
        run: ctest --verbose --parallel 20 -C Debug

      - name: Report ccache stats
        shell: bash
        run: ccache -s -v
