| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- name: test
- on:
- push:
- pull_request:
- workflow_dispatch:
- inputs:
- gtest_filter:
- description: 'Google Test filter'
- test_linux:
- description: 'Test on Linux'
- type: boolean
- default: true
- test_macos:
- description: 'Test on MacOS'
- type: boolean
- default: true
- test_windows:
- description: 'Test on Windows'
- type: boolean
- default: true
- concurrency:
- group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
- cancel-in-progress: true
- env:
- # Exclude *_Online tests by default — they hit external services and flake on
- # CI runners. Run with workflow_dispatch + a custom filter to include them.
- GTEST_FILTER: ${{ github.event.inputs.gtest_filter || '-*_Online' }}
- jobs:
- style-check:
- runs-on: ubuntu-latest
- if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
- continue-on-error: true
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: run style check
- run: |
- clang-format --version
- cd test && make style_check
- build-and-test-on-32bit:
- runs-on: ubuntu-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
- strategy:
- matrix:
- config:
- - arch_flags: -m32
- arch_suffix: :i386
- name: (32-bit)
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install libraries
- run: |
- sudo dpkg --add-architecture i386
- sudo apt-get update
- sudo apt-get install -y libc6-dev${{ matrix.config.arch_suffix }} libstdc++-13-dev${{ matrix.config.arch_suffix }} \
- libssl-dev${{ matrix.config.arch_suffix }} libcurl4-openssl-dev${{ matrix.config.arch_suffix }} \
- zlib1g-dev${{ matrix.config.arch_suffix }} libbrotli-dev${{ matrix.config.arch_suffix }} \
- libzstd-dev${{ matrix.config.arch_suffix }}
- - name: build and run tests
- run: cd test && make test EXTRA_CXXFLAGS="${{ matrix.config.arch_flags }}"
- ubuntu:
- runs-on: ubuntu-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
- strategy:
- fail-fast: false
- matrix:
- tls_backend: [openssl, mbedtls, wolfssl]
- name: ubuntu (${{ matrix.tls_backend }})
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install common libraries
- run: |
- sudo apt-get update
- sudo apt-get install -y libcurl4-openssl-dev zlib1g-dev libbrotli-dev libzstd-dev
- - name: install OpenSSL
- if: matrix.tls_backend == 'openssl'
- run: sudo apt-get install -y libssl-dev
- - name: install Mbed TLS
- if: matrix.tls_backend == 'mbedtls'
- run: sudo apt-get install -y libmbedtls-dev
- - name: install wolfSSL
- if: matrix.tls_backend == 'wolfssl'
- run: sudo apt-get install -y libwolfssl-dev
- - name: build and run tests (OpenSSL)
- if: matrix.tls_backend == 'openssl'
- run: cd test && make test_split && make test_openssl_parallel
- env:
- LSAN_OPTIONS: suppressions=lsan_suppressions.txt
- - name: build and run tests (Mbed TLS)
- if: matrix.tls_backend == 'mbedtls'
- run: cd test && make test_split_mbedtls && make test_mbedtls_parallel
- - name: build and run tests (wolfSSL)
- if: matrix.tls_backend == 'wolfssl'
- run: cd test && make test_split_wolfssl && make test_wolfssl_parallel
- - name: run fuzz test target
- if: matrix.tls_backend == 'openssl'
- run: cd test && make fuzz_test
- - name: build and run WebSocket heartbeat test
- if: matrix.tls_backend == 'openssl'
- run: cd test && make test_websocket_heartbeat && ./test_websocket_heartbeat
- - name: build and run ThreadPool test
- run: cd test && make test_thread_pool && ./test_thread_pool
- # Ubuntu 26.04's apt ships Mbed TLS 3.6, giving 3.x coverage that
- # ubuntu-latest (24.04 = 2.28) and macOS (Homebrew = 4.x) no longer provide.
- # Uses the 26.04 public-preview image; fold into the main ubuntu matrix once
- # ubuntu-latest moves to 26.04.
- ubuntu-2604-mbedtls:
- runs-on: ubuntu-26.04
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
- name: ubuntu-26.04 (mbedtls 3.x)
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install common libraries
- run: |
- sudo apt-get update
- sudo apt-get install -y libcurl4-openssl-dev zlib1g-dev libbrotli-dev libzstd-dev
- - name: install Mbed TLS
- run: sudo apt-get install -y libmbedtls-dev
- - name: build and run tests (Mbed TLS)
- run: cd test && make test_split_mbedtls && make test_mbedtls_parallel
- # BoringSSL is Google's fork of OpenSSL. It has no API stability guarantee
- # and is not packaged by distros, so we build it from source. cpp-httplib
- # treats it as an OpenSSL backend variant via the OPENSSL_IS_BORINGSSL
- # macro (see httplib.h). This job is best-effort: continue-on-error keeps
- # upstream API drift from blocking PRs while still surfacing breakage.
- ubuntu-boringssl:
- runs-on: ubuntu-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
- continue-on-error: true
- name: ubuntu (boringssl, best-effort)
- env:
- # Tracking HEAD keeps us honest about upstream churn. If breakage
- # becomes routine, replace HEAD with a 40-char commit SHA; the
- # resolve step uses the SHA directly when it matches that shape.
- BORINGSSL_REF: HEAD
- BORINGSSL_PREFIX: ${{ github.workspace }}/boringssl-install
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install common libraries
- run: |
- sudo apt-get update
- sudo apt-get install -y libcurl4-openssl-dev zlib1g-dev libbrotli-dev libzstd-dev
- - name: resolve BoringSSL commit
- id: boringssl-rev
- # Accept either a ref name (resolved via git ls-remote) or a full
- # 40-char SHA used directly. ls-remote does not list arbitrary
- # commit SHAs, so pinning requires the second path.
- run: |
- if [[ "${BORINGSSL_REF}" =~ ^[0-9a-f]{40}$ ]]; then
- sha="${BORINGSSL_REF}"
- echo "Using pinned BoringSSL SHA: ${sha}"
- else
- sha=$(git ls-remote https://boringssl.googlesource.com/boringssl "${BORINGSSL_REF}" | awk '{print $1}')
- if [ -z "$sha" ]; then
- echo "Failed to resolve BoringSSL ref ${BORINGSSL_REF}" >&2
- exit 1
- fi
- echo "Resolved ${BORINGSSL_REF} -> ${sha}"
- fi
- echo "sha=${sha}" >> "$GITHUB_OUTPUT"
- - name: cache BoringSSL build
- id: boringssl-cache
- uses: actions/cache@v4
- with:
- path: ${{ env.BORINGSSL_PREFIX }}
- key: boringssl-${{ runner.os }}-${{ steps.boringssl-rev.outputs.sha }}
- - name: build BoringSSL
- if: steps.boringssl-cache.outputs.cache-hit != 'true'
- run: |
- set -e
- git clone https://boringssl.googlesource.com/boringssl boringssl
- cd boringssl
- git checkout "${{ steps.boringssl-rev.outputs.sha }}"
- cmake -S . -B build \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
- -DCMAKE_INSTALL_PREFIX="${BORINGSSL_PREFIX}"
- cmake --build build -j"$(nproc)" --target install
- - name: build and run tests (BoringSSL)
- # Override OPENSSL_SUPPORT to point the existing OpenSSL Makefile path
- # at BoringSSL's prefix. BoringSSL defines OPENSSL_IS_BORINGSSL in
- # <openssl/base.h>, which httplib.h and test.cc use to switch on API
- # differences (e.g. SAN-only hostname verification, no CN fallback).
- #
- # BoringSSL's public headers (<openssl/stack.h>) use std::enable_if_t,
- # so consumers must compile with C++14 or later. cpp-httplib itself
- # supports C++11, but anyone pairing it with BoringSSL inherits this
- # constraint. EXTRA_CXXFLAGS appends after the Makefile's -std=c++11
- # and the later flag wins.
- run: |
- cd test
- BORINGSSL_FLAGS="-DCPPHTTPLIB_OPENSSL_SUPPORT -I${BORINGSSL_PREFIX}/include -L${BORINGSSL_PREFIX}/lib -lssl -lcrypto -lpthread"
- make test_split OPENSSL_SUPPORT="${BORINGSSL_FLAGS}" EXTRA_CXXFLAGS="-std=c++17"
- make test_openssl_parallel OPENSSL_SUPPORT="${BORINGSSL_FLAGS}" EXTRA_CXXFLAGS="-std=c++17"
- env:
- LSAN_OPTIONS: suppressions=lsan_suppressions.txt
- # macOS counterpart of the BoringSSL job. Same best-effort posture; the
- # extra framework links cover the macOS Keychain integration that
- # httplib.h auto-enables for any TLS backend on macOS.
- macos-boringssl:
- runs-on: macos-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true')
- continue-on-error: true
- name: macos (boringssl, best-effort)
- env:
- BORINGSSL_REF: HEAD
- BORINGSSL_PREFIX: ${{ github.workspace }}/boringssl-install
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: resolve BoringSSL commit
- id: boringssl-rev
- # Accept either a ref name (resolved via git ls-remote) or a full
- # 40-char SHA used directly. ls-remote does not list arbitrary
- # commit SHAs, so pinning requires the second path.
- run: |
- if [[ "${BORINGSSL_REF}" =~ ^[0-9a-f]{40}$ ]]; then
- sha="${BORINGSSL_REF}"
- echo "Using pinned BoringSSL SHA: ${sha}"
- else
- sha=$(git ls-remote https://boringssl.googlesource.com/boringssl "${BORINGSSL_REF}" | awk '{print $1}')
- if [ -z "$sha" ]; then
- echo "Failed to resolve BoringSSL ref ${BORINGSSL_REF}" >&2
- exit 1
- fi
- echo "Resolved ${BORINGSSL_REF} -> ${sha}"
- fi
- echo "sha=${sha}" >> "$GITHUB_OUTPUT"
- - name: cache BoringSSL build
- id: boringssl-cache
- uses: actions/cache@v4
- with:
- path: ${{ env.BORINGSSL_PREFIX }}
- key: boringssl-${{ runner.os }}-${{ steps.boringssl-rev.outputs.sha }}
- - name: build BoringSSL
- if: steps.boringssl-cache.outputs.cache-hit != 'true'
- run: |
- set -e
- git clone https://boringssl.googlesource.com/boringssl boringssl
- cd boringssl
- git checkout "${{ steps.boringssl-rev.outputs.sha }}"
- cmake -S . -B build \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
- -DCMAKE_INSTALL_PREFIX="${BORINGSSL_PREFIX}"
- cmake --build build -j"$(sysctl -n hw.ncpu)" --target install
- - name: build and run tests (BoringSSL)
- run: |
- cd test
- # CoreFoundation/Security frameworks satisfy the Keychain integration
- # auto-enabled in httplib.h for macOS TLS builds.
- BORINGSSL_FLAGS="-DCPPHTTPLIB_OPENSSL_SUPPORT -I${BORINGSSL_PREFIX}/include -L${BORINGSSL_PREFIX}/lib -lssl -lcrypto -framework CoreFoundation -framework Security"
- make test_split OPENSSL_SUPPORT="${BORINGSSL_FLAGS}" EXTRA_CXXFLAGS="-std=c++17"
- make test_openssl_parallel OPENSSL_SUPPORT="${BORINGSSL_FLAGS}" EXTRA_CXXFLAGS="-std=c++17"
- env:
- LSAN_OPTIONS: suppressions=lsan_suppressions.txt
- # Reproducer for https://github.com/yhirose/cpp-httplib/issues/2431.
- # On Linux/glibc, getaddrinfo_with_timeout() schedules an asynchronous
- # DNS lookup with getaddrinfo_a(GAI_NOWAIT) using a stack-local gaicb.
- # When gai_suspend() hits the connection timeout, gai_cancel() is called
- # but does not block; the resolver worker can later write back into the
- # destroyed stack frame. To make the worker actually reach that write,
- # the test job runs a loopback UDP responder (test/dns_test_fixture.py)
- # that delays its reply past the test's 1s timeout, and uses an iptables
- # NAT rule so glibc's lookups land on that fixture instead of a real
- # nameserver. With ASAN's detect_stack_use_after_return enabled, the
- # late write-back is reported as a stack-use-after-return.
- issue-2431-repro:
- runs-on: ubuntu-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
- name: issue-2431 repro (Linux + ASAN)
- # Bound the whole job in case anything in the test harness hangs
- # unexpectedly. With the fixture in place a normal run is well under
- # a minute either way (ASAN abort on broken HEAD, clean pass on fix).
- timeout-minutes: 5
- env:
- DNS_FIXTURE_PORT: "15353"
- DNS_FIXTURE_DELAY: "3"
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install libraries
- run: |
- sudo apt-get update
- sudo apt-get install -y libssl-dev zlib1g-dev libbrotli-dev \
- libzstd-dev libcurl4-openssl-dev iptables util-linux iproute2
- - name: start loopback DNS test fixture
- run: |
- # Force glibc through its DNS code path: Ubuntu's default
- # nsswitch short-circuits to NOTFOUND through mdns4_minimal,
- # which would skip the buggy code entirely.
- sudo sed -i 's/^hosts:.*/hosts: dns/' /etc/nsswitch.conf
- # Run the loopback fixture (delayed UDP responder).
- python3 test/dns_test_fixture.py "$DNS_FIXTURE_PORT" "$DNS_FIXTURE_DELAY" \
- >/tmp/dns_fixture.log 2>&1 &
- echo $! | sudo tee /tmp/dns_fixture.pid >/dev/null
- # Wait for the fixture to start listening.
- for _ in $(seq 1 50); do
- if ss -lun "( sport = :$DNS_FIXTURE_PORT )" | grep -q ":$DNS_FIXTURE_PORT"; then
- break
- fi
- sleep 0.1
- done
- ss -lun "( sport = :$DNS_FIXTURE_PORT )" | grep -q ":$DNS_FIXTURE_PORT" \
- || { echo "fixture failed to start"; cat /tmp/dns_fixture.log; exit 1; }
- # Send the test process's DNS lookups to the loopback fixture.
- # NAT only the local OUTPUT chain; conntrack handles the reply path.
- sudo iptables -t nat -I OUTPUT -p udp --dport 53 \
- -j REDIRECT --to-port "$DNS_FIXTURE_PORT"
- # Sanity check: a query must take at least the fixture delay
- # and resolve to NXDOMAIN (proving traffic reaches the fixture).
- start=$(date +%s)
- getent hosts unresolvable-host.invalid >/dev/null 2>&1 || true
- elapsed=$(( $(date +%s) - start ))
- if [ "$elapsed" -lt 2 ]; then
- echo "ERROR: lookup returned in ${elapsed}s; fixture not in path" >&2
- exit 1
- fi
- echo "[ok] DNS lookups are routed to the test fixture (took ${elapsed}s)"
- - name: build test binary
- run: cd test && make test
- - name: run GetAddrInfoAsyncCancelTest
- run: |
- cd test
- ARCH=$(uname -m)
- CPPHTTPLIB_TEST_ISSUE_2431=1 \
- ASAN_OPTIONS=detect_stack_use_after_return=1 \
- LSAN_OPTIONS=suppressions=lsan_suppressions.txt \
- setarch "$ARCH" -R \
- ./test --gtest_filter='GetAddrInfoAsyncCancelTest.*'
- - name: tear down test fixture
- if: always()
- run: |
- sudo iptables -t nat -F OUTPUT || true
- if [ -f /tmp/dns_fixture.pid ]; then
- sudo kill "$(cat /tmp/dns_fixture.pid)" 2>/dev/null || true
- fi
- macos:
- runs-on: macos-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true')
- strategy:
- fail-fast: false
- matrix:
- tls_backend: [openssl, mbedtls, wolfssl]
- name: macos (${{ matrix.tls_backend }})
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install Mbed TLS
- if: matrix.tls_backend == 'mbedtls'
- run: brew install mbedtls
- - name: install wolfSSL
- if: matrix.tls_backend == 'wolfssl'
- run: brew install wolfssl
- - name: build and run tests (OpenSSL)
- if: matrix.tls_backend == 'openssl'
- run: cd test && make test_split && make test_openssl_parallel
- env:
- LSAN_OPTIONS: suppressions=lsan_suppressions.txt
- - name: build and run tests (Mbed TLS)
- if: matrix.tls_backend == 'mbedtls'
- run: cd test && make test_split_mbedtls && make test_mbedtls_parallel
- - name: build and run tests (wolfSSL)
- if: matrix.tls_backend == 'wolfssl'
- run: cd test && make test_split_wolfssl && make test_wolfssl_parallel
- - name: run fuzz test target
- if: matrix.tls_backend == 'openssl'
- run: cd test && make fuzz_test
- - name: build and run WebSocket heartbeat test
- if: matrix.tls_backend == 'openssl'
- run: cd test && make test_websocket_heartbeat && ./test_websocket_heartbeat
- - name: build and run ThreadPool test
- run: cd test && make test_thread_pool && ./test_thread_pool
- ios-parse-check:
- runs-on: macos-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_macos == 'true')
- name: ios header parse check (not officially supported)
- steps:
- - name: checkout
- uses: actions/checkout@v4
- - name: install OpenSSL headers
- run: brew install openssl@3
- - name: verify header parses on iOS target
- run: |
- IOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path)
- OPENSSL_INC=$(brew --prefix openssl@3)/include
- echo "Using iOS SDK: $IOS_SDK"
- echo '#include "httplib.h"' | clang++ \
- -isysroot "$IOS_SDK" \
- -target arm64-apple-ios16.0 \
- -std=c++11 \
- -DCPPHTTPLIB_OPENSSL_SUPPORT \
- -I"$OPENSSL_INC" \
- -I. -Wall -Wextra \
- -fsyntax-only -x c++ -
- - name: verify CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN is rejected on iOS
- run: |
- IOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path)
- OPENSSL_INC=$(brew --prefix openssl@3)/include
- out=$(echo '#include "httplib.h"' | clang++ \
- -isysroot "$IOS_SDK" \
- -target arm64-apple-ios16.0 \
- -std=c++11 \
- -DCPPHTTPLIB_OPENSSL_SUPPORT \
- -DCPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN \
- -I"$OPENSSL_INC" \
- -I. \
- -fsyntax-only -x c++ - 2>&1 || true)
- if echo "$out" | grep -q "only supported on macOS"; then
- echo "OK: #error fired as expected"
- else
- echo "FAIL: expected #error did not fire"
- echo "--- compiler output ---"
- echo "$out"
- exit 1
- fi
- windows:
- runs-on: windows-latest
- if: >
- (github.event_name == 'push') ||
- (github.event_name == 'pull_request' &&
- github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
- (github.event_name == 'workflow_dispatch' && github.event.inputs.test_windows == 'true')
- strategy:
- fail-fast: false
- matrix:
- config:
- - with_ssl: false
- compiled: false
- run_tests: true
- name: without SSL
- - with_ssl: true
- compiled: false
- run_tests: true
- name: with SSL
- - with_ssl: false
- compiled: true
- run_tests: false
- name: compiled
- name: windows ${{ matrix.config.name }}
- steps:
- - name: Prepare Git for Checkout on Windows
- run: |
- git config --global core.autocrlf false
- git config --global core.eol lf
- - name: Checkout
- uses: actions/checkout@v4
- - name: Export GitHub Actions cache environment variables
- uses: actions/github-script@v7
- with:
- script: |
- core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
- core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- - name: Setup msbuild on windows
- uses: microsoft/setup-msbuild@v2
- - name: Cache vcpkg packages
- id: vcpkg-cache
- uses: actions/cache@v4
- with:
- path: C:/vcpkg/installed
- key: vcpkg-installed-windows-gtest-curl-zlib-brotli-zstd
- - name: Install vcpkg dependencies
- if: steps.vcpkg-cache.outputs.cache-hit != 'true'
- run: vcpkg install gtest curl zlib brotli zstd
- - name: Install OpenSSL
- if: ${{ matrix.config.with_ssl }}
- run: choco install openssl
- - name: Configure CMake ${{ matrix.config.name }}
- run: >
- cmake -B build -S .
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake
- -DHTTPLIB_TEST=ON
- -DHTTPLIB_COMPILE=${{ matrix.config.compiled && 'ON' || 'OFF' }}
- -DHTTPLIB_USE_OPENSSL_IF_AVAILABLE=${{ matrix.config.with_ssl && 'ON' || 'OFF' }}
- -DHTTPLIB_REQUIRE_ZLIB=ON
- -DHTTPLIB_REQUIRE_BROTLI=ON
- -DHTTPLIB_REQUIRE_ZSTD=ON
- -DHTTPLIB_REQUIRE_OPENSSL=${{ matrix.config.with_ssl && 'ON' || 'OFF' }}
- - name: Build ${{ matrix.config.name }}
- run: cmake --build build --config Release -- /v:m /clp:ShowCommandLine
- - name: Run tests ${{ matrix.config.name }}
- if: ${{ matrix.config.run_tests }}
- shell: pwsh
- working-directory: build/test
- run: |
- $shards = 4
- $procs = @()
- for ($i = 0; $i -lt $shards; $i++) {
- $log = "shard_${i}.log"
- $procs += Start-Process -FilePath ./Release/httplib-test.exe `
- -ArgumentList "--gtest_color=yes","--gtest_filter=${{ github.event.inputs.gtest_filter || '-*_Online' }}" `
- -NoNewWindow -PassThru -RedirectStandardOutput $log -RedirectStandardError "${log}.err" `
- -Environment @{ GTEST_TOTAL_SHARDS="$shards"; GTEST_SHARD_INDEX="$i" }
- }
- $procs | Wait-Process
- $failed = $false
- for ($i = 0; $i -lt $shards; $i++) {
- $log = "shard_${i}.log"
- $proc = $procs[$i]
- $hasPassed = Select-String -Path $log -Pattern "\[ PASSED \]" -Quiet
- $hasFailed = Select-String -Path $log -Pattern "\[ FAILED \]" -Quiet
- if ($hasPassed -and -not $hasFailed -and $proc.ExitCode -eq 0) {
- $passed = (Select-String -Path $log -Pattern "\[ PASSED \]").Line
- Write-Host "Shard ${i}: $passed"
- } else {
- Write-Host "=== Shard $i FAILED (exit=$($proc.ExitCode)) ==="
- Get-Content $log
- if (Test-Path "${log}.err") { Get-Content "${log}.err" }
- $failed = $true
- }
- }
- if ($failed) { exit 1 }
- Write-Host "All shards passed."
- env:
- VCPKG_ROOT: "C:/vcpkg"
- VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|