{-# LANGUAGE CPP, MultiParamTypeClasses, DeriveDataTypeable #-} module Main ( main ) where import qualified Darcs.Test.Misc import qualified Darcs.Test.Patch import qualified Darcs.Test.Email import Control.Monad (when) import Data.List ( isPrefixOf, isSuffixOf, sort ) import qualified Data.ByteString.Char8 as B import System.Console.CmdLib import System.FilePath( takeDirectory, takeBaseName, isAbsolute ) import System.IO( hSetBinaryMode, hSetBuffering, BufferMode( NoBuffering ), stdin, stdout, stderr ) import Test.Framework.Providers.API import Test.Framework import Shellish hiding ( liftIO, run ) import qualified Shellish doUnit :: IO [Test] doUnit = return unitTests -- | This is the big list of tests that will be run using testrunner. unitTests :: [Test] unitTests = [ Darcs.Test.Email.testSuite , Darcs.Test.Misc.testSuite ] ++ Darcs.Test.Patch.testSuite -- ---------------------------------------------------------------------- -- shell tests -- ---------------------------------------------------------------------- data Format = Hashed | Darcs2 deriving Show data Running = Running deriving Show data Result = Success | Skipped | Failed String instance Show Result where show Success = "Success" show Skipped = "Skipped" show (Failed f) = unlines (map ("| " ++) $ lines f) instance TestResultlike Running Result where testSucceeded Success = True testSucceeded Skipped = True testSucceeded _ = False data ShellTest = ShellTest { format :: Format , testfile :: FilePath , testdir :: Maybe FilePath -- ^ only if you want to set it explicitly , _darcspath :: FilePath } runtest' :: ShellTest -> FilePath -> ShIO Result runtest' (ShellTest fmt _ _ dp) srcdir = do wd <- pwd setenv "HOME" wd setenv "TESTDATA" (srcdir "tests" "data") setenv "TESTBIN" (srcdir "tests" "bin") setenv "DARCS_TESTING_PREFS_DIR" $ wd ".darcs" setenv "EMAIL" "tester" setenv "DARCS_DONT_COLOR" "1" setenv "DARCS_DONT_ESCAPE_ANYTHING" "1" getenv "PATH" >>= setenv "PATH" . ((takeDirectory dp ++ ":") ++) setenv "DARCS" dp mkdir ".darcs" writefile ".darcs/defaults" defaults -- Warning: A do-notation statement discarded a result of type String. _ <- Shellish.run "bash" [ "test" ] return Success `catch_sh` \e -> case e of RunFailed _ 200 _ -> return Skipped RunFailed _ _ _ -> Failed <$> B.unpack <$> lastOutput where defaults = unlines ["ALL " ++ fmtstr, "send no-edit-description", "ALL ignore-times"] fmtstr = case fmt of Darcs2 -> "darcs-2" Hashed -> "hashed" runtest :: ShellTest -> ShIO Result runtest t = withTmp $ \dir -> do cp "tests/lib" dir cp ("tests" testfile t) (dir "test") srcdir <- pwd silently $ sub $ cd dir >> runtest' t srcdir where withTmp = case testdir t of Just dir -> \job -> do let d = (dir show (format t) takeBaseName (testfile t)) mkdir_p d job d Nothing -> withTmpDir instance Testlike Running Result ShellTest where testTypeName _ = "Shell" runTest _ test = runImprovingIO $ do yieldImprovement Running liftIO (shellish $ runtest test) shellTest :: FilePath -> Format -> Maybe FilePath -> String -> Test shellTest dp fmt tdir file = Test (file ++ " (" ++ show fmt ++ ")") $ ShellTest fmt file tdir dp findShell :: FilePath -> Maybe FilePath -> Bool -> ShIO [Test] findShell dp tdir isFailing = do files <- sort <$> grep relevant <$> grep (".sh" `isSuffixOf`) <$> ls "tests" return [ shellTest dp fmt tdir file | fmt <- [ Darcs2, Hashed ] , file <- files ] where relevant = (if isFailing then id else not) . ("failing-" `isPrefixOf`) findNetwork :: FilePath -> Maybe FilePath -> ShIO [Test] findNetwork dp tdir = do files <- sort <$> grep (".sh" `isSuffixOf`) <$> ls "tests/network" return [ shellTest dp Darcs2 tdir ("network" file) | file <- files ] -- ---------------------------------------------------------------------- -- harness -- ---------------------------------------------------------------------- data Config = Config { failing :: Bool , shell :: Bool , network :: Bool , unit :: Bool , darcs :: String , tests :: [String] , testDir :: Maybe FilePath , plain :: Bool , hideSuccesses :: Bool , threads :: Int } deriving (Data, Typeable, Eq) instance Attributes Config where attributes _ = group "Options" [ failing %> Help "Run the failing (shell) tests." , shell %> Help "Run the passing, non-network shell tests." %+ Default True , network %> Help "Run the network shell tests." , unit %> Help "Run the unit tests." %+ Default True , tests %> Help "Pattern to limit the tests to run." %+ short 't' , testDir %> Help "Directory to run tests in" %+ Default (Nothing :: Maybe FilePath) , plain %> Help "Use plain-text output." , hideSuccesses %> Help "Hide successes." , threads %> Default (1 :: Int) %+ short 'j' ] data DarcsTest = DarcsTest deriving Typeable instance Command DarcsTest (Record Config) where run _ conf _ = do let args = [ "-j", show $ threads conf ] ++ concat [ ["-t", x ] | x <- tests conf ] ++ [ "--plain" | True <- [plain conf] ] ++ [ "--hide-successes" | True <- [hideSuccesses conf] ] ++ [ "--maximum-unsuitable-generated-tests", "700" ] case testDir conf of Nothing -> return () Just d -> do e <- shellish (test_e d) when e $ fail ("Directory " ++ d ++ " already exists. Cowardly exiting") when (shell conf || network conf || failing conf) $ do when (null $ darcs conf) $ fail ("No darcs specified. Perhaps --darcs `pwd`/dist/build/darcs/darcs" ++ exeSuffix ++ "?") when (not (isAbsolute (darcs conf))) $ fail ("Argument to --darcs should be an absolute path") when (not (exeSuffix `isSuffixOf` darcs conf)) $ putStrLn $ "Warning: --darcs flag does not end with " ++ exeSuffix ++ " - some tests may fail (case does matter)" ftests <- shellish $ if failing conf then findShell (darcs conf) (testDir conf) True else return [] stests <- shellish $ if shell conf then findShell (darcs conf) (testDir conf) False else return [] utests <- if unit conf then doUnit else return [] ntests <- shellish $ if network conf then findNetwork (darcs conf) (testDir conf) else return [] defaultMainWithArgs (ftests ++ stests ++ utests ++ ntests) args where exeSuffix :: String #ifdef WIN32 exeSuffix = ".exe" #else exeSuffix = "" #endif main :: IO () main = do hSetBinaryMode stdout True hSetBuffering stdout NoBuffering hSetBinaryMode stderr True hSetBinaryMode stdin True getArgs >>= execute DarcsTest