{-# LANGUAGE OverloadedStrings #-}
module Samples where
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.Golden (goldenVsFile)
import System.FilePath ((</>))
import Data.Maybe (mapMaybe)
import qualified Data.List
import qualified Data.Text
import qualified Data.Text.IO
import qualified System.Environment
import qualified System.FilePath
import qualified System.Directory
import qualified System.IO
import qualified System.IO.Temp
import qualified System.Process
import Data.Text.IO ( hPutStrLn )
import qualified Update.Nix.FetchGit
import Update.Nix.FetchGit.Types ( Dryness(..)
, Env(Env)
)
-- | Provided output file @f@ pointing to e.g. @tests/test_rec_sets.out.nix@
-- * turn this into @tests/test_rec_sets.in.nix@
-- * copy to temporary directory
-- * create fake git repositories using @tests/fakeRepo.sh@
-- * adjust @url@ to point to the faked git repositories in the temporary directory
-- * perform update
-- * adjust @url@ to point to the expected one
-- * copy file back to @tests/test_rec_sets.out.nix@ so it be compared to @expected.nix@
runTest :: String -> IO ()
runTest f =
System.IO.Temp.withSystemTempDirectory "test-update-nix-fetchgit" $ \dir ->
System.IO.Temp.withSystemTempDirectory "test-update-nix-fetchgit-store" $ \storeDir -> do
let
inFile = Data.Text.unpack
$ Data.Text.replace ".out.nix" ".in.nix"
$ Data.Text.pack f
inBase = System.FilePath.takeBaseName inFile
System.Directory.copyFile inFile (dir </> inBase)
testScript <- System.Directory.makeAbsolute "tests/fakeRepo.sh"
_ <- System.Process.waitForProcess =<< System.Process.runProcess
"bash"
[testScript] (Just dir)
Nothing
Nothing Nothing Nothing
replaceFile (dir </> inBase) "/tmp/nix-update-fetchgit-test" (Data.Text.pack dir)
System.Environment.setEnv "NIX_STATE_DIR" $ storeDir </> "state"
System.Environment.setEnv "NIX_STORE_DIR" storeDir
-- work around race condition https://github.com/NixOS/nix/issues/2706
System.Directory.createDirectoryIfMissing True $ storeDir </> "state/gcroots"
-- and another - error: SQLite database storeDir </> 'state/db/db.sqlite' is busy
_ <- System.Process.readCreateProcess
(System.Process.shell "nix-store --init")
mempty
let env = Env (const (Data.Text.IO.hPutStrLn System.IO.stderr)) [] [] Wet False
Update.Nix.FetchGit.processFile env (dir </> inBase)
replaceFile (dir </> inBase) (Data.Text.pack dir) "/tmp/nix-update-fetchgit-test"
System.Directory.copyFile (dir </> inBase) f
where
replaceFile f' what with =
Data.Text.IO.readFile f' >>= Data.Text.IO.writeFile f' . Data.Text.replace what with
test_derivation :: IO TestTree
test_derivation = do
localSamples <- findSamples "tests"
networkedSamples <- findSamples "tests/networked"
samples <- inNixBuild >>= \case
False -> pure $ localSamples <> networkedSamples
True -> do
hPutStrLn System.IO.stderr "Skipping networked tests inside Nix build"
pure localSamples
pure $ testGroup "golden" $ map mk samples
where
mk n =
let tEx = (n ++ ".expected.nix")
tOut = (n ++ ".out.nix")
in goldenVsFile ("update of " ++ tOut) tEx tOut (runTest tOut)
findSamples :: FilePath -> IO [String]
findSamples dir =
fmap (dir </>)
. mapMaybe (dropSuffix ".in.nix")
<$> System.Directory.listDirectory dir
dropSuffix :: String -> String -> Maybe String
dropSuffix s t = if s `Data.List.isSuffixOf` t
then Just $ take (length t - length s) t
else Nothing
-- From https://github.com/input-output-hk/ouroboros-network
-- | Infer from environment variables whether we are running within a Nix build
-- (and not just a nix-shell).
inNixBuild :: IO Bool
inNixBuild = do
let testEnv = fmap (maybe False (not . null)) . System.Environment.lookupEnv
haveNixBuildDir <- testEnv "NIX_BUILD_TOP"
inNixShell <- testEnv "IN_NIX_SHELL"
pure (haveNixBuildDir && not inNixShell)