name: Tests

on:
  push:
    branches: master
  pull_request:
    branches: master
  schedule:
    - cron: "0 12 * * 1"

env:
  CARGO_INCREMENTAL: 0
  RUSTFLAGS: "-Dwarnings"

jobs:
  check-doc:
    name: Docs, deadlinks, minimal dependencies
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly # Needed for -Z minimal-versions and doc_cfg
          override: true
      - uses: Swatinem/rust-cache@v1
      - name: Install precompiled cargo-deadlinks
        run: |
          export URL=$(curl -s https://api.github.com/repos/deadlinks/cargo-deadlinks/releases/latest | jq -r '.assets[] | select(.name | contains("cargo-deadlinks-linux")) | .browser_download_url')
          wget -O /tmp/cargo-deadlinks $URL
          chmod +x /tmp/cargo-deadlinks
          mv /tmp/cargo-deadlinks ~/.cargo/bin
      - name: Generate Docs
        env:
          RUSTDOCFLAGS: --cfg docsrs
        run: cargo deadlinks -- --features=custom,std
      - run: |
          cargo generate-lockfile -Z minimal-versions
          cargo test --features=custom,std

  main-tests:
    name: Main tests
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        toolchain: [nightly, beta, stable, 1.34]
        # Only Test macOS on stable to reduce macOS CI jobs
        include:
          - os: macos-latest
            toolchain: stable
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
      - uses: Swatinem/rust-cache@v1
      - run: cargo test
      - run: cargo test --features=std
      - run: cargo test --features=custom # custom should do nothing here
      - if: ${{ matrix.toolchain == 'nightly' }}
        run: cargo build --benches

  linux-tests:
    name: Additional Linux targets
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target: [
          x86_64-unknown-linux-musl,
          i686-unknown-linux-gnu,
          i686-unknown-linux-musl,
        ]
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: ${{ matrix.target }}
          toolchain: stable
      - uses: Swatinem/rust-cache@v1
      - name: Install multilib
        # update is needed to fix the 404 error on install, see:
        # https://github.com/actions/virtual-environments/issues/675
        run: |
          sudo apt-get update
          sudo apt-get install gcc-multilib
      - run: cargo test --target=${{ matrix.target }} --features=std

  # We can only Build/Link on these targets for now.
  # TODO: Run the iOS binaries in the simulator
  # TODO: build/run aarch64-apple-darwin binaries on a x86_64 Mac
  apple-tests:
    name: Additional Apple targets
    runs-on: macos-latest
    strategy:
      matrix:
        target: [
          aarch64-apple-ios,
          x86_64-apple-ios,
        ]
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: ${{ matrix.target }}
          toolchain: stable
      - uses: Swatinem/rust-cache@v1
      - name: Build Tests
        run: cargo test --no-run --target=${{ matrix.target }} --features=std

  windows-tests:
    name: Additional Windows targets
    runs-on: windows-latest
    strategy:
      matrix:
        toolchain: [
          stable-x86_64-gnu,
          stable-i686-gnu,
          stable-i686-msvc,
        ]
    steps:
      - uses: actions/checkout@v2
      - name: Install toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true
      - uses: Swatinem/rust-cache@v1
      - run: cargo test --features=std

  cross-tests:
    name: Cross Test
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target: [
          aarch64-unknown-linux-gnu,
          aarch64-linux-android,
          mips-unknown-linux-gnu,
        ]
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: ${{ matrix.target }}
          toolchain: stable
      - uses: Swatinem/rust-cache@v1
      - name: Install precompiled cross
        run: |
          export URL=$(curl -s https://api.github.com/repos/cross-rs/cross/releases/latest | jq -r '.assets[] | select(.name | contains("x86_64-unknown-linux-gnu.tar.gz")) | .browser_download_url')
          wget -O /tmp/binaries.tar.gz $URL
          tar -C /tmp -xzf /tmp/binaries.tar.gz
          mv /tmp/cross ~/.cargo/bin
      - name: Test
        run: cross test --no-fail-fast --target=${{ matrix.target }} --features=std

  cross-link:
    name: Cross Build/Link
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target: [
          # See: https://github.com/rust-random/getrandom/issues/254
          # sparcv9-sun-solaris,
          x86_64-unknown-netbsd,
        ]
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: ${{ matrix.target }}
          toolchain: stable
      - uses: Swatinem/rust-cache@v1
      - name: Install precompiled cross
        run: |
          export URL=$(curl -s https://api.github.com/repos/cross-rs/cross/releases/latest | jq -r '.assets[] | select(.name | contains("x86_64-unknown-linux-gnu.tar.gz")) | .browser_download_url')
          wget -O /tmp/binaries.tar.gz $URL
          tar -C /tmp -xzf /tmp/binaries.tar.gz
          mv /tmp/cross ~/.cargo/bin
      - name: Build Tests
        run: cross test --no-run --target=${{ matrix.target }} --features=std

  web-tests:
    name: Web tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: wasm32-unknown-unknown
          toolchain: stable
      - uses: Swatinem/rust-cache@v1
      - name: Install precompiled wasm-bindgen-test-runner
        run: |
          export VERSION=$(cargo metadata --format-version=1 | jq -r '.packages[] | select ( .name == "wasm-bindgen" ) | .version')
          wget -O /tmp/binaries.tar.gz https://github.com/rustwasm/wasm-bindgen/releases/download/$VERSION/wasm-bindgen-$VERSION-x86_64-unknown-linux-musl.tar.gz
          tar -C /tmp -xzf /tmp/binaries.tar.gz --strip-components=1
          mv /tmp/wasm-bindgen-test-runner ~/.cargo/bin
      - name: Test (Node)
        run: cargo test --target=wasm32-unknown-unknown --features=js
      - name: Test (Firefox)
        env:
          GECKODRIVER: /usr/bin/geckodriver
        run: cargo test --target=wasm32-unknown-unknown --features=js,test-in-browser
      - name: Test (Chrome)
        env:
          CHROMEDRIVER: /usr/bin/chromedriver
        run: cargo test --target=wasm32-unknown-unknown --features=js,test-in-browser
      - name: Test (custom getrandom)
        run: cargo test --target=wasm32-unknown-unknown --features=custom

  wasi-tests:
    name: WASI test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: wasm32-wasi
          toolchain: stable
      - uses: Swatinem/rust-cache@v1
      - name: Install precompiled wasmtime
        run: |
          export URL=$(curl -s https://api.github.com/repos/bytecodealliance/wasmtime/releases/latest | jq -r '.assets[] | select(.name | contains("x86_64-linux.tar.xz")) | .browser_download_url')
          wget -O /tmp/binaries.tar.xz $URL
          tar -C /tmp -xf /tmp/binaries.tar.xz --strip-components=1
          mv /tmp/wasmtime ~/.cargo/bin
      - run: cargo test --target wasm32-wasi

  emscripten-tests:
    name: Emscripten tests
    runs-on: ubuntu-latest
    env:
      EMSDK_VERSION: 1.39.20 # Last emsdk compatible with Rust's LLVM 11
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
      - run: rustup target add wasm32-unknown-emscripten
      - run: rustup target add asmjs-unknown-emscripten
      - uses: Swatinem/rust-cache@v1
      - name: Cache emsdk
        id: cache-emsdk
        uses: actions/cache@v2
        with:
          path: ~/emsdk
          key: ${{ runner.os }}-${{ env.EMSDK_VERSION }}-emsdk
      - name: Install emsdk
        if: steps.cache-emsdk.outputs.cache-hit != 'true'
        run: |
          git clone https://github.com/emscripten-core/emsdk.git ~/emsdk
          cd ~/emsdk
          ./emsdk install $EMSDK_VERSION
          ./emsdk activate $EMSDK_VERSION
      - run: echo "$HOME/emsdk/upstream/emscripten" >> $GITHUB_PATH
      - name: wasm test
        run: cargo test --target=wasm32-unknown-emscripten --features=std
      - name: asm.js test
        run: | # Debug info breaks on asm.js
          RUSTFLAGS="$RUSTFLAGS -C debuginfo=0"
          cargo test --target=asmjs-unknown-emscripten --features=std

  build:
    name: Build only
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target: [
          x86_64-unknown-freebsd,
          x86_64-fuchsia,
          x86_64-unknown-redox,
          x86_64-fortanix-unknown-sgx,
        ]
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          target: ${{ matrix.target }}
          toolchain: nightly # Required to build libc for Redox
          override: true
      - uses: Swatinem/rust-cache@v1
      - name: Build
        run: cargo build --target=${{ matrix.target }} --features=std

  build-std:
    name: Build-only (build-std)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Install toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly # Required to build libcore
          components: rust-src
          override: true
      - uses: Swatinem/rust-cache@v1
      - name: Hermit (x86-64 only)
        run: cargo build -Z build-std=core --target=x86_64-unknown-hermit
      - name: UEFI (RDRAND)
        run: cargo build -Z build-std=core --features=rdrand --target=x86_64-unknown-uefi
      - name: L4Re (RDRAND)
        run: cargo build -Z build-std=core --features=rdrand --target=x86_64-unknown-l4re-uclibc
      - name: VxWorks
        run: cargo build -Z build-std=core --target=x86_64-wrs-vxworks
      - name: SOLID
        run: cargo build -Z build-std=core --target=aarch64-kmc-solid_asp3
      - name: Nintendo 3DS
        run: cargo build -Z build-std=core --target=armv6k-nintendo-3ds

  clippy-fmt:
    name: Clippy + rustfmt
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          # https://github.com/rust-lang/rust-clippy/pull/6379 added MSRV
          # support, so we need to use nightly until this is on stable.
          toolchain: nightly
          components: rustfmt, clippy
          override: true
      - uses: Swatinem/rust-cache@v1
      - name: clippy
        run: cargo clippy --all --features=custom,std
      - name: fmt
        run: cargo fmt --all -- --check
