packages feed

glob-posix-0.2.0.0: test/Spec.hs

import Control.Exception (bracket_)
import System.Directory
import System.FilePath ((</>))
import System.Info (os)
import System.IO (IOMode(..), withFile)
import System.Posix.User
import Test.Tasty
import Test.Tasty.ExpectedFailure
import Test.Tasty.HUnit

import System.Directory.Glob
import System.Directory.Glob.GNU


main :: IO ()
main = do
    putStrLn $ "\nRunning on " ++ os
    tmp <- getTemporaryDirectory

    -- We only expect Linux to have GNU extensions
    let gnuHandling = if os == "linux"
                         then id
                         else ignoreTest

    defaultMain $ testGroup "Tests" [
        testGroup "POSIX Functionality" (posixTests tmp),
        gnuHandling $ testGroup "GNU Extensions" (gnuTests tmp)
        ]

posixTests :: FilePath -> [TestTree]
posixTests tmp = [
    testCase "Basic case" $
        glob globDefaults "/usr/bin" !@?= ["/usr/bin"],

    testCase "Non-existant path" $
        glob globDefaults "/foo" !@?= [],

    testCase "globMany" . withTempFile "foo" $ \f1 ->
        withTempFile "bar" $ \f2 ->
            globMany globDefaults [tmp </> "foo", tmp </> "bar"] !@?= [f1, f2],

    testCase "GLOB_MARK" $
        glob globMark "/usr/bin" !@?= ["/usr/bin/"],

    testCase "GLOB_NOCHECK" $
        glob globNoCheck "/foo" !@?= ["/foo"],

    testCase "GLOB_ESCAPE" . withTempFile "a?b" $ \f ->
        glob globDefaults (tmp </> "a\\?b") !@?= [f],

    testCase "GLOB_NOESCAPE" . withTempFile "a\\?b" $ \f ->
        glob globNoEscape (tmp </> "a\\?b") !@?= [f]

    ]

gnuTests :: FilePath -> [TestTree]
gnuTests tmp = [
    testCase "GLOB_NOMAGIC" $
        glob globNoMagic "/foo" !@?= ["/foo"],


    testCase "GLOB_PERIOD" . withTempFile ".ab" $ \f -> do
        glob globDefaults           (tmp </> "?ab") !@?= []
        glob globPeriod (tmp </> "?ab") !@?= [f],

    testCase "GLOB_BRACE" . withTempFile "foo" $ \f1 ->
        withTempFile "far" $ \f2 -> do
            glob globDefaults          (tmp </> "f{oo,ar}") !@?= []
            glob globBrace (tmp </> "f{oo,ar}") !@?= [f1, f2],

    testCase "GLOB_TILDE" $ do
        h <- getHomeDirectory
        user <- getUserName
        glob globDefaults          ('~':user) !@?= []
        glob globTilde ('~':user) !@?= [h]

    ]


-- Convenience operator that eliminates the need to bind the actual result before asserting it is equal to the expected result
(!@?=) :: (Eq a, Show a) => IO a -> a -> Assertion
(!@?=) x y = do
    x' <- x
    x' @?= y

-- Deterministic temp file creation & deletion
withTempFile :: FilePath -> (FilePath -> IO a) -> IO a
withTempFile f cb = do
    d <- getTemporaryDirectory
    let f' = d </> f
    let createFile fp = withFile fp WriteMode (\_ -> return ())

    bracket_
        (createFile f')
        (removeFile f')
        (cb f')

-- Gets the username of the current user
-- We can't use getLoginName here because it requires a controlling tty
getUserName :: IO String
getUserName = userName <$> (getUserEntryForID =<< getEffectiveUserID)