content: 
  module Test(main) where
  
  import Control.Exception.Extra
  import Control.Monad.Extra
  import Data.Maybe
  import Data.List.Extra
  import System.Directory
  import System.Environment
  import General.Timing
  import Development.Shake.Internal.FileInfo
  import Development.Shake.Internal.FileName
  import qualified Data.ByteString.Char8 as BS
  import Test.Type(sleepFileTimeCalibrate)
  import Control.Concurrent.Extra
  
  import qualified Test.Basic
  import qualified Test.Batch
  import qualified Test.Benchmark
  import qualified Test.Builtin
  import qualified Test.BuiltinOverride
  import qualified Test.C
  import qualified Test.Cache
  import qualified Test.Cleanup
  import qualified Test.CloseFileHandles
  import qualified Test.Command
  import qualified Test.Config
  import qualified Test.Database
  import qualified Test.Digest
  import qualified Test.Directory
  import qualified Test.Docs
  import qualified Test.Errors
  import qualified Test.Existence
  import qualified Test.FileLock
  import qualified Test.FilePath
  import qualified Test.FilePattern
  import qualified Test.Files
  import qualified Test.Forward
  import qualified Test.History
  import qualified Test.Journal
  import qualified Test.Lint
  import qualified Test.Live
  import qualified Test.Manual
  import qualified Test.Match
  import qualified Test.Monad
  import qualified Test.Ninja
  import qualified Test.Oracle
  import qualified Test.OrderOnly
  import qualified Test.Parallel
  import qualified Test.Pool
  import qualified Test.Progress
  import qualified Test.Random
  import qualified Test.Rebuild
  import qualified Test.Reschedule
  import qualified Test.Resources
  import qualified Test.Self
  import qualified Test.SelfMake
  import qualified Test.Tar
  import qualified Test.Targets
  import qualified Test.Thread
  import qualified Test.Tup
  import qualified Test.Unicode
  import qualified Test.Util
  import qualified Test.Verbosity
  import qualified Test.Version
  
  import qualified Run
  
  
  fakes = ["clean" * clean, "test" * test, "make" * makefile, "filetime" * filetime]
      where (*) = (,)
  
  mains =
      ["basic" * Test.Basic.main
      ,"batch" * Test.Batch.main
      ,"benchmark" * Test.Benchmark.main
      ,"builtin" * Test.Builtin.main
      ,"builtinOverride" * Test.BuiltinOverride.main
      ,"c" * Test.C.main
      ,"cache" * Test.Cache.main
      ,"cleanup" * Test.Cleanup.main
      ,"closefilehandles" * Test.CloseFileHandles.main
      ,"command" * Test.Command.main
      ,"config" * Test.Config.main
      ,"database" * Test.Database.main
      ,"digest" * Test.Digest.main
      ,"directory" * Test.Directory.main
      ,"docs" * Test.Docs.main
      ,"errors" * Test.Errors.main
      ,"existence" * Test.Existence.main
      ,"filelock" * Test.FileLock.main
      ,"filepath" * Test.FilePath.main
      ,"filepattern" * Test.FilePattern.main
      ,"files" * Test.Files.main
      ,"forward" * Test.Forward.main
      ,"history" * Test.History.main
      ,"journal" * Test.Journal.main
      ,"lint" * Test.Lint.main
      ,"live" * Test.Live.main
      ,"manual" * Test.Manual.main
      ,"match" * Test.Match.main
      ,"monad" * Test.Monad.main
      ,"ninja" * Test.Ninja.main
      ,"oracle" * Test.Oracle.main
      ,"orderonly" * Test.OrderOnly.main
      ,"parallel" * Test.Parallel.main
      ,"pool" * Test.Pool.main
      ,"progress" * Test.Progress.main
      ,"random" * Test.Random.main
      ,"rebuild" * Test.Rebuild.main
      ,"reschedule" * Test.Reschedule.main
      ,"resources" * Test.Resources.main
      ,"self" * Test.Self.main
      ,"selfmake" * Test.SelfMake.main
      ,"tar" * Test.Tar.main
      ,"targets" * Test.Targets.main
      ,"thread" * Test.Thread.main
      ,"tup" * Test.Tup.main
      ,"unicode" * Test.Unicode.main
      ,"util" * Test.Util.main
      ,"verbosity" * Test.Verbosity.main
      ,"version" * Test.Version.main]
      where (*) = (,)
  
  
  main :: IO ()
  main = do
      resetTimings
      xs <- getArgs
      case flip lookup (fakes ++ mains) =<< listToMaybe xs of
          _ | null xs -> do
              putStrLn "******************************************************************"
              putStrLn "** Running shake test suite, run with '--help' to see arguments **"
              putStrLn "******************************************************************"
              unlessM (doesFileExist "shake.cabal") $ do
                  putStrLn ""
                  errorIO "\nERROR: Must run the test suite from a directory containing the Shake repo."
              withArgs ["test"] main
              withArgs ["random","test","3m"] main
          Nothing -> putStrLn $ unlines
              ["Welcome to the Shake demo"
              ,""
              ,unwords $ "Modes:" : map fst fakes
              ,unwords $ "Demos:" : map fst mains
              ,""
              ,"As an example, try:"
              ,""
              ,"  shake-test self --jobs=2 --trace"
              ,""
              ,"Which will build Shake, using Shake, on 2 threads."
              ,"You must run the test suite from a directory containing the Shake repo."
              ]
          Just main -> main =<< sleepFileTimeCalibrate "output/calibrate"
  
  
  makefile :: IO () -> IO ()
  makefile _ = do
      args <- getArgs
      withArgs (drop1 args) Run.main
  
  
  filetime :: IO () -> IO ()
  filetime _ = do
      args <- getArgs
      addTiming "Reading files"
      files <- concatForM (drop1 args) $ \file ->
          BS.lines . BS.filter (/= '\r') <$> BS.readFile file
      let n = length files
      evaluate n
      addTiming "Modtime"
      let (a,bcd) = splitAt (n `div` 4) files
      let (b,cd) = splitAt (n `div` 4) bcd
      let (c,d) = splitAt (n `div` 4) cd
      vars <- forM [a,b,c,d] $ \xs ->
          onceFork $ mapM_ (getFileInfo False . fileNameFromByteString) xs
      sequence_ vars
  
  
  clean :: IO () -> IO ()
  clean extra = sequence_ [withArgs [name,"clean"] $ main extra | (name,main) <- mains]
  
  
  test :: IO () -> IO ()
  test yield = do
      args <- getArgs
      flip onException (putStrLn "TESTS FAILED") $
          sequence_ [withArgs (name:"test":drop1 args) $ test yield | (name,test) <- mains, name /= "random"]
  