-- |
-- Copyright: © 2018-2020 IOHK
-- License: Apache-2.0
--
-- Utility function for finding the package test data directory.

module Test.Utils.Paths
    ( getTestData
    , getTestDataPath
    , inNixBuild
    ) where

import Prelude

import Control.Monad.IO.Class
    ( liftIO )
import Data.FileEmbed
    ( makeRelativeToProject )
import Language.Haskell.TH.Syntax
    ( Exp, Q, liftData )
import System.Environment
    ( lookupEnv )
import System.FilePath
    ( (</>) )

-- | A TH function to get the test data directory.
--
-- It combines the current source file location and cabal file to locate the
-- package directory in such a way that works in both the stack/cabal package
-- build and ghci.
--
-- For the Nix build, rather than baking in a path that starts with @/build@, it
-- makes the test data path relative to the current directory.
getTestData :: Q Exp
getTestData :: Q Exp
getTestData = FilePath -> Q Exp
getTestDataPath (FilePath
"test" FilePath -> FilePath -> FilePath
</> FilePath
"data")

-- | A variant of 'getTestData' which lets you specify the test data 'FilePath'
-- relative to the package root directory.
getTestDataPath :: FilePath -> Q Exp
getTestDataPath :: FilePath -> Q Exp
getTestDataPath FilePath
relPath = do
    FilePath
absPath <- FilePath -> Q FilePath
makeRelativeToProject FilePath
relPath
    Bool
useRel <- IO Bool -> Q Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO Bool
inNixBuild
    FilePath -> Q Exp
forall a. Data a => a -> Q Exp
liftData (if Bool
useRel then FilePath
relPath else FilePath
absPath)

-- | Infer from environment variables whether we are running within a Nix build
-- (and not just a nix-shell).
inNixBuild :: IO Bool
inNixBuild :: IO Bool
inNixBuild = do
    let testEnv :: FilePath -> IO Bool
testEnv = (Maybe FilePath -> Bool) -> IO (Maybe FilePath) -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Bool -> (FilePath -> Bool) -> Maybe FilePath -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Bool -> Bool
not (Bool -> Bool) -> (FilePath -> Bool) -> FilePath -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null)) (IO (Maybe FilePath) -> IO Bool)
-> (FilePath -> IO (Maybe FilePath)) -> FilePath -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO (Maybe FilePath)
lookupEnv
    Bool
haveNixBuildDir <- FilePath -> IO Bool
testEnv FilePath
"NIX_BUILD_TOP"
    Bool
inNixShell <- FilePath -> IO Bool
testEnv FilePath
"IN_NIX_SHELL"
    Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool
haveNixBuildDir Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
inNixShell)