on master help sign in
Merge pull request #737 from yesodweb/azure

Switch to Azure for CI

commit89c1f5028ccf17f0f664cfcc266398df8acd4c41 authorMichael Snoyman <michael@snoyman.com> dateMon 1 Apr 2019, 15:02 (8 years ago) parentd7ead17658908b
12 files changed+345−390
.azure/azure-linux-template.yml+111 .azure/azure-osx-template.yml+40 .azure/azure-pipelines.yml+30 .azure/azure-windows-template.yml+22 .travis.yml−251 README.md+1−1 appveyor.yml−37 stack-nightly.yaml−25 stack.yaml+25−1 warp/test/ResponseSpec.hs+12−18 warp/test/RunSpec.hs+98−55 warp/warp.cabal+6−2
.azure/azure-linux-template.ymlnew file+111
@@ -0,0 +1,111 @@
1+jobs:
2+- job: ${{ parameters.name }}
3+ timeoutInMinutes: 180
4+ pool:
5+ vmImage: ${{ parameters.vmImage }}
6+ strategy:
7+ matrix:
8+ stack-def:
9+ BUILD: stack
10+ stack-lts-6:
11+ BUILD: stack
12+ STACK_YAML: stack-lts-6.yaml
13+ ARGS: "--resolver lts-6"
14+ stack-lts-9:
15+ BUILD: stack
16+ STACK_YAML: stack-lts-9.yaml
17+ ARGS: "--resolver lts-9"
18+ stack-lts-11:
19+ BUILD: stack
20+ STACK_YAML: stack-lts-11.yaml
21+ ARGS: "--resolver lts-11"
22+ stack-lts-12:
23+ BUILD: stack
24+ STACK_YAML: stack-lts-12.yaml
25+ ARGS: "--resolver lts-12"
26+ stack-lts-13:
27+ BUILD: stack
28+ ARGS: "--resolver lts-13"
29+ cabal-7.10.3:
30+ BUILD: cabal
31+ GHCVER: 7.10.3
32+ CABALVER: 1.22
33+ cabal-8.0.2:
34+ BUILD: cabal
35+ GHCVER: 8.0.2
36+ CABALVER: 1.24
37+ cabal-8.2.2:
38+ BUILD: cabal
39+ GHCVER: 8.4.4
40+ CABALVER: 2.0
41+ cabal-8.4.4:
42+ BUILD: cabal
43+ GHCVER: 8.4.4
44+ CABALVER: 2.2
45+ cabal-8.6.4:
46+ BUILD: cabal
47+ GHCVER: 8.6.4
48+ CABALVER: 2.4
49+ maxParallel: 6
50+ steps:
51+ - script: |
52+ export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
53+ mkdir -p ~/.local/bin
54+ curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
55+ case "$BUILD" in
56+ cabal)
57+ sudo add-apt-repository -y ppa:hvr/ghc
58+ sudo apt-get update
59+ sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER
60+ # See note here: https://github.com/haskell-CI/haskell-ci#alex--happy-with-ghc--78
61+ if [ "$GHCVER" = "head" ] || [ "${GHCVER%.*}" = "7.8" ] || [ "${GHCVER%.*}" = "7.10" ]; then
62+ sudo apt-get install happy-1.19.4 alex-3.1.3
63+ export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH
64+ else
65+ sudo apt-get install happy alex
66+ fi
67+ export PATH=$HOME/.local/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
68+ cabal --version
69+ cabal update
70+ PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
71+ cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
72+ ;;
73+ *)
74+ export PATH=$HOME/.local/bin:$PATH
75+ stack --install-ghc $ARGS test --bench --only-dependencies
76+ ;;
77+ esac
78+ set -ex
79+ case "$BUILD" in
80+ cabal)
81+ cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
82+
83+ ORIGDIR=$(pwd)
84+ for dir in $PACKAGES
85+ do
86+ cd $dir
87+ cabal check || [ "$CABALVER" == "1.16" ]
88+ cabal sdist
89+ PKGVER=$(cabal info . | awk '{print $2;exit}')
90+ SRC_TGZ=$PKGVER.tar.gz
91+ cd dist
92+ tar zxfv "$SRC_TGZ"
93+ cd "$PKGVER"
94+ cabal configure --enable-tests --ghc-options -O0
95+ cabal build
96+ if [ "$CABALVER" = "1.16" ] || [ "$CABALVER" = "1.18" ]; then
97+ cabal test
98+ else
99+ cabal test --show-details=streaming
100+ fi
101+ cd $ORIGDIR
102+ done
103+ ;;
104+ *)
105+ stack $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
106+ ;;
107+ esac
108+ set +ex
109+ env:
110+ OS_NAME: ${{ parameters.os }}
111+ displayName: 'Installation ${{parameters.os}} & Test'
.azure/azure-osx-template.ymlnew file+40
@@ -0,0 +1,40 @@
1+jobs:
2+- job: ${{ parameters.name }}
3+ timeoutInMinutes: 180
4+ pool:
5+ vmImage: ${{ parameters.vmImage }}
6+ strategy:
7+ matrix:
8+ stack-def:
9+ BUILD: stack
10+ stack-lts-6:
11+ BUILD: stack
12+ STACK_YAML: stack-lts-6.yaml
13+ ARGS: "--resolver lts-6"
14+ stack-lts-9:
15+ BUILD: stack
16+ STACK_YAML: stack-lts-9.yaml
17+ ARGS: "--resolver lts-9"
18+ stack-lts-11:
19+ BUILD: stack
20+ STACK_YAML: stack-lts-11.yaml
21+ ARGS: "--resolver lts-11"
22+ stack-lts-12:
23+ BUILD: stack
24+ STACK_YAML: stack-lts-12.yaml
25+ ARGS: "--resolver lts-12"
26+ stack-lts-13:
27+ BUILD: stack
28+ ARGS: "--resolver lts-13"
29+ maxParallel: 3
30+ steps:
31+ - script: |
32+ export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
33+ mkdir -p ~/.local/bin
34+ curl -skL https://get.haskellstack.org/stable/osx-x86_64.tar.gz | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin;
35+ export PATH=$HOME/.local/bin:$PATH
36+ stack --install-ghc $ARGS test --bench --only-dependencies
37+ stack $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
38+ env:
39+ OS_NAME: ${{ parameters.os }}
40+ displayName: 'Installation ${{parameters.os}} & Test'
.azure/azure-pipelines.ymlnew file+30
@@ -0,0 +1,30 @@
1+# This is the complex Azure configuration, which is intended for use
2+# on open source libraries which need compatibility across multiple GHC
3+# versions, must work with cabal-install, and should be
4+# cross-platform. For more information and other options, see:
5+#
6+# https://docs.haskellstack.org/en/stable/azure_ci/
7+#
8+# Copy these contents into the root directory of your Github project in a file
9+# named azure-pipelines.yml
10+#
11+# For better organization, you split various jobs into seprate parts
12+# and each of them are controlled via individual file.
13+jobs:
14+- template: azure-linux-template.yml
15+ parameters:
16+ name: Linux
17+ vmImage: ubuntu-16.04
18+ os: linux
19+
20+- template: azure-osx-template.yml
21+ parameters:
22+ name: macOS
23+ vmImage: macOS-10.13
24+ os: osx
25+
26+- template: azure-windows-template.yml
27+ parameters:
28+ name: Windows
29+ vmImage: vs2017-win2016
30+ os: windows
.azure/azure-windows-template.ymlnew file+22
@@ -0,0 +1,22 @@
1+jobs:
2+- job: ${{ parameters.name }}
3+ timeoutInMinutes: 180
4+ pool:
5+ vmImage: ${{ parameters.vmImage }}
6+ strategy:
7+ matrix:
8+ stack-lts-13:
9+ BUILD: stack
10+ ARGS: "--resolver lts-13"
11+ maxParallel: 3
12+ steps:
13+ - bash: |
14+ export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
15+ curl -sSkL http://www.stackage.org/stack/windows-x86_64 -o /usr/bin/stack.zip
16+ unzip -o /usr/bin/stack.zip -d /usr/bin/
17+ stack setup $ARGS > /dev/null
18+ stack --install-ghc $ARGS test --bench --only-dependencies
19+ stack $ARGS test --bench --no-run-benchmarks
20+ env:
21+ OS_NAME: ${{ parameters.os }}
22+ displayName: 'Installation ${{parameters.os}} & Test'
.travis.ymldeleted−251
@@ -1,251 +0,0 @@
1−# This is the complex Travis configuration, which is intended for use
2−# on open source libraries which need compatibility across multiple GHC
3−# versions, must work with cabal-install, and should be
4−# cross-platform. For more information and other options, see:
5−#
6−# https://docs.haskellstack.org/en/stable/travis_ci/
7−#
8−# Copy these contents into the root directory of your Github project in a file
9−# named .travis.yml
10−
11−# Use new container infrastructure to enable caching
12−sudo: false
13−
14−# Do not choose a language; we provide our own build tools.
15−language: generic
16−
17−# Caching so the next build will be fast too.
18−cache:
19− directories:
20− - $HOME/.ghc
21− - $HOME/.cabal
22− - $HOME/.stack
23− - $TRAVIS_BUILD_DIR/.stack-work
24−
25−# The different configurations we want to test. We have BUILD=cabal which uses
26−# cabal-install, and BUILD=stack which uses Stack. More documentation on each
27−# of those below.
28−#
29−# We set the compiler values here to tell Travis to use a different
30−# cache file per set of arguments.
31−#
32−# If you need to have different apt packages for each combination in the
33−# matrix, you can use a line such as:
34−# addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
35−matrix:
36− include:
37− # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See:
38− # https://github.com/hvr/multi-ghc-travis
39− #- env: BUILD=cabal GHCVER=7.0.4 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
40− # compiler: ": #GHC 7.0.4"
41− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.0.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
42− #- env: BUILD=cabal GHCVER=7.2.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
43− # compiler: ": #GHC 7.2.2"
44− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
45− #- env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
46− # compiler: ": #GHC 7.4.2"
47− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
48− #- env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
49− # compiler: ": #GHC 7.6.3"
50− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
51− #- env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 HAPPYVER=1.19.5 ALEXVER=3.1.7
52− # compiler: ": #GHC 7.8.4"
53− # addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
54− - env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7
55− compiler: ": #GHC 7.10.3"
56− addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
57− - env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7
58− compiler: ": #GHC 8.0.2"
59− addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
60− - env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 HAPPYVER=1.19.5 ALEXVER=3.1.7
61− compiler: ": #GHC 8.2.2"
62− addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
63− - env: BUILD=cabal GHCVER=8.4.3 CABALVER=2.2 HAPPYVER=1.19.5 ALEXVER=3.1.7
64− compiler: ": #GHC 8.4.3"
65− addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
66−
67− # Build with the newest GHC and cabal-install. This is an accepted failure,
68− # see below.
69− - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
70− compiler: ": #GHC HEAD"
71− addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
72−
73− # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
74− # variable, such as using --stack-yaml to point to a different file.
75− #- env: BUILD=stack ARGS=""
76− # compiler: ": #stack default"
77− # addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
78−
79− #- env: BUILD=stack ARGS="--resolver lts-2"
80− # compiler: ": #stack 7.8.4"
81− # addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
82−
83− #- env: BUILD=stack ARGS="--resolver lts-3"
84− # compiler: ": #stack 7.10.2"
85− # addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
86−
87− - env: BUILD=stack ARGS="--resolver lts-6" STACK_YAML="stack-lts-6.yaml"
88− compiler: ": #stack 7.10.3"
89− addons: {apt: {packages: [libgmp-dev]}}
90−
91− #- env: BUILD=stack ARGS="--resolver lts-7"
92− # compiler: ": #stack 8.0.1"
93− # addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
94−
95− - env: BUILD=stack ARGS="--resolver lts-9" STACK_YAML="stack-lts-9.yaml"
96− compiler: ": #stack 8.0.2"
97− addons: {apt: {packages: [libgmp-dev]}}
98−
99− - env: BUILD=stack ARGS="--resolver lts-11" STACK_YAML="stack-lts-11.yaml"
100− compiler: ": #stack 8.2.2"
101− addons: {apt: {packages: [libgmp-dev]}}
102−
103− - env: BUILD=stack ARGS="--resolver lts-12" STACK_YAML="stack-lts-12.yaml"
104− compiler: ": #stack 8.4.3"
105− addons: {apt: {packages: [libgmp-dev]}}
106−
107− # Nightly builds are allowed to fail
108− - env: BUILD=stack ARGS="--resolver nightly" STACK_YAML="stack-nightly.yaml"
109− compiler: ": #stack nightly"
110− addons: {apt: {packages: [libgmp-dev]}}
111−
112− # Build on macOS in addition to Linux
113− #- env: BUILD=stack ARGS=""
114− # compiler: ": #stack default osx"
115− # os: osx
116−
117− # Travis includes an macOS which is incompatible with GHC 7.8.4
118− #- env: BUILD=stack ARGS="--resolver lts-2"
119− # compiler: ": #stack 7.8.4 osx"
120− # os: osx
121−
122− #- env: BUILD=stack ARGS="--resolver lts-3"
123− # compiler: ": #stack 7.10.2 osx"
124− # os: osx
125−
126− - env: BUILD=stack ARGS="--resolver lts-6" STACK_YAML="stack-lts-6.yaml"
127− compiler: ": #stack 7.10.3 osx"
128− os: osx
129−
130− #- env: BUILD=stack ARGS="--resolver lts-7"
131− # compiler: ": #stack 8.0.1 osx"
132− # os: osx
133−
134− - env: BUILD=stack ARGS="--resolver lts-9" STACK_YAML="stack-lts-9.yaml"
135− compiler: ": #stack 8.0.2 osx"
136− os: osx
137−
138− - env: BUILD=stack ARGS="--resolver lts-11" STACK_YAML="stack-lts-11.yaml"
139− compiler: ": #stack 8.2.2 osx"
140− os: osx
141−
142− - env: BUILD=stack ARGS="--resolver lts-12" STACK_YAML="stack-lts-12.yaml"
143− compiler: ": #stack 8.4.3 osx"
144− os: osx
145−
146− - env: BUILD=stack ARGS="--resolver nightly"
147− compiler: ": #stack nightly osx"
148− os: osx
149−
150− allow_failures:
151− - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
152− #- env: BUILD=stack ARGS="--resolver nightly"
153−
154−before_install:
155−# Using compiler above sets CC to an invalid value, so unset it
156−- unset CC
157−
158−# We want to always allow newer versions of packages when building on GHC HEAD
159−- CABALARGS=""
160−- if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi
161−
162−# Download and unpack the stack executable
163−- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH
164−- mkdir -p ~/.local/bin
165−- |
166− if [ `uname` = "Darwin" ]
167− then
168− travis_retry curl --insecure -L https://get.haskellstack.org/stable/osx-x86_64.tar.gz | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
169− else
170− travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
171− fi
172−
173− # Use the more reliable S3 mirror of Hackage
174− mkdir -p $HOME/.cabal
175− echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config
176− echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config
177−
178−
179−install:
180−- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
181−- if [ -f configure.ac ]; then autoreconf -i; fi
182−- |
183− set -ex
184− case "$BUILD" in
185− stack)
186− # Avoid out of memory condition
187− stack --no-terminal --install-ghc $ARGS build Cabal
188−
189− # Add in extra-deps for older snapshots, as necessary
190− #
191− # This is disabled by default, as relying on the solver like this can
192− # make builds unreliable. Instead, if you have this situation, it's
193− # recommended that you maintain multiple stack-lts-X.yaml files.
194−
195− #stack --no-terminal --install-ghc $ARGS test --bench --dry-run || ( \
196− # stack --no-terminal $ARGS build cabal-install && \
197− # stack --no-terminal $ARGS solver --update-config)
198−
199− # Build the dependencies
200− stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies
201− ;;
202− cabal)
203− cabal --version
204− travis_retry cabal update
205−
206− # Get the list of packages from the stack.yaml file. Note that
207− # this will also implicitly run hpack as necessary to generate
208− # the .cabal files needed by cabal-install.
209− PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
210−
211− # Due to dependency on wai-logger (which depends on some packages here),
212− # we can't build just dependencies
213− #
214− # cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
215− ;;
216− esac
217− set +ex
218−
219−script:
220−- |
221− set -ex
222− case "$BUILD" in
223− stack)
224− stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
225− ;;
226− cabal)
227− cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
228−
229− ORIGDIR=$(pwd)
230− for dir in $PACKAGES
231− do
232− cd $dir
233− cabal check || [ "$CABALVER" == "1.16" ]
234− cabal sdist
235− PKGVER=$(cabal info . | awk '{print $2;exit}')
236− SRC_TGZ=$PKGVER.tar.gz
237− cd dist
238− tar zxfv "$SRC_TGZ"
239− cd "$PKGVER"
240− cabal configure --enable-tests --ghc-options -O0
241− cabal build
242− if [ "$CABALVER" = "1.16" ] || [ "$CABALVER" = "1.18" ]; then
243− cabal test
244− else
245− cabal test --show-details=streaming --log=/dev/stdout
246− fi
247− cd $ORIGDIR
248− done
249− ;;
250− esac
251− set +ex
README.md+1−1
@@ -10,4 +10,4 @@ Code can be written that works with any web framework targeting WAI.
1010
1111[Haddock Documentation](http://hackage.haskell.org/package/wai)
1212
13−[![Build Status](https://travis-ci.org/yesodweb/wai.svg?branch=master)](https://travis-ci.org/yesodweb/wai)
13+[![Build Status](https://dev.azure.com/yesodweb/wai/_apis/build/status/yesodweb.wai?branchName=master)](https://dev.azure.com/yesodweb/wai/_build/latest?definitionId=1&branchName=master)
appveyor.ymldeleted−37
@@ -1,37 +0,0 @@
1−build: off
2−
3−before_test:
4−# http://help.appveyor.com/discussions/problems/6312-curl-command-not-found
5−- set PATH=C:\Program Files\Git\mingw64\bin;%PATH%
6−
7−- curl -sS -ostack.zip -L --insecure https://get.haskellstack.org/stable/windows-x86_64.zip
8−- 7z x stack.zip stack.exe
9−
10−clone_folder: "c:\\stack"
11−environment:
12− global:
13− STACK_ROOT: "c:\\sr"
14−
15− # Override the temp directory to avoid sed escaping issues
16− # See https://github.com/haskell/cabal/issues/5386
17− TMP: "c:\\tmp"
18−
19− matrix:
20− #- ARGS: ""
21− #- ARGS: "--resolver lts-2"
22− #- ARGS: "--resolver lts-3"
23− - ARGS: "--stack-yaml stack-lts-6.yaml"
24− #- ARGS: "--resolver lts-7"
25− - ARGS: "--stack-yaml stack-lts-9.yaml"
26− - ARGS: "--stack-yaml stack-lts-11.yaml"
27− - ARGS: "--stack-yaml stack-lts-12.yaml"
28− #- ARGS: "--resolver nightly"
29−
30−test_script:
31−
32−# Install toolchain, but do it silently due to lots of output
33−- stack %ARGS% setup > nul
34−
35−# The ugly echo "" hack is to avoid complaints about 0 being an invalid file
36−# descriptor
37−- echo "" | stack %ARGS% --no-terminal test
stack-nightly.yamldeleted−25
@@ -1,25 +0,0 @@
1−resolver: nightly-2018-08-17
2−packages:
3−- ./auto-update
4−- ./mime-types
5−- ./wai
6−- ./wai-extra
7−- ./warp
8−- ./warp-tls
9−- ./wai-app-static
10−- ./wai-websockets
11−- ./wai-conduit
12−flags:
13− wai-extra:
14− build-example: true
15−nix:
16− enable: false
17− packages:
18− - fcgi
19− - zlib
20−image:
21− containers:
22− - base: "fpco/pid1"
23− name: "yesodweb/warp"
24− executables:
25− - warp
stack.yamlmode 120000 → 100644+25−1
@@ -1 +0,0 @@
1−stack-lts-12.yaml
@@ -0,0 +1,25 @@
1+resolver: lts-13.14
2+packages:
3+- ./auto-update
4+- ./mime-types
5+- ./wai
6+- ./wai-extra
7+- ./warp
8+- ./warp-tls
9+- ./wai-app-static
10+- ./wai-websockets
11+- ./wai-conduit
12+flags:
13+ wai-extra:
14+ build-example: true
15+nix:
16+ enable: false
17+ packages:
18+ - fcgi
19+ - zlib
20+image:
21+ containers:
22+ - base: "fpco/pid1"
23+ name: "yesodweb/warp"
24+ executables:
25+ - warp
warp/test/ResponseSpec.hs+12−18
@@ -10,13 +10,9 @@ import Network.HTTP.Types
1010import Network.Wai hiding (responseHeaders)
1111import Network.Wai.Handler.Warp
1212import Network.Wai.Handler.Warp.Response
13−import RunSpec (withApp)
14−import System.IO (hClose, hFlush)
13+import RunSpec (withApp, msClose, msWrite, msRead, connectTo)
1514import Test.Hspec
1615
17−-- import HTTP
18−import RunSpec (connectTo)
19−
2016main :: IO ()
2117main = hspec spec
2218
@@ -25,15 +21,14 @@ testRange :: S.ByteString -- ^ range value
2521 -> Maybe String -- ^ expected content-range value
2622 -> Spec
2723testRange range out crange = it title $ withApp defaultSettings app $ \port -> do
28− handle <- connectTo "127.0.0.1" port
29− S.hPutStr handle "GET / HTTP/1.0\r\n"
30− S.hPutStr handle "Range: bytes="
31− S.hPutStr handle range
32− S.hPutStr handle "\r\n\r\n"
33− hFlush handle
24+ handle <- connectTo port
25+ msWrite handle "GET / HTTP/1.0\r\n"
26+ msWrite handle "Range: bytes="
27+ msWrite handle range
28+ msWrite handle "\r\n\r\n"
3429 threadDelay 10000
35− bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ S.hGetSome handle 1024
36− hClose handle
30+ bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ msRead handle 1024
31+ msClose handle
3732 last bss `shouldBe` out
3833 let hs = mapMaybe toHeader bss
3934 lookup "Content-Range" hs `shouldBe` fmap ("bytes " ++) crange
@@ -52,12 +47,11 @@ testPartial :: Integer -- ^ file size
5247 -> String -- ^ expected output
5348 -> Spec
5449testPartial size offset count out = it title $ withApp defaultSettings app $ \port -> do
55− handle <- connectTo "127.0.0.1" port
56− S.hPutStr handle "GET / HTTP/1.0\r\n\r\n"
57− hFlush handle
50+ handle <- connectTo port
51+ msWrite handle "GET / HTTP/1.0\r\n\r\n"
5852 threadDelay 10000
59− bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ S.hGetSome handle 1024
60− hClose handle
53+ bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ msRead handle 1024
54+ msClose handle
6155 out `shouldBe` last bss
6256 let hs = mapMaybe toHeader bss
6357 lookup "Content-Length" hs `shouldBe` Just (show $ length $ last bss)
warp/test/RunSpec.hs+98−55
@@ -2,7 +2,7 @@
22{-# LANGUAGE OverloadedStrings #-}
33{-# LANGUAGE ScopedTypeVariables #-}
44
5−module RunSpec (main, spec, withApp, connectTo) where
5+module RunSpec (main, spec, withApp, connectTo, MySocket, msWrite, msRead, msClose) where
66
77import Control.Concurrent (forkIO, killThread, threadDelay)
88import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
@@ -11,7 +11,7 @@ import qualified Control.Exception as E
1111import Control.Exception.Lifted (bracket, try, IOException, onException)
1212import Control.Monad (forM_, replicateM_, unless)
1313import Control.Monad.IO.Class (MonadIO, liftIO)
14−import Data.ByteString (ByteString, hPutStr, hGetSome)
14+import Data.ByteString (ByteString)
1515import qualified Data.ByteString as S
1616import Data.ByteString.Builder (byteString)
1717import qualified Data.ByteString.Char8 as S8
@@ -23,7 +23,6 @@ import Network.Socket
2323import Network.Socket.ByteString (sendAll)
2424import Network.Wai hiding (responseHeaders)
2525import Network.Wai.Handler.Warp
26−import System.IO (hFlush, hClose, Handle, IOMode(..))
2726import System.IO.Unsafe (unsafePerformIO)
2827import System.Timeout (timeout)
2928import Test.Hspec
@@ -36,13 +35,44 @@ main = hspec spec
3635type Counter = I.IORef (Either String Int)
3736type CounterApplication = Counter -> Application
3837
39−connectTo :: HostName -> Int -> IO Handle
40−connectTo host port = do
41− let hints = defaultHints { addrSocketType = Stream }
42− addr:_ <- getAddrInfo (Just hints) (Just host) (Just $ show port)
43− sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
44− connect sock $ addrAddress addr
45− socketToHandle sock ReadWriteMode
38+data MySocket = MySocket
39+ { msSocket :: !Socket
40+ , _msBuffer :: !(I.IORef ByteString)
41+ }
42+
43+msWrite :: MySocket -> ByteString -> IO ()
44+msWrite ms bs = sendAll (msSocket ms) bs
45+
46+msRead :: MySocket -> Int -> IO ByteString
47+msRead (MySocket s ref) expected = do
48+ bs <- I.readIORef ref
49+ inner (bs:) (S.length bs)
50+ where
51+ inner front total =
52+ case compare total expected of
53+ EQ -> do
54+ I.writeIORef ref mempty
55+ pure $ S.concat $ front []
56+ GT -> do
57+ let bs = S.concat $ front []
58+ (x, y) = S.splitAt expected bs
59+ I.writeIORef ref y
60+ pure x
61+ LT -> do
62+ bs <- safeRecv s 4096
63+ if S.null bs
64+ then do
65+ I.writeIORef ref mempty
66+ pure $ S.concat $ front []
67+ else inner (front . (bs:)) (total + S.length bs)
68+
69+msClose :: MySocket -> IO ()
70+msClose = Network.Socket.close . msSocket
71+
72+connectTo :: Int -> IO MySocket
73+connectTo port = MySocket
74+ <$> (fst <$> getSocketTCP "127.0.0.1" port)
75+ <*> I.newIORef mempty
4676
4777incr :: MonadIO m => Counter -> m ()
4878incr icount = liftIO $ I.atomicModifyIORef icount $ \ecount ->
@@ -106,7 +136,13 @@ withApp settings app f = do
106136 bracket
107137 (forkIO $ runSettings settings' app `onException` putMVar baton ())
108138 killThread
109− (const $ takeMVar baton >> f port)
139+ (const $ do
140+ takeMVar baton
141+ -- use timeout to make sure we don't take too long
142+ mres <- timeout (60 * 1000 * 1000) (f port)
143+ case mres of
144+ Nothing -> error "Timeout triggered, too slow!"
145+ Just a -> pure a)
110146
111147runTest :: Int -- ^ expected number of requests
112148 -> CounterApplication
@@ -115,9 +151,9 @@ runTest :: Int -- ^ expected number of requests
115151runTest expected app chunks = do
116152 ref <- I.newIORef (Right 0)
117153 withApp defaultSettings (app ref) $ \port -> do
118− handle <- connectTo "127.0.0.1" port
119− forM_ chunks $ \chunk -> hPutStr handle chunk >> hFlush handle
120− _ <- timeout 100000 $ replicateM_ expected $ hGetSome handle 4096
154+ ms <- connectTo port
155+ forM_ chunks $ \chunk -> msWrite ms chunk
156+ _ <- timeout 100000 $ replicateM_ expected $ msRead ms 4096
121157 res <- I.readIORef ref
122158 case res of
123159 Left s -> error s
@@ -133,10 +169,9 @@ runTerminateTest expected input = do
133169 ref <- I.newIORef Nothing
134170 let onExc _ = I.writeIORef ref . Just
135171 withApp (setOnException onExc defaultSettings) dummyApp $ \port -> do
136− handle <- connectTo "127.0.0.1" port
137− hPutStr handle input
138− hFlush handle
139− hClose handle
172+ handle <- connectTo port
173+ msWrite handle input
174+ msClose handle
140175 threadDelay 1000
141176 res <- I.readIORef ref
142177 show res `shouldBe` show (Just expected)
@@ -208,13 +243,12 @@ spec = do
208243 liftIO $ I.writeIORef iheaders $ requestHeaders req
209244 f $ responseLBS status200 [] ""
210245 withApp defaultSettings app $ \port -> do
211− handle <- connectTo "127.0.0.1" port
246+ handle <- connectTo port
212247 let input = S.concat
213248 [ "GET / HTTP/1.1\r\nfoo: bar\r\n baz\r\n\tbin\r\n\r\n"
214249 ]
215− hPutStr handle input
216− hFlush handle
217− hClose handle
250+ msWrite handle input
251+ msClose handle
218252 threadDelay 1000
219253 headers <- I.readIORef iheaders
220254 headers `shouldBe`
@@ -226,13 +260,12 @@ spec = do
226260 liftIO $ I.writeIORef iheaders $ requestHeaders req
227261 f $ responseLBS status200 [] ""
228262 withApp defaultSettings app $ \port -> do
229− handle <- connectTo "127.0.0.1" port
263+ handle <- connectTo port
230264 let input = S.concat
231265 [ "GET / HTTP/1.1\r\nfoo:bar\r\n\r\n"
232266 ]
233− hPutStr handle input
234− hFlush handle
235− hClose handle
267+ msWrite handle input
268+ msClose handle
236269 threadDelay 1000
237270 headers <- I.readIORef iheaders
238271 headers `shouldBe`
@@ -241,28 +274,33 @@ spec = do
241274
242275 describe "chunked bodies" $ do
243276 it "works" $ do
277+ countVar <- newTVarIO (0 :: Int)
244278 ifront <- I.newIORef id
245279 let app req f = do
246280 bss <- consumeBody $ requestBody req
247281 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
282+ atomically $ modifyTVar countVar (+ 1)
248283 f $ responseLBS status200 [] ""
249284 withApp defaultSettings app $ \port -> do
250− handle <- connectTo "127.0.0.1" port
285+ handle <- connectTo port
251286 let input = S.concat
252287 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
253288 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n\r\n"
254289 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
255290 , "b\r\nHello World\r\n0\r\n\r\n"
256291 ]
257− hPutStr handle input
258− hFlush handle
259− hClose handle
260− threadDelay 1000
292+ msWrite handle input
293+ msClose handle
294+ atomically $ do
295+ count <- readTVar countVar
296+ check $ count == 2
261297 front <- I.readIORef ifront
262298 front [] `shouldBe`
263299 [ "Hello World\nBye"
264300 , "Hello World"
265301 ]
302+#if !WINDOWS
303+-- Too slow on Windows
266304 it "lots of chunks" $ do
267305 ifront <- I.newIORef id
268306 countVar <- newTVarIO (0 :: Int)
@@ -272,13 +310,13 @@ spec = do
272310 atomically $ modifyTVar countVar (+ 1)
273311 f $ responseLBS status200 [] ""
274312 withApp defaultSettings app $ \port -> do
275− handle <- connectTo "127.0.0.1" port
313+ handle <- connectTo port
276314 let input = concat $ replicate 2 $
277315 ["POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"] ++
278316 (replicate 50 "5\r\n12345\r\n") ++
279317 ["0\r\n\r\n"]
280− mapM_ (\bs -> hPutStr handle bs >> hFlush handle) input
281− hClose handle
318+ mapM_ (msWrite handle) input
319+ msClose handle
282320 atomically $ do
283321 count <- readTVar countVar
284322 check $ count == 2
@@ -286,7 +324,6 @@ spec = do
286324 front [] `shouldBe` replicate 2 (S.concat $ replicate 50 "12345")
287325-- For some reason, the following test on Windows causes the socket
288326-- to be killed prematurely. Worth investigating in the future if possible.
289−#if !WINDOWS
290327 it "in chunks" $ do
291328 ifront <- I.newIORef id
292329 countVar <- newTVarIO (0 :: Int)
@@ -296,15 +333,15 @@ spec = do
296333 atomically $ modifyTVar countVar (+ 1)
297334 f $ responseLBS status200 [] ""
298335 withApp defaultSettings app $ \port -> do
299− handle <- connectTo "127.0.0.1" port
336+ handle <- connectTo port
300337 let input = S.concat
301338 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
302339 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n"
303340 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
304341 , "b\r\nHello World\r\n0\r\n\r\n"
305342 ]
306− mapM_ (\bs -> hPutStr handle bs >> hFlush handle) $ map S.singleton $ S.unpack input
307− hClose handle
343+ mapM_ (msWrite handle) $ map S.singleton $ S.unpack input
344+ msClose handle
308345 atomically $ do
309346 count <- readTVar countVar
310347 check $ count == 2
@@ -330,16 +367,16 @@ spec = do
330367 let bs1 = S.replicate 2048 88
331368 bs2 = "This is short"
332369 bs = S.append bs1 bs2
333− handle <- connectTo "127.0.0.1" port
334− hPutStr handle "POST / HTTP/1.1\r\n"
335− hPutStr handle "content-length: "
336− hPutStr handle $ S8.pack $ show $ S.length bs
337− hPutStr handle "\r\n\r\n"
370+ handle <- connectTo port
371+ msWrite handle "POST / HTTP/1.1\r\n"
372+ msWrite handle "content-length: "
373+ msWrite handle $ S8.pack $ show $ S.length bs
374+ msWrite handle "\r\n\r\n"
338375 threadDelay 100000
339− hPutStr handle bs1
376+ msWrite handle bs1
340377 threadDelay 100000
341− hPutStr handle bs2
342− hClose handle
378+ msWrite handle bs2
379+ msClose handle
343380 threadDelay 5000000
344381 front <- I.readIORef ifront
345382 S.concat (front []) `shouldBe` bs
@@ -356,30 +393,33 @@ spec = do
356393 loop
357394 doubleBS = S.concatMap $ \w -> S.pack [w, w]
358395 withApp defaultSettings app $ \port -> do
359− handle <- connectTo "127.0.0.1" port
360− hPutStr handle "POST / HTTP/1.1\r\n\r\n12345"
361− hFlush handle
362− timeout 100000 (S.hGet handle 10) >>= (`shouldBe` Just "1122334455")
363− hPutStr handle "67890"
364− hFlush handle
365− timeout 100000 (S.hGet handle 10) >>= (`shouldBe` Just "6677889900")
396+ ms <- connectTo port
397+ msWrite ms "POST / HTTP/1.1\r\n\r\n12345"
398+ timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "1122334455")
399+ msWrite ms "67890"
400+ timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "6677889900")
366401
367402 it "only one date and server header" $ do
368403 let app _ f = f $ responseLBS status200
369404 [ ("server", "server")
370405 , ("date", "date")
371406 ] ""
407+ getValues key = map snd
408+ . filter (\(key', _) -> key == key')
409+ . responseHeaders
372410 withApp defaultSettings app $ \port -> do
373411 res <- sendGET $ "http://127.0.0.1:" ++ show port
374− getHeaderValue hServer (responseHeaders res) `shouldBe` Just "server"
375− getHeaderValue hDate (responseHeaders res) `shouldBe` Just "date"
412+ getValues hServer res `shouldBe` ["server"]
413+ getValues hDate res `shouldBe` ["date"]
376414
377415 it "streaming echo #249" $ do
416+ countVar <- newTVarIO (0 :: Int)
378417 let app req f = f $ responseStream status200 [] $ \write _ -> do
379418 let loop = do
380419 bs <- requestBody req
381420 unless (S.null bs) $ do
382421 write $ byteString bs
422+ atomically $ modifyTVar countVar (+ 1)
383423 loop
384424 loop
385425 withApp defaultSettings app $ \port -> do
@@ -387,6 +427,9 @@ spec = do
387427 sendAll sock "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
388428 threadDelay 10000
389429 sendAll sock "5\r\nhello\r\n0\r\n\r\n"
430+ atomically $ do
431+ count <- readTVar countVar
432+ check $ count >= 1
390433 bs <- safeRecv sock 4096
391434 S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"
392435
warp/warp.cabal+6−2
@@ -120,6 +120,8 @@ Test-Suite doctest
120120 Main-Is: doctests.hs
121121 Build-Depends: base >= 4.8 && < 5
122122 , doctest >= 0.10.1
123+ if os(windows)
124+ Buildable: False
123125
124126Test-Suite spec
125127 Main-Is: Spec.hs
@@ -219,7 +221,8 @@ Test-Suite spec
219221 Cpp-Options: -DSENDFILEFD
220222 Build-Depends: unix
221223 if os(windows)
222− Cpp-Options: -DWINDOWS
224+ Cpp-Options: -DWINDOWS
225+ Build-Depends: time
223226
224227Benchmark parser
225228 Type: exitcode-stdio-1.0
@@ -251,7 +254,8 @@ Benchmark parser
251254 Cpp-Options: -DSENDFILEFD
252255 Build-Depends: unix
253256 if os(windows)
254− Cpp-Options: -DWINDOWS
257+ Cpp-Options: -DWINDOWS
258+ Build-Depends: time
255259
256260Source-Repository head
257261 Type: git