{-# LANGUAGE ScopedTypeVariables #-} module TestUtils where import Prelude () import Prelude.Compat import Control.Monad import Control.Monad.Trans.Maybe import Control.Exception import System.Process import System.Directory import System.Info import System.Exit (exitFailure) import System.IO (stderr, hPutStrLn) findNodeProcess :: IO (Maybe String) findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names where names = ["nodejs", "node"] -- | -- Fetches code necessary to run the tests with. The resulting support code -- should then be checked in, so that npm/bower etc is not required to run the -- tests. -- -- Simply rerun this (via ghci is probably easiest) when the support code needs -- updating. -- updateSupportCode :: IO () updateSupportCode = do setCurrentDirectory "tests/support" if System.Info.os == "mingw32" then callProcess "setup-win.cmd" [] else do callProcess "npm" ["install"] -- bower uses shebang "/usr/bin/env node", but we might have nodejs node <- maybe cannotFindNode pure =<< findNodeProcess -- Sometimes we run as a root (e.g. in simple docker containers) -- And we are non-interactive: https://github.com/bower/bower/issues/1162 callProcess node ["node_modules/.bin/bower", "--allow-root", "install", "--config.interactive=false"] setCurrentDirectory "../.." where cannotFindNode :: IO a cannotFindNode = do hPutStrLn stderr "Cannot find node (or nodejs) executable" exitFailure -- | -- The support modules that should be cached between test cases, to avoid -- excessive rebuilding. -- supportModules :: [String] supportModules = [ "Control.Alt" , "Control.Alternative" , "Control.Applicative" , "Control.Apply" , "Control.Biapplicative" , "Control.Biapply" , "Control.Bind" , "Control.Category" , "Control.Comonad" , "Control.Extend" , "Control.Lazy" , "Control.Monad" , "Control.Monad.Eff" , "Control.Monad.Eff.Class" , "Control.Monad.Eff.Console" , "Control.Monad.Eff.Unsafe" , "Control.Monad.Rec.Class" , "Control.Monad.ST" , "Control.MonadPlus" , "Control.MonadZero" , "Control.Plus" , "Control.Semigroupoid" , "Data.Array" , "Data.Array.Partial" , "Data.Array.ST" , "Data.Array.ST.Iterator" , "Data.Bifoldable" , "Data.Bifunctor" , "Data.Bifunctor.Clown" , "Data.Bifunctor.Flip" , "Data.Bifunctor.Join" , "Data.Bifunctor.Joker" , "Data.Bifunctor.Product" , "Data.Bifunctor.Wrap" , "Data.Bitraversable" , "Data.Boolean" , "Data.BooleanAlgebra" , "Data.Bounded" , "Data.Char" , "Data.CommutativeRing" , "Data.Either" , "Data.Either.Nested" , "Data.Eq" , "Data.EuclideanRing" , "Data.Field" , "Data.Foldable" , "Data.Function" , "Data.Function.Uncurried" , "Data.Functor" , "Data.Functor.Invariant" , "Data.Generic" , "Data.Generic.Rep" , "Data.Generic.Rep.Bounded" , "Data.Generic.Rep.Eq" , "Data.Generic.Rep.Monoid" , "Data.Generic.Rep.Ord" , "Data.Generic.Rep.Semigroup" , "Data.Generic.Rep.Show" , "Data.HeytingAlgebra" , "Data.Identity" , "Data.Lazy" , "Data.List" , "Data.List.Lazy" , "Data.List.Lazy.NonEmpty" , "Data.List.Lazy.Types" , "Data.List.NonEmpty" , "Data.List.Partial" , "Data.List.Types" , "Data.List.ZipList" , "Data.Maybe" , "Data.Maybe.First" , "Data.Maybe.Last" , "Data.Monoid" , "Data.Monoid.Additive" , "Data.Monoid.Alternate" , "Data.Monoid.Conj" , "Data.Monoid.Disj" , "Data.Monoid.Dual" , "Data.Monoid.Endo" , "Data.Monoid.Multiplicative" , "Data.NaturalTransformation" , "Data.Newtype" , "Data.NonEmpty" , "Data.Ord" , "Data.Ord.Unsafe" , "Data.Ordering" , "Data.Ring" , "Data.Semigroup" , "Data.Semiring" , "Data.Show" , "Data.String" , "Data.String.CaseInsensitive" , "Data.String.Regex" , "Data.String.Regex.Flags" , "Data.String.Regex.Unsafe" , "Data.String.Unsafe" , "Data.Symbol" , "Data.Traversable" , "Data.Tuple" , "Data.Tuple.Nested" , "Data.Unfoldable" , "Data.Unit" , "Data.Void" , "PSCI.Support" , "Partial" , "Partial.Unsafe" , "Prelude" , "Test.Assert" , "Type.Data.Ordering" , "Type.Data.Symbol" , "Type.Equality" , "Type.Prelude" , "Type.Proxy" , "Unsafe.Coerce" ] pushd :: forall a. FilePath -> IO a -> IO a pushd dir act = do original <- getCurrentDirectory setCurrentDirectory dir result <- try act :: IO (Either IOException a) setCurrentDirectory original either throwIO return result