on master help sign in
Merge pull request #737 from yesodweb/azure
89c1f50Michael Snoyman
.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.
10
10
11[Haddock Documentation](http://hackage.haskell.org/package/wai)
11[Haddock Documentation](http://hackage.haskell.org/package/wai)
12
12
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
10import Network.Wai hiding (responseHeaders)
10import Network.Wai hiding (responseHeaders)
11import Network.Wai.Handler.Warp
11import Network.Wai.Handler.Warp
12import Network.Wai.Handler.Warp.Response
12import Network.Wai.Handler.Warp.Response
13−import RunSpec (withApp)
13+import RunSpec (withApp, msClose, msWrite, msRead, connectTo)
14−import System.IO (hClose, hFlush)
15import Test.Hspec
14import Test.Hspec
16
15
17−-- import HTTP
18−import RunSpec (connectTo)
19−
20main :: IO ()
16main :: IO ()
21main = hspec spec
17main = hspec spec
22
18
@@ -25,15 +21,14 @@ testRange :: S.ByteString -- ^ range value
25 -> Maybe String -- ^ expected content-range value
21 -> Maybe String -- ^ expected content-range value
26 -> Spec
22 -> Spec
27testRange range out crange = it title $ withApp defaultSettings app $ \port -> do
23testRange range out crange = it title $ withApp defaultSettings app $ \port -> do
28− handle <- connectTo "127.0.0.1" port
24+ handle <- connectTo port
29− S.hPutStr handle "GET / HTTP/1.0\r\n"
25+ msWrite handle "GET / HTTP/1.0\r\n"
30− S.hPutStr handle "Range: bytes="
26+ msWrite handle "Range: bytes="
31− S.hPutStr handle range
27+ msWrite handle range
32− S.hPutStr handle "\r\n\r\n"
28+ msWrite handle "\r\n\r\n"
33− hFlush handle
34 threadDelay 10000
29 threadDelay 10000
35− bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ S.hGetSome handle 1024
30+ bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ msRead handle 1024
36− hClose handle
31+ msClose handle
37 last bss `shouldBe` out
32 last bss `shouldBe` out
38 let hs = mapMaybe toHeader bss
33 let hs = mapMaybe toHeader bss
39 lookup "Content-Range" hs `shouldBe` fmap ("bytes " ++) crange
34 lookup "Content-Range" hs `shouldBe` fmap ("bytes " ++) crange
@@ -52,12 +47,11 @@ testPartial :: Integer -- ^ file size
52 -> String -- ^ expected output
47 -> String -- ^ expected output
53 -> Spec
48 -> Spec
54testPartial size offset count out = it title $ withApp defaultSettings app $ \port -> do
49testPartial size offset count out = it title $ withApp defaultSettings app $ \port -> do
55− handle <- connectTo "127.0.0.1" port
50+ handle <- connectTo port
56− S.hPutStr handle "GET / HTTP/1.0\r\n\r\n"
51+ msWrite handle "GET / HTTP/1.0\r\n\r\n"
57− hFlush handle
58 threadDelay 10000
52 threadDelay 10000
59− bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ S.hGetSome handle 1024
53+ bss <- fmap (lines . filter (/= '\r') . S8.unpack) $ msRead handle 1024
60− hClose handle
54+ msClose handle
61 out `shouldBe` last bss
55 out `shouldBe` last bss
62 let hs = mapMaybe toHeader bss
56 let hs = mapMaybe toHeader bss
63 lookup "Content-Length" hs `shouldBe` Just (show $ length $ last bss)
57 lookup "Content-Length" hs `shouldBe` Just (show $ length $ last bss)
warp/test/RunSpec.hs+98−55
@@ -2,7 +2,7 @@
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4
4
5−module RunSpec (main, spec, withApp, connectTo) where
5+module RunSpec (main, spec, withApp, connectTo, MySocket, msWrite, msRead, msClose) where
6
6
7import Control.Concurrent (forkIO, killThread, threadDelay)
7import Control.Concurrent (forkIO, killThread, threadDelay)
8import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
8import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
@@ -11,7 +11,7 @@ import qualified Control.Exception as E
11import Control.Exception.Lifted (bracket, try, IOException, onException)
11import Control.Exception.Lifted (bracket, try, IOException, onException)
12import Control.Monad (forM_, replicateM_, unless)
12import Control.Monad (forM_, replicateM_, unless)
13import Control.Monad.IO.Class (MonadIO, liftIO)
13import Control.Monad.IO.Class (MonadIO, liftIO)
14−import Data.ByteString (ByteString, hPutStr, hGetSome)
14+import Data.ByteString (ByteString)
15import qualified Data.ByteString as S
15import qualified Data.ByteString as S
16import Data.ByteString.Builder (byteString)
16import Data.ByteString.Builder (byteString)
17import qualified Data.ByteString.Char8 as S8
17import qualified Data.ByteString.Char8 as S8
@@ -23,7 +23,6 @@ import Network.Socket
23import Network.Socket.ByteString (sendAll)
23import Network.Socket.ByteString (sendAll)
24import Network.Wai hiding (responseHeaders)
24import Network.Wai hiding (responseHeaders)
25import Network.Wai.Handler.Warp
25import Network.Wai.Handler.Warp
26−import System.IO (hFlush, hClose, Handle, IOMode(..))
27import System.IO.Unsafe (unsafePerformIO)
26import System.IO.Unsafe (unsafePerformIO)
28import System.Timeout (timeout)
27import System.Timeout (timeout)
29import Test.Hspec
28import Test.Hspec
@@ -36,13 +35,44 @@ main = hspec spec
36type Counter = I.IORef (Either String Int)
35type Counter = I.IORef (Either String Int)
37type CounterApplication = Counter -> Application
36type CounterApplication = Counter -> Application
38
37
39−connectTo :: HostName -> Int -> IO Handle
38+data MySocket = MySocket
40−connectTo host port = do
39+ { msSocket :: !Socket
41− let hints = defaultHints { addrSocketType = Stream }
40+ , _msBuffer :: !(I.IORef ByteString)
42− addr:_ <- getAddrInfo (Just hints) (Just host) (Just $ show port)
41+ }
43− sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
42+
44− connect sock $ addrAddress addr
43+msWrite :: MySocket -> ByteString -> IO ()
45− socketToHandle sock ReadWriteMode
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
46
76
47incr :: MonadIO m => Counter -> m ()
77incr :: MonadIO m => Counter -> m ()
48incr icount = liftIO $ I.atomicModifyIORef icount $ \ecount ->
78incr icount = liftIO $ I.atomicModifyIORef icount $ \ecount ->
@@ -106,7 +136,13 @@ withApp settings app f = do
106 bracket
136 bracket
107 (forkIO $ runSettings settings' app `onException` putMVar baton ())
137 (forkIO $ runSettings settings' app `onException` putMVar baton ())
108 killThread
138 killThread
139+ (const $ do
109− (const $ takeMVar baton >> f port)
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)
110
146
111runTest :: Int -- ^ expected number of requests
147runTest :: Int -- ^ expected number of requests
112 -> CounterApplication
148 -> CounterApplication
@@ -115,9 +151,9 @@ runTest :: Int -- ^ expected number of requests
115runTest expected app chunks = do
151runTest expected app chunks = do
116 ref <- I.newIORef (Right 0)
152 ref <- I.newIORef (Right 0)
117 withApp defaultSettings (app ref) $ \port -> do
153 withApp defaultSettings (app ref) $ \port -> do
118− handle <- connectTo "127.0.0.1" port
154+ ms <- connectTo port
119− forM_ chunks $ \chunk -> hPutStr handle chunk >> hFlush handle
155+ forM_ chunks $ \chunk -> msWrite ms chunk
120− _ <- timeout 100000 $ replicateM_ expected $ hGetSome handle 4096
156+ _ <- timeout 100000 $ replicateM_ expected $ msRead ms 4096
121 res <- I.readIORef ref
157 res <- I.readIORef ref
122 case res of
158 case res of
123 Left s -> error s
159 Left s -> error s
@@ -133,10 +169,9 @@ runTerminateTest expected input = do
133 ref <- I.newIORef Nothing
169 ref <- I.newIORef Nothing
134 let onExc _ = I.writeIORef ref . Just
170 let onExc _ = I.writeIORef ref . Just
135 withApp (setOnException onExc defaultSettings) dummyApp $ \port -> do
171 withApp (setOnException onExc defaultSettings) dummyApp $ \port -> do
136− handle <- connectTo "127.0.0.1" port
172+ handle <- connectTo port
137− hPutStr handle input
173+ msWrite handle input
138− hFlush handle
139− hClose handle
174+ msClose handle
140 threadDelay 1000
175 threadDelay 1000
141 res <- I.readIORef ref
176 res <- I.readIORef ref
142 show res `shouldBe` show (Just expected)
177 show res `shouldBe` show (Just expected)
@@ -208,13 +243,12 @@ spec = do
208 liftIO $ I.writeIORef iheaders $ requestHeaders req
243 liftIO $ I.writeIORef iheaders $ requestHeaders req
209 f $ responseLBS status200 [] ""
244 f $ responseLBS status200 [] ""
210 withApp defaultSettings app $ \port -> do
245 withApp defaultSettings app $ \port -> do
211− handle <- connectTo "127.0.0.1" port
246+ handle <- connectTo port
212 let input = S.concat
247 let input = S.concat
213 [ "GET / HTTP/1.1\r\nfoo: bar\r\n baz\r\n\tbin\r\n\r\n"
248 [ "GET / HTTP/1.1\r\nfoo: bar\r\n baz\r\n\tbin\r\n\r\n"
214 ]
249 ]
215− hPutStr handle input
250+ msWrite handle input
216− hFlush handle
217− hClose handle
251+ msClose handle
218 threadDelay 1000
252 threadDelay 1000
219 headers <- I.readIORef iheaders
253 headers <- I.readIORef iheaders
220 headers `shouldBe`
254 headers `shouldBe`
@@ -226,13 +260,12 @@ spec = do
226 liftIO $ I.writeIORef iheaders $ requestHeaders req
260 liftIO $ I.writeIORef iheaders $ requestHeaders req
227 f $ responseLBS status200 [] ""
261 f $ responseLBS status200 [] ""
228 withApp defaultSettings app $ \port -> do
262 withApp defaultSettings app $ \port -> do
229− handle <- connectTo "127.0.0.1" port
263+ handle <- connectTo port
230 let input = S.concat
264 let input = S.concat
231 [ "GET / HTTP/1.1\r\nfoo:bar\r\n\r\n"
265 [ "GET / HTTP/1.1\r\nfoo:bar\r\n\r\n"
232 ]
266 ]
233− hPutStr handle input
267+ msWrite handle input
234− hFlush handle
235− hClose handle
268+ msClose handle
236 threadDelay 1000
269 threadDelay 1000
237 headers <- I.readIORef iheaders
270 headers <- I.readIORef iheaders
238 headers `shouldBe`
271 headers `shouldBe`
@@ -241,28 +274,33 @@ spec = do
241
274
242 describe "chunked bodies" $ do
275 describe "chunked bodies" $ do
243 it "works" $ do
276 it "works" $ do
277+ countVar <- newTVarIO (0 :: Int)
244 ifront <- I.newIORef id
278 ifront <- I.newIORef id
245 let app req f = do
279 let app req f = do
246 bss <- consumeBody $ requestBody req
280 bss <- consumeBody $ requestBody req
247 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
281 liftIO $ I.atomicModifyIORef ifront $ \front -> (front . (S.concat bss:), ())
282+ atomically $ modifyTVar countVar (+ 1)
248 f $ responseLBS status200 [] ""
283 f $ responseLBS status200 [] ""
249 withApp defaultSettings app $ \port -> do
284 withApp defaultSettings app $ \port -> do
250− handle <- connectTo "127.0.0.1" port
285+ handle <- connectTo port
251 let input = S.concat
286 let input = S.concat
252 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
287 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
253 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n\r\n"
288 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n\r\n"
254 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
289 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
255 , "b\r\nHello World\r\n0\r\n\r\n"
290 , "b\r\nHello World\r\n0\r\n\r\n"
256 ]
291 ]
257− hPutStr handle input
292+ msWrite handle input
258− hFlush handle
293+ msClose handle
259− hClose handle
294+ atomically $ do
260− threadDelay 1000
295+ count <- readTVar countVar
296+ check $ count == 2
261 front <- I.readIORef ifront
297 front <- I.readIORef ifront
262 front [] `shouldBe`
298 front [] `shouldBe`
263 [ "Hello World\nBye"
299 [ "Hello World\nBye"
264 , "Hello World"
300 , "Hello World"
265 ]
301 ]
302+#if !WINDOWS
303+-- Too slow on Windows
266 it "lots of chunks" $ do
304 it "lots of chunks" $ do
267 ifront <- I.newIORef id
305 ifront <- I.newIORef id
268 countVar <- newTVarIO (0 :: Int)
306 countVar <- newTVarIO (0 :: Int)
@@ -272,13 +310,13 @@ spec = do
272 atomically $ modifyTVar countVar (+ 1)
310 atomically $ modifyTVar countVar (+ 1)
273 f $ responseLBS status200 [] ""
311 f $ responseLBS status200 [] ""
274 withApp defaultSettings app $ \port -> do
312 withApp defaultSettings app $ \port -> do
275− handle <- connectTo "127.0.0.1" port
313+ handle <- connectTo port
276 let input = concat $ replicate 2 $
314 let input = concat $ replicate 2 $
277 ["POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"] ++
315 ["POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"] ++
278 (replicate 50 "5\r\n12345\r\n") ++
316 (replicate 50 "5\r\n12345\r\n") ++
279 ["0\r\n\r\n"]
317 ["0\r\n\r\n"]
280− mapM_ (\bs -> hPutStr handle bs >> hFlush handle) input
318+ mapM_ (msWrite handle) input
281− hClose handle
319+ msClose handle
282 atomically $ do
320 atomically $ do
283 count <- readTVar countVar
321 count <- readTVar countVar
284 check $ count == 2
322 check $ count == 2
@@ -286,7 +324,6 @@ spec = do
286 front [] `shouldBe` replicate 2 (S.concat $ replicate 50 "12345")
324 front [] `shouldBe` replicate 2 (S.concat $ replicate 50 "12345")
287-- For some reason, the following test on Windows causes the socket
325-- For some reason, the following test on Windows causes the socket
288-- to be killed prematurely. Worth investigating in the future if possible.
326-- to be killed prematurely. Worth investigating in the future if possible.
289−#if !WINDOWS
290 it "in chunks" $ do
327 it "in chunks" $ do
291 ifront <- I.newIORef id
328 ifront <- I.newIORef id
292 countVar <- newTVarIO (0 :: Int)
329 countVar <- newTVarIO (0 :: Int)
@@ -296,15 +333,15 @@ spec = do
296 atomically $ modifyTVar countVar (+ 1)
333 atomically $ modifyTVar countVar (+ 1)
297 f $ responseLBS status200 [] ""
334 f $ responseLBS status200 [] ""
298 withApp defaultSettings app $ \port -> do
335 withApp defaultSettings app $ \port -> do
299− handle <- connectTo "127.0.0.1" port
336+ handle <- connectTo port
300 let input = S.concat
337 let input = S.concat
301 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
338 [ "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
302 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n"
339 , "c\r\nHello World\n\r\n3\r\nBye\r\n0\r\n"
303 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
340 , "POST / HTTP/1.1\r\nTransfer-Encoding: Chunked\r\n\r\n"
304 , "b\r\nHello World\r\n0\r\n\r\n"
341 , "b\r\nHello World\r\n0\r\n\r\n"
305 ]
342 ]
306− mapM_ (\bs -> hPutStr handle bs >> hFlush handle) $ map S.singleton $ S.unpack input
343+ mapM_ (msWrite handle) $ map S.singleton $ S.unpack input
307− hClose handle
344+ msClose handle
308 atomically $ do
345 atomically $ do
309 count <- readTVar countVar
346 count <- readTVar countVar
310 check $ count == 2
347 check $ count == 2
@@ -330,16 +367,16 @@ spec = do
330 let bs1 = S.replicate 2048 88
367 let bs1 = S.replicate 2048 88
331 bs2 = "This is short"
368 bs2 = "This is short"
332 bs = S.append bs1 bs2
369 bs = S.append bs1 bs2
333− handle <- connectTo "127.0.0.1" port
370+ handle <- connectTo port
334− hPutStr handle "POST / HTTP/1.1\r\n"
371+ msWrite handle "POST / HTTP/1.1\r\n"
335− hPutStr handle "content-length: "
372+ msWrite handle "content-length: "
336− hPutStr handle $ S8.pack $ show $ S.length bs
373+ msWrite handle $ S8.pack $ show $ S.length bs
337− hPutStr handle "\r\n\r\n"
374+ msWrite handle "\r\n\r\n"
338 threadDelay 100000
375 threadDelay 100000
339− hPutStr handle bs1
376+ msWrite handle bs1
340 threadDelay 100000
377 threadDelay 100000
341− hPutStr handle bs2
378+ msWrite handle bs2
342− hClose handle
379+ msClose handle
343 threadDelay 5000000
380 threadDelay 5000000
344 front <- I.readIORef ifront
381 front <- I.readIORef ifront
345 S.concat (front []) `shouldBe` bs
382 S.concat (front []) `shouldBe` bs
@@ -356,30 +393,33 @@ spec = do
356 loop
393 loop
357 doubleBS = S.concatMap $ \w -> S.pack [w, w]
394 doubleBS = S.concatMap $ \w -> S.pack [w, w]
358 withApp defaultSettings app $ \port -> do
395 withApp defaultSettings app $ \port -> do
359− handle <- connectTo "127.0.0.1" port
396+ ms <- connectTo port
360− hPutStr handle "POST / HTTP/1.1\r\n\r\n12345"
397+ msWrite ms "POST / HTTP/1.1\r\n\r\n12345"
361− hFlush handle
362− timeout 100000 (S.hGet handle 10) >>= (`shouldBe` Just "1122334455")
398+ timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "1122334455")
363− hPutStr handle "67890"
399+ msWrite ms "67890"
364− hFlush handle
365− timeout 100000 (S.hGet handle 10) >>= (`shouldBe` Just "6677889900")
400+ timeout 100000 (msRead ms 10) >>= (`shouldBe` Just "6677889900")
366
401
367 it "only one date and server header" $ do
402 it "only one date and server header" $ do
368 let app _ f = f $ responseLBS status200
403 let app _ f = f $ responseLBS status200
369 [ ("server", "server")
404 [ ("server", "server")
370 , ("date", "date")
405 , ("date", "date")
371 ] ""
406 ] ""
407+ getValues key = map snd
408+ . filter (\(key', _) -> key == key')
409+ . responseHeaders
372 withApp defaultSettings app $ \port -> do
410 withApp defaultSettings app $ \port -> do
373 res <- sendGET $ "http://127.0.0.1:" ++ show port
411 res <- sendGET $ "http://127.0.0.1:" ++ show port
374− getHeaderValue hServer (responseHeaders res) `shouldBe` Just "server"
412+ getValues hServer res `shouldBe` ["server"]
375− getHeaderValue hDate (responseHeaders res) `shouldBe` Just "date"
413+ getValues hDate res `shouldBe` ["date"]
376
414
377 it "streaming echo #249" $ do
415 it "streaming echo #249" $ do
416+ countVar <- newTVarIO (0 :: Int)
378 let app req f = f $ responseStream status200 [] $ \write _ -> do
417 let app req f = f $ responseStream status200 [] $ \write _ -> do
379 let loop = do
418 let loop = do
380 bs <- requestBody req
419 bs <- requestBody req
381 unless (S.null bs) $ do
420 unless (S.null bs) $ do
382 write $ byteString bs
421 write $ byteString bs
422+ atomically $ modifyTVar countVar (+ 1)
383 loop
423 loop
384 loop
424 loop
385 withApp defaultSettings app $ \port -> do
425 withApp defaultSettings app $ \port -> do
@@ -387,6 +427,9 @@ spec = do
387 sendAll sock "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
427 sendAll sock "POST / HTTP/1.1\r\ntransfer-encoding: chunked\r\n\r\n"
388 threadDelay 10000
428 threadDelay 10000
389 sendAll sock "5\r\nhello\r\n0\r\n\r\n"
429 sendAll sock "5\r\nhello\r\n0\r\n\r\n"
430+ atomically $ do
431+ count <- readTVar countVar
432+ check $ count >= 1
390 bs <- safeRecv sock 4096
433 bs <- safeRecv sock 4096
391 S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"
434 S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"
392
435
warp/warp.cabal+6−2
@@ -120,6 +120,8 @@ Test-Suite doctest
120 Main-Is: doctests.hs
120 Main-Is: doctests.hs
121 Build-Depends: base >= 4.8 && < 5
121 Build-Depends: base >= 4.8 && < 5
122 , doctest >= 0.10.1
122 , doctest >= 0.10.1
123+ if os(windows)
124+ Buildable: False
123
125
124Test-Suite spec
126Test-Suite spec
125 Main-Is: Spec.hs
127 Main-Is: Spec.hs
@@ -219,7 +221,8 @@ Test-Suite spec
219 Cpp-Options: -DSENDFILEFD
221 Cpp-Options: -DSENDFILEFD
220 Build-Depends: unix
222 Build-Depends: unix
221 if os(windows)
223 if os(windows)
222− Cpp-Options: -DWINDOWS
224+ Cpp-Options: -DWINDOWS
225+ Build-Depends: time
223
226
224Benchmark parser
227Benchmark parser
225 Type: exitcode-stdio-1.0
228 Type: exitcode-stdio-1.0
@@ -251,7 +254,8 @@ Benchmark parser
251 Cpp-Options: -DSENDFILEFD
254 Cpp-Options: -DSENDFILEFD
252 Build-Depends: unix
255 Build-Depends: unix
253 if os(windows)
256 if os(windows)
254− Cpp-Options: -DWINDOWS
257+ Cpp-Options: -DWINDOWS
258+ Build-Depends: time
255
259
256Source-Repository head
260Source-Repository head
257 Type: git
261 Type: git