Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ before_install:
- travis_retry sudo add-apt-repository -y ppa:hvr/ghc
- travis_retry sudo apt-get update
- travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER # see note about happy/alex
- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
- export PATH=$HOME/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH

install:
- cabal --version
Expand All @@ -39,6 +39,12 @@ script:
- cabal check
- cabal sdist # tests that a source-distribution can be generated

- cabal copy
- cd test/integration
- stack setup
- stack test
- cd ../..

# Check that the resulting source distribution can be built & installed.
# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
# `cabal install --force-reinstalls dist/*-*.tar.gz`
Expand Down
42 changes: 0 additions & 42 deletions src/test/IntegrationTests.hs

This file was deleted.

20 changes: 0 additions & 20 deletions stack.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ homepage: https://github.com/commercialhaskell/stack
test/package-dump/ghc-7.8.txt
test/package-dump/ghc-7.10.txt

flag integration-tests
manual: True
default: False
description: Build the integration test executable

library
hs-source-dirs: src/
ghc-options: -Wall
Expand Down Expand Up @@ -177,21 +172,6 @@ executable stack
, http-client
default-language: Haskell2010

executable stack-integration-tests
hs-source-dirs: src/test
main-is: IntegrationTests.hs
ghc-options: -Wall
build-depends: base >= 4.7 && <5
, hspec
, process
, temporary
, directory
default-language: Haskell2010
if flag(integration-tests)
buildable: True
else
buildable: False

test-suite stack-test
type: exitcode-stdio-1.0
hs-source-dirs: src/test
Expand Down
2 changes: 2 additions & 0 deletions test/integration/Dummy.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
main :: IO ()
main = return ()
24 changes: 24 additions & 0 deletions test/integration/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Copyright (c) 2015, stack
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of stackage-common nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
128 changes: 128 additions & 0 deletions test/integration/Spec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}

import Control.Applicative
import Control.Arrow
import Control.Concurrent.Async
import Control.Exception
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Trans.Resource
import qualified Data.ByteString.Lazy as L
import Data.Char
import Data.Conduit
import Data.Conduit.Binary (sinkLbs)
import Data.Conduit.Filesystem (sourceDirectoryDeep)
import qualified Data.Conduit.List as CL
import Data.Conduit.Process
import Data.List (isSuffixOf, stripPrefix)
import qualified Data.Map as Map
import Data.Text.Encoding.Error (lenientDecode)
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import Data.Typeable
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import System.IO.Temp
import System.PosixCompat.Files
import Test.Hspec

main :: IO ()
main = do
currDir <- getCurrentDirectory

let findExe name = do
mexe <- findExecutable name
case mexe of
Nothing -> error $ name ++ " not found on PATH"
Just exe -> return exe
runghc <- findExe "runghc"
stack <- findExe "stack"

tests <- getDirectoryContents "tests" >>= filterM hasTest

envOrig <- getEnvironment

withSystemTempDirectory ("stack-integration-home") $ \newHome -> do
let env' = Map.toList
$ Map.insert "STACK_EXE" stack
$ Map.insert "HOME" newHome
$ Map.insert "APPDATA" newHome
$ Map.delete "GHC_PACKAGE_PATH"
$ Map.fromList
$ map (first (map toUpper)) envOrig

origStackRoot <- getAppUserDataDirectory "stack"

