From 77d8404f59d0bac2e3e0bddd8e7b5ccd7b93a469 Mon Sep 17 00:00:00 2001 From: JustMe Date: Sat, 10 Oct 2026 04:11:55 +0800 Subject: [PATCH] ci(test): load MsQuic for Linux tests [CI] --- ci/fetch-quic-test-runtime.sh | 82 +++++++++++++++++++++++++++++++++++ ci/verify-backend.sh | 3 ++ 2 files changed, 85 insertions(+) create mode 100644 ci/fetch-quic-test-runtime.sh diff --git a/ci/fetch-quic-test-runtime.sh b/ci/fetch-quic-test-runtime.sh new file mode 100644 index 0000000..4f9dee9 --- /dev/null +++ b/ci/fetch-quic-test-runtime.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# Prepare the native MsQuic runtime for in-process Agent/Probe tests. +# Debian packages are extracted locally (no root install); downloads live in +# the persistent backend test cache so fast and slow workflows reuse them. +set -euo pipefail + +cache="${1:?usage: fetch-quic-test-runtime.sh }" +runtime="$cache/runtime" +downloads="$cache/downloads" +mkdir -p "$runtime" "$downloads" + +if command -v apk >/dev/null 2>&1; then + # The Alpine test image installs runtime libraries into the normal loader path. + apk add --no-cache libmsquic numactl lttng-ust zlib >/dev/null + exit 0 +fi + +case "$(uname -m)" in + x86_64) deb_arch=amd64 ;; + aarch64|arm64) deb_arch=arm64 ;; + *) echo "unsupported architecture for QUIC test runtime: $(uname -m)" >&2; exit 2 ;; +esac + +download() { + local url="$1" destination="$2" + if [[ ! -s "$destination" ]]; then + curl --fail --silent --show-error --retry 3 "$url" -o "$destination" + fi +} + +extract_library_sonames() { + local package="$1" unpack="$2" data entry normalized name soname + mkdir -p "$unpack" + if [[ ! -f "$unpack/.extracted" ]]; then + (cd "$unpack" && ar x "$package") + data="$(find "$unpack" -maxdepth 1 -type f -name 'data.tar.*' -print -quit)" + [[ -n "$data" ]] || { echo "package has no data archive: $package" >&2; exit 1; } + while IFS= read -r entry; do + normalized="${entry#./}" + case "$normalized" in + usr/lib/*|lib/*) ;; + *) continue ;; + esac + name="${normalized##*/}" + [[ "$name" =~ \.so\.[0-9]+(\.[0-9]+)+$ ]] || continue + [[ "$name" =~ ^libmsquic\.lttng\.so\. ]] && continue + soname="$(sed -E 's/^(.+\.so\.[0-9]+).*/\1/' <<<"$name")" + tar -xf "$data" -C "$unpack" "$entry" + install -m 0644 "$unpack/$normalized" "$runtime/$soname" + done < <(tar -tf "$data") + touch "$unpack/.extracted" + fi +} + +package_cache="$downloads/packages" +unpack_cache="$downloads/unpacked" +mkdir -p "$package_cache" "$unpack_cache" + +msquic_index='https://packages.microsoft.com/debian/12/prod/pool/main/libm/libmsquic/' +msquic_file="$(curl --fail --silent --show-error --retry 3 "$msquic_index" \ + | grep -oE "libmsquic_[0-9]+(\.[0-9]+){1,3}_${deb_arch}\.deb" \ + | sort -Vu | tail -n 1)" +[[ -n "$msquic_file" ]] || { echo "could not find a stable MsQuic package for $deb_arch" >&2; exit 1; } + +packages=( + "$msquic_index$msquic_file" + "https://deb.debian.org/debian/pool/main/n/numactl/libnuma1_2.0.16-1_${deb_arch}.deb" + "https://deb.debian.org/debian/pool/main/libz/libzstd/libzstd1_1.5.4+dfsg2-5_${deb_arch}.deb" + "https://deb.debian.org/debian/pool/main/z/zlib/zlib1g_1.2.13.dfsg-1_${deb_arch}.deb" +) + +for url in "${packages[@]}"; do + file="${url##*/}" + package="$package_cache/$file" + download "$url" "$package" + extract_library_sonames "$package" "$unpack_cache/${file%.deb}" +done + +for library in libmsquic.so.2 libnuma.so.1 libz.so.1 libzstd.so.1; do + [[ -f "$runtime/$library" ]] || { echo "missing QUIC test library: $library" >&2; exit 1; } +done +echo "prepared MsQuic test runtime ($deb_arch) in $runtime" diff --git a/ci/verify-backend.sh b/ci/verify-backend.sh index 3361733..ea765a8 100644 --- a/ci/verify-backend.sh +++ b/ci/verify-backend.sh @@ -66,6 +66,9 @@ fi # 测试在缓存目录里跑完整的解决方案(不再重复编译) log="$cache/last-test.log" +quic_runtime="$cache/quic-runtime" +bash "$root/ci/fetch-quic-test-runtime.sh" "$quic_runtime" +export LD_LIBRARY_PATH="$quic_runtime/runtime${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" status=0 # 别的程序集里没有匹配的测试会因为「零个测试」返回 8,忽略它 (cd "$src/backend" && dotnet test --solution MoShiro.slnx -c Release --no-build "${filter[@]}" --ignore-exit-code 8) 2>&1 | tee "$log" || status=${PIPESTATUS[0]}