From ca723882d4911b60b051c7bc380fe7da09f45e1c Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Fri, 25 Oct 2019 00:02:30 +0100 Subject: [PATCH] HttpStress: Add Stress Pipelines (dotnet/corefx#41833) Commit migrated from https://github.com/dotnet/corefx/commit/f41ba828c76126a871d986cb5b7e9c44ddf6f3d7 --- eng/pipelines/libraries/stress/http-linux.yml | 28 ++++++++ eng/pipelines/libraries/stress/http-windows.yml | 34 +++++++++ .../tests/StressTests/HttpStress/Dockerfile | 8 +++ .../tests/StressTests/HttpStress/Readme.md | 8 +-- .../tests/StressTests/HttpStress/StressServer.cs | 2 +- .../tests/StressTests/HttpStress/corefx.Dockerfile | 28 ++++++++ .../HttpStress/load-corefx-testhost.ps1 | 80 +++++++++++++++++++++- .../StressTests/HttpStress/load-corefx-testhost.sh | 56 ++++++++++++++- 8 files changed, 232 insertions(+), 12 deletions(-) create mode 100644 eng/pipelines/libraries/stress/http-linux.yml create mode 100644 eng/pipelines/libraries/stress/http-windows.yml create mode 100644 src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile create mode 100644 src/libraries/System.Net.Http/tests/StressTests/HttpStress/corefx.Dockerfile diff --git a/eng/pipelines/libraries/stress/http-linux.yml b/eng/pipelines/libraries/stress/http-linux.yml new file mode 100644 index 0000000..e1936fd --- /dev/null +++ b/eng/pipelines/libraries/stress/http-linux.yml @@ -0,0 +1,28 @@ +trigger: none + +pool: + name: Hosted Ubuntu 1604 + +variables: + httpStressProject: src/System.Net.Http/tests/StressTests/HttpStress + sdkBaseImage: sdk-corefx-current + httpStressImage: httpstress + +steps: +- checkout: self + clean: true + fetchDepth: 0 + lfs: false + +- bash: | + docker build -t $(sdkBaseImage) -f $(Build.SourcesDirectory)/$(HttpStressProject)/corefx.Dockerfile . + displayName: Build Corefx + +- bash: | + cd '$(Build.SourcesDirectory)/$(HttpStressProject)' + docker build -t $(httpStressImage) --build-arg SDK_BASE_IMAGE=$(sdkBaseImage) . + displayName: Build HttpStress + +- bash: | + docker run --rm -e HTTPSTRESS_ARGS='$(HTTPSTRESS_ARGS)' $(httpStressImage) + displayName: Run HttpStress diff --git a/eng/pipelines/libraries/stress/http-windows.yml b/eng/pipelines/libraries/stress/http-windows.yml new file mode 100644 index 0000000..a18de65 --- /dev/null +++ b/eng/pipelines/libraries/stress/http-windows.yml @@ -0,0 +1,34 @@ +trigger: none + +pool: + name: Hosted VS2017 + +variables: + httpStressProject: src/System.Net.Http/tests/StressTests/HttpStress/ + +steps: +- checkout: self + clean: true + fetchDepth: 0 + lfs: false + +- powershell: | + .\build.cmd -ci -c $(BUILD_CONFIGURATION) + displayName: Build Corefx + +- powershell: | + cd '$(Build.SourcesDirectory)/$(HttpStressProject)' + # Load testhost sdk in environment + . .\load-corefx-testhost.ps1 -c $(BUILD_CONFIGURATION) -b + # Run the stress suite + dotnet run -c $(BUILD_CONFIGURATION) -- $(HTTPSTRESS_ARGS) + displayName: Run HttpStress + +- task: PublishBuildArtifacts@1 + displayName: Publish Logs + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(BUILD_CONFIGURATION)' + PublishLocation: Container + ArtifactName: 'httpstress_$(Agent.Os)_$(Agent.JobName)' + continueOnError: true + condition: always() diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile new file mode 100644 index 0000000..8f6571a --- /dev/null +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile @@ -0,0 +1,8 @@ +ARG SDK_BASE_IMAGE=mcr.microsoft.com/dotnet/core/sdk:3.0.100-buster +FROM $SDK_BASE_IMAGE + +WORKDIR /app +COPY . . + +ENV HTTPSTRESS_ARGS='-maxExecutionTime 30 -displayInterval 60' +CMD dotnet run -c Release -- $HTTPSTRESS_ARGS diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Readme.md b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Readme.md index 92ef65d..94d9f7a 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Readme.md +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Readme.md @@ -30,13 +30,9 @@ PS> .\build.sh -c Release # Load the testhost sdk in the current environment, must match build configuration PS> . .\src\System.Net.Http\tests\StressTests\HttpStress\load-corefx-testhost.ps1 -c Release # run the stress suite with the new bits -PS> cd .\src\System.Net.Http\tests\StressTests\HttpStress ; dotnet run --runtime win10-x64 +PS> cd .\src\System.Net.Http\tests\StressTests\HttpStress ; dotnet run -c Release -- ``` -Note that the `--runtime` argument is necessary because `testhost` -does not bundle the required aspnetcore runtime dependencies. -This will force the sdk to install the relevant native bits from nuget. - Equivalently using bash on linux: ```bash @@ -45,5 +41,5 @@ $ ./build.sh -c Release # Load the testhost sdk in the current environment, must match build configuration $ source src/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.sh -c Release # run the stress suite with the new bits -$ cd src/System.Net.Http/tests/StressTests/HttpStress && dotnet run -r linux-x64 +$ cd src/System.Net.Http/tests/StressTests/HttpStress && dotnet run -- ``` \ No newline at end of file diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs index 6acec37..f81a71e 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs @@ -289,7 +289,7 @@ namespace HttpStress private void SetUpJustInTimeLogging() { - if (_eventListener == null) + if (_eventListener == null && !Console.IsInputRedirected) { // If no command-line requested logging, enable the user to press 'L' to enable logging to the console // during execution, so that it can be done just-in-time when something goes awry. diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/corefx.Dockerfile b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/corefx.Dockerfile new file mode 100644 index 0000000..be62e71 --- /dev/null +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/corefx.Dockerfile @@ -0,0 +1,28 @@ +# Builds a dotnet sdk base image which contains corefx bits compiled from source +ARG BUILD_BASE_IMAGE=mcr.microsoft.com/dotnet-buildtools/prereqs:rhel7_prereqs_2 +ARG SDK_BASE_IMAGE=mcr.microsoft.com/dotnet/core/sdk:3.0.100-buster + +FROM $BUILD_BASE_IMAGE as corefxbuild + +WORKDIR /repo +COPY . . + +ARG CONFIG=Release +RUN ./build.sh -c $CONFIG + +FROM $SDK_BASE_IMAGE as target + +ARG TESTHOST_LOCATION=/repo/artifacts/bin/testhost +ARG TFM=netcoreapp +ARG OS=Linux +ARG ARCH=x64 +ARG CONFIG=Release + +ARG COREFX_SHARED_FRAMEWORK_NAME=Microsoft.NETCore.App +ARG SOURCE_COREFX_VERSION=5.0.0 +ARG TARGET_SHARED_FRAMEWORK=/usr/share/dotnet/shared +ARG TARGET_COREFX_VERSION=3.0.0 + +COPY --from=corefxbuild \ + $TESTHOST_LOCATION/$TFM-$OS-$CONFIG-$ARCH/shared/$COREFX_SHARED_FRAMEWORK_NAME/$SOURCE_COREFX_VERSION/* \ + $TARGET_SHARED_FRAMEWORK/$COREFX_SHARED_FRAMEWORK_NAME/$TARGET_COREFX_VERSION/ diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.ps1 b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.ps1 index e6c7826..dfb3fa4 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.ps1 +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.ps1 @@ -10,7 +10,8 @@ Param( [string][Alias('f')]$framework = "netcoreapp", [string][Alias('c')]$configuration = "Debug", [string][Alias('a')]$arch = "x64", - [string][Alias('o')]$os = "" + [string][Alias('o')]$os = "", + [switch][Alias('b')]$copyAspNetBits ) # script needs to be sourced, detect if running standalone @@ -47,6 +48,73 @@ if ($os -eq "") $os=$(Find-Os) } +# the corefx testhost does not bundle AspNetCore runtime bits; +# fix up by copying from the bootstrap sdk +function Copy-Aspnetcore-Bits([string] $testhost_path) +{ + + function find-bootstrap-sdk() + { + if (test-path -PathType container "$COREFX_ROOT_DIR/.dotnet") + { + "$COREFX_ROOT_DIR/.dotnet" + } + else + { + $dotnet_path = $(which dotnet) + + # follow any symlinks if unix + if (which readlink) + { + $dotnet_path = $(readlink -f $dotnet_path) + } + + $(dirname $dotnet_path) + } + } + + $netfx_bits_folder="Microsoft.NETCore.App" + $aspnet_bits_folder="Microsoft.AspNetCore.App" + + if (!(test-path -PathType container "$testhost_path/shared/$aspnet_bits_folder")) + { + $bootstrap_sdk=$(find-bootstrap-sdk) + + function get-most-recent-version($path) + { + (Get-ChildItem -Directory "$path" ` + | Select-Object -ExpandProperty Fullname ` + | Split-Path -Leaf ` + | ForEach-Object{[System.Version]$_} ` + | Sort-Object -Descending ` + | Select-Object -First 1).ToString() + } + + $netfx_runtime_version=$(get-most-recent-version "$testhost_path/shared/$netfx_bits_folder") + $aspnet_runtime_version=$(get-most-recent-version "$bootstrap_sdk/shared/$aspnet_bits_folder") + + # copy the bits + mkdir -p "$testhost_path/shared/$aspnet_bits_folder/" > $null + copy-item -R "$bootstrap_sdk/shared/$aspnet_bits_folder/$aspnet_runtime_version" "$testhost_path/shared/$aspnet_bits_folder/$netfx_runtime_version" + if (!$?) + { + write-host "failed to copy aspnetcore bits" + return + } + + $aspNetRuntimeConfig="$testhost_path/shared/$aspnet_bits_folder/$netfx_runtime_version/$aspnet_bits_folder.runtimeconfig.json" + if (test-path -PathType leaf "$aspNetRuntimeConfig") + { + # point aspnetcore runtimeconfig.json to current netfx version + # would prefer jq here but missing in many distros by default + $updated_content = $(get-content "$aspNetRuntimeConfig") -replace '"version"\s*:\s*"[^"]*"', "`"version`":`"$netfx_runtime_version`"" + write-output $updated_content | Out-File -FilePath "$aspNetRuntimeConfig" -Encoding utf8 + } + + write-host "Copied Microsoft.AspNetCore.App runtime bits from $bootstrap_sdk" + } +} + function Set-Sdk-Environment() { $candidate_path=$([IO.Path]::Combine($COREFX_ROOT_DIR, 'artifacts', 'bin', 'testhost', "$FRAMEWORK-$OS-$CONFIGURATION-$ARCH")) @@ -56,13 +124,18 @@ function Set-Sdk-Environment() write-output "Could not locate testhost sdk path $candidate_path" return } - elseif (!$(test-path -PathType leaf $([IO.Path]::Combine($candidate_path, "dotnet"))) -and - !$(test-path -PathType leaf $([IO.Path]::Combine($candidate_path, "dotnet.exe")))) + elseif (!$(test-path -PathType leaf "$candidate_path/dotnet") -and + !$(test-path -PathType leaf "$candidate_path/dotnet.exe")) { write-output "Could not find dotnet executable in testhost sdk path $candidate_path" return } + if($copyAspNetBits) + { + Copy-Aspnetcore-Bits $candidate_path + } + $pathSeparator=if($os -eq "Windows_NT") { ";" } else { ":" } $env:DOTNET_ROOT=$candidate_path @@ -72,4 +145,5 @@ function Set-Sdk-Environment() $env:DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2 } + Set-Sdk-Environment diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.sh b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.sh index e91fc26..ed06450 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.sh +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/load-corefx-testhost.sh @@ -14,7 +14,7 @@ fi # find corefx root, assuming script lives in the git repo SOURCE_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -COREFX_ROOT_DIR=$(git -C "$SOURCE_DIR" rev-parse --show-toplevel) +COREFX_ROOT_DIR=$(cd -P "$SOURCE_DIR" && git rev-parse --show-toplevel) usage() { @@ -23,6 +23,7 @@ usage() echo " -c Build configuration: defaults to Debug" echo " -a Build architecture: defaults to netcoreapp" echo " -o Operating system" + echo " -b Copy AspNetCore bits from bootstrap SDK" } detect_os() @@ -41,19 +42,61 @@ OS=$(detect_os) ARCH=x64 FRAMEWORK=netcoreapp CONFIGURATION=Debug +COPY_ASPNETCORE_BITS="false" OPTIND=1 -while getopts "hf:c:a:o:" opt; do +while getopts "hf:c:a:o:b" opt; do case $opt in f) FRAMEWORK=$OPTARG ;; c) CONFIGURATION=$OPTARG ;; a) ARCH=$OPTARG ;; o) OS=$OPTARG ;; + b) COPY_ASPNETCORE_BITS="true" ;; h) usage ; return 0 ;; *) usage ; return 1 ;; esac done +# the corefx testhost does not bundle AspNetCore runtime bits; +# fix up by copying from the bootstrap sdk +copy_aspnetcore_bits() +{ + testhost_path=$1 + + find_bootstrap_sdk() + { + if [ -d "$COREFX_ROOT_DIR/.dotnet" ]; then + echo $COREFX_ROOT_DIR/.dotnet + else + echo $(dirname "$(readlink -f "$(which dotnet)")") + fi + } + + netfx_bits_folder="Microsoft.NETCore.App" + aspnet_bits_folder="Microsoft.AspNetCore.App" + + if [ ! -d "$testhost_path/shared/$aspnet_bits_folder" ]; then + + bootstrap_sdk=$(find_bootstrap_sdk) + netfx_runtime_version=$(ls "$testhost_path/shared/$netfx_bits_folder" | sort -V | tail -n1) + aspnet_runtime_version=$(ls "$bootstrap_sdk/shared/$aspnet_bits_folder" | sort -V | tail -n1) + + # copy the bits + mkdir -p "$testhost_path/shared/$aspnet_bits_folder/" + cp -R "$bootstrap_sdk/shared/$aspnet_bits_folder/$aspnet_runtime_version" "$testhost_path/shared/$aspnet_bits_folder/$netfx_runtime_version" + [ $? -ne 0 ] && return 1 + + aspNetRuntimeConfig="$testhost_path/shared/$aspnet_bits_folder/$netfx_runtime_version/$aspnet_bits_folder.runtimeconfig.json" + if [ -f "$aspNetRuntimeConfig" ]; then + # point aspnetcore runtimeconfig.json to current netfx version + # would prefer jq here but missing in many distros by default + sed -i 's/"version"\s*:\s*"[^"]*"/"version":"'$netfx_runtime_version'"/g' "$aspNetRuntimeConfig" + fi + + echo "Copied Microsoft.AspNetCore.App runtime bits from $bootstrap_sdk" + fi +} + apply_to_environment() { candidate_path="$COREFX_ROOT_DIR/artifacts/bin/testhost/$FRAMEWORK-$OS-$CONFIGURATION-$ARCH" @@ -66,6 +109,15 @@ apply_to_environment() return 1 fi + if [ $COPY_ASPNETCORE_BITS = "true" ]; then + copy_aspnetcore_bits $candidate_path + + if [ $? -ne 0 ]; then + echo "failed to copy aspnetcore bits" + return 1 + fi + fi + export DOTNET_ROOT=$candidate_path export DOTNET_CLI_HOME=$candidate_path export DOTNET_MULTILEVEL_LOOKUP=0 -- 2.7.4