hspec $ mapM_ (test runghc env' currDir origStackRoot newHome) tests

hasTest :: FilePath -> IO Bool
hasTest dir = doesFileExist $ "tests" </> dir </> "Main.hs"

test :: FilePath -- ^ runghc
-> [(String, String)] -- ^ env
-> FilePath -- ^ currdir
-> FilePath -- ^ origStackRoot
-> FilePath -- ^ newHome
-> String
-> Spec
test runghc env' currDir origStackRoot newHome name = it name $ withDir $ \dir -> do
removeDirectoryRecursive newHome
copyStackRoot origStackRoot (newHome </> takeFileName origStackRoot)
let testDir = currDir </> "tests" </> name
mainFile = testDir </> "Main.hs"
libDir = currDir </> "lib"
cp = (proc runghc
[ "-clear-package-db"
, "-global-package-db"
, "-i" ++ libDir
, mainFile
])
{ cwd = Just dir
, env = Just env'
}
(ClosedStream, outSrc, errSrc, sph) <- streamingProcess cp
(out, err, ec) <- runConcurrently $ (,,)
<$> Concurrently (outSrc $$ sinkLbs)
<*> Concurrently (errSrc $$ sinkLbs)
<*> Concurrently (waitForStreamingProcess sph)
when (ec /= ExitSuccess) $ throwIO $ TestFailure out err ec
where
withDir = withSystemTempDirectory ("stack-integration-" ++ name)

data TestFailure = TestFailure L.ByteString L.ByteString ExitCode
deriving Typeable
instance Show TestFailure where
show (TestFailure out err ec) = concat
[ "Exited with " ++ show ec
, "\n\nstdout:\n"
, toStr out
, "\n\nstderr:\n"
, toStr err
]
where
toStr = TL.unpack . TL.decodeUtf8With lenientDecode
instance Exception TestFailure

copyStackRoot :: FilePath -> FilePath -> IO ()
copyStackRoot src dst =
runResourceT $ sourceDirectoryDeep False src $$ CL.mapM_ go
where
go srcfp = when toCopy $ liftIO $ do
Just suffix <- return $ stripPrefix src srcfp
let dstfp = dst ++ "/" ++ suffix
createDirectoryIfMissing True $ takeDirectory dstfp
createSymbolicLink srcfp dstfp `catch` \(_ :: IOException) ->
copyFile srcfp dstfp -- for Windows
where
toCopy = any (`isSuffixOf` srcfp)
-- FIXME command line parameters to control how many of these get
-- copied, trade-off of runtime/bandwidth vs isolation of tests
[ ".tar"
, ".xz"
-- , ".gz"
, ".7z.exe"
, "00-index.cache"
]
43 changes: 43 additions & 0 deletions test/integration/lib/StackTest.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module StackTest where

import Control.Exception
import System.Environment
import System.FilePath
import System.Directory
import System.IO
import System.Process
import System.Exit
import System.Environment

stack' :: [String] -> IO ExitCode
stack' args = do
stack <- getEnv "STACK_EXE"
putStrLn $ "Running stack with args " ++ show args
(Nothing, Nothing, Nothing, ph) <- createProcess (proc stack args)
waitForProcess ph

stack :: [String] -> IO ()
stack args = do
ec <- stack' args
if ec == ExitSuccess
then return ()
else error $ "Exited with exit code: " ++ show ec

stackErr :: [String] -> IO ()
stackErr args = do
ec <- stack' args
if ec == ExitSuccess
then error "stack was supposed to fail, but didn't"
else return ()

doesNotExist :: FilePath -> IO ()
doesNotExist fp = do
putStrLn $ "doesNotExist " ++ fp
isFile <- doesFileExist fp
if isFile
then error $ "File exists: " ++ fp
else do
isDir <- doesDirectoryExist fp
if isDir
then error $ "Directory exists: " ++ fp
else return ()
45 changes: 45 additions & 0 deletions test/integration/stack-integration-tests.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: stack-integration-tests
version: 0.0.0
synopsis: Integration tests
description: Integration tests
license: BSD3
license-file: LICENSE
author: Chris Done
maintainer: chrisdone@fpcomplete.com
category: Development
build-type: Simple
cabal-version: >=1.10
homepage: https://github.com/commercialhaskell/stack

-- This is only present because cabal won't allow a test suite without a
-- library or executable
executable stack-integration-dummy
main-is: Dummy.hs
build-depends: base
default-language: Haskell2010

test-suite stack-integration-tests
type: exitcode-stdio-1.0
main-is: Spec.hs
ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N

build-depends: base >= 4.7 && < 10
, temporary
, hspec
, process
, filepath
, directory
, text
, unix-compat
, containers
, conduit
, conduit-extra
, resourcet
, async
, transformers
, bytestring
default-language: Haskell2010

source-repository head
type: git
location: https://github.com/commercialhaskell/stack
3 changes: 3 additions & 0 deletions test/integration/stack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
packages:
- '.'
resolver: lts-2.9
6 changes: 6 additions & 0 deletions test/integration/tests/basic-install/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import StackTest

main :: IO ()
main = do
stack ["install", "acme-missiles-0.3"]
doesNotExist "stack.yaml"
7 changes: 7 additions & 0 deletions test/integration/tests/cyclic-test-deps/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import StackTest

main :: IO ()
main = do
stack ["unpack", "text-1.2.1.1"]
stack ["init", "--resolver", "lts-2.9"]
stack ["test", "--dry-run"]
12 changes: 12 additions & 0 deletions test/integration/tests/sanity/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import StackTest

main :: IO ()
main = do
stack ["--version"]
stack ["--help"]
stack ["unpack", "acme-missiles-0.2"]
stack ["unpack", "acme-missiles"]
stackErr ["command-does-not-exist"]
stackErr ["unpack", "invalid-package-name-"]
stackErr ["build"]
doesNotExist "stack.yaml"