name: CI

on:
  pull_request:
    types: [opened, synchronize]
  push:
    branches:
    - cpp_master
    tags:
    - '*'

jobs:
  macos:
    runs-on: macos-latest
    strategy:
      fail-fast: false
      matrix:
        pattern: [0, 1, 2, 3]
    steps:
    - uses: actions/checkout@v1
    - name: Cache boost
      id: cache-boost
      uses: actions/cache@v1
      with:
        path: usr
        key: ${{ runner.os }}-boost-20200107
    - name: Build boost
      if: steps.cache-boost.outputs.cache-hit != 'true'
      run: ./.github/depends/boost.sh -b 64 -t clang
    - name: build and test
      env:
        CXX: clang++
      shell: bash
      run: |
        BASE=`pwd`;

        # matrix config
        if [ ${{ matrix.pattern }} == 0 ]; then
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="64"
          export CHAR_SIGN="unsigned"
          export API_VERSION="1"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 1 ]; then
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="64"
          export CHAR_SIGN="signed"
          export API_VERSION="3"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 2 ]; then
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="64"
          export CHAR_SIGN="signed"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 3 ]; then
          ACTION="ci/build_cmake.sh"
          export ARCH="64"
          export CHAR_SIGN="unsigned"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi

        # install gtest
        wget https://github.com/google/googletest/archive/release-1.7.0.zip -O googletest-release-1.7.0.zip
        unzip -q googletest-release-1.7.0.zip
        cd googletest-release-1.7.0
        $CXX -m${ARCH} src/gtest-all.cc -I. -Iinclude -c
        $CXX -m${ARCH} src/gtest_main.cc -I. -Iinclude -c
        ar -rv libgtest.a gtest-all.o
        ar -rv libgtest_main.a gtest_main.o
        mkdir -p ${BASE}/usr/include
        cp -r include/gtest ${BASE}/usr/include
        mkdir -p ${BASE}/usr/lib
        mv *.a ${BASE}/usr/lib
        cd ..

        # build and test
        CMAKE_CXX_COMPILER="${CXX}" CMAKE_LIBRARY_PATH="${BASE}/usr/lib:${BASE}/build" GTEST_ROOT="${BASE}/usr" CMAKE_PREFIX_PATH="${BASE}/usr/clang/lib${ARCH}/cmake" CXXFLAGS="-Werror -g ${SANITIZE}" ${ACTION}
        cat Files.cmake| grep ".*\.[h|hpp]" | perl -pe 's/ //g' | sort > tmp1  && find include -name "*.h" -o -name "*.hpp" | sort > tmp2 && diff tmp1 tmp2

  linux:
    runs-on: ubuntu-18.04
    strategy:
      fail-fast: false
      matrix:
        pattern: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    steps:
    - uses: actions/checkout@v1
    - name: install build depends
      run: |
        sudo apt-get update
        sudo apt-get install g++-multilib clang-8 valgrind
    - name: Cache boost
      id: cache-boost
      uses: actions/cache@v1
      with:
        path: usr
        key: ${{ runner.os }}-boost-20200107
    - name: Build boost
      if: steps.cache-boost.outputs.cache-hit != 'true'
      run: ./.github/depends/boost.sh -b both -t gcc
    - name: build and test
      shell: bash
      run: |
        BASE=`pwd`;

        # matrix config
        if [ ${{ matrix.pattern }} == 0 ]; then
          export CXX=clang++
          ACTION="ci/build_cmake.sh"
          export ARCH="64"
          export CHAR_SIGN="unsigned"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 1 ]; then
          export CXX=clang++
          ACTION="ci/build_cmake.sh"
          export ARCH="32"
          export CHAR_SIGN="signed"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 2 ]; then
          export CXX=clang++
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="64"
          export CHAR_SIGN="signed"
          export API_VERSION="3"
          export X3_PARSE="ON"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 3 ]; then
          export CXX=clang++
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="32"
          export CHAR_SIGN="unsigned"
          export API_VERSION="2"
        fi
        if [ ${{ matrix.pattern }} == 4 ]; then
          export CXX=g++
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="64"
          export CHAR_SIGN="signed"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 5 ]; then
          export CXX=g++
          ACTION="ci/build_cmake.sh"
          export CXX17="ON"
          export ARCH="32"
          export CHAR_SIGN="unsigned"
          export API_VERSION="3"
          export X3_PARSE="ON"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 6 ]; then
          export CXX=g++
          ACTION="ci/build_cmake.sh"
          export ARCH="64"
          export CHAR_SIGN="unsigned"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 7 ]; then
          export CXX=g++
          ACTION="ci/build_cmake.sh"
          export ARCH="32"
          export CHAR_SIGN="signed"
          export API_VERSION="1"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 8 ]; then
          export CXX=g++
          ACTION="ci/build_cmake.sh"
          export ARCH="32"
          export CHAR_SIGN="signed"
          export API_VERSION="2"
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 9 ]; then
          export CXX=clang++
          ACTION="ci/build_regression.sh"
          export ARCH="64"
          export SAN="UBSAN"
          export MSGPACK_FUZZ_REGRESSION="ON"
          export CTEST_OUTPUT_ON_FAILURE=1
          export SANITIZE="-fsanitize=undefined"
        fi
        if [ ${{ matrix.pattern }} == 10 ]; then
          export CXX=clang++
          ACTION="ci/build_regression.sh"
          export ARCH="64"
          export SAN="ASAN"
          export MSGPACK_FUZZ_REGRESSION="ON"
          export CTEST_OUTPUT_ON_FAILURE=1
          export SANITIZE="-fsanitize=undefined"
        fi

        # install gtest
        wget https://github.com/google/googletest/archive/release-1.7.0.zip -O googletest-release-1.7.0.zip
        unzip -q googletest-release-1.7.0.zip
        cd googletest-release-1.7.0
        $CXX -m${ARCH} src/gtest-all.cc -I. -Iinclude -c -fPIC
        $CXX -m${ARCH} src/gtest_main.cc -I. -Iinclude -c -fPIC
        ar -rv libgtest.a gtest-all.o
        ar -rv libgtest_main.a gtest_main.o
        mkdir -p ${BASE}/usr/include
        cp -r include/gtest ${BASE}/usr/include
        mkdir -p ${BASE}/usr/lib
        mv *.a ${BASE}/usr/lib
        cd ..

        # install zlib
        if [ ${ARCH} == 32 ]; then
          sudo apt-get install lib32z1-dev
        fi

        # build and test
        CMAKE_CXX_COMPILER="${CXX}" CMAKE_LIBRARY_PATH="${BASE}/usr/lib:${BASE}/build" GTEST_ROOT="${BASE}/usr" CMAKE_PREFIX_PATH="${BASE}/usr/gcc/lib${ARCH}/cmake" CXXFLAGS="-Werror -g ${SANITIZE}" MSGPACK_SAN="${SAN}" ${ACTION}
        cat Files.cmake| grep ".*\.[h|hpp]" | perl -pe 's/ //g' | sort > tmp1  && find include -name "*.h" -o -name "*.hpp" | sort > tmp2 && diff tmp1 tmp2
  windows:
    runs-on: windows-2016
    strategy:
      fail-fast: false
      matrix:
        pattern: [0, 1, 2]
    steps:
    - uses: actions/checkout@v1
    - name: Cache vcpkg
      id: cache-vcpkg
      uses: actions/cache@v1.0.3
      with:
        path: C:/vcpkg/installed/x64-windows
        key: ${{ runner.os }}-vcpkg
    - name: Build dependencies
      if: steps.cache-vcpkg.outputs.cache-hit != 'true'
      shell: powershell
      run: |
        vcpkg update
        vcpkg install gtest:x64-windows
        vcpkg install zlib:x64-windows
    - name: Build and test
      shell: powershell
      run: |
        if (${{ matrix.pattern }} -eq 0) {
          $CPPVER="-DMSGPACK_CXX17=ON"
        }
        if (${{ matrix.pattern }} -eq 1) {
          $CPPVER="-DMSGPACK_CXX11=ON"
        }
        if (${{ matrix.pattern }} -eq 2) {
          $CPPVER="-DMSGPACK_CXX11=OFF"
        }

        $CUR=(Get-Location).Path
        md build
        cd build
        cmake -A x64 -DBOOST_ROOT="$env:BOOST_ROOT_1_72_0" -DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake" $CPPVER "-DCMAKE_CXX_FLAGS=/D_VARIADIC_MAX=10 /EHsc /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING" ..
        if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
        cmake --build . --config Release
        $pathbak="$env:PATH"
        $env:PATH="C:\vcpkg\installed\x64-windows\bin;$CUR\build\Release;$pathbak"
        ctest -V
        if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
        $env:PATH=$pathbak
