unix-recursive-0.1.0.0: test/Spec/Listing.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Spec.Listing (spec, DirectoryListing (..)) where
import Data.List (sort)
import Data.String
import System.Posix.Files (FileStatus)
import qualified System.Posix.Files as Posix
import Test.Hspec
class (Show a, Ord a, IsString a) => DirectoryListing a where
list :: a -> IO [a]
followList :: a -> IO [a]
listMatching :: (a -> Bool) -> a -> IO [a]
followListMatching :: (a -> Bool) -> a -> IO [a]
listAccessible :: a -> IO [a]
listDirectories :: a -> IO [a]
listRegularFiles :: a -> IO [a]
listSymbolicLinks :: a -> IO [a]
listCustom :: (a -> Bool) -> (FileStatus -> a -> IO Bool) -> a -> IO [a]
spec :: forall a. DirectoryListing a => (a -> a -> Bool) -> Spec
spec filter = do
context "Not following symlinks" $ do
describe "listEverything" $ do
it "returns expected list of everything in workdir" $ do
res :: [a] <- list "test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir1"
, "test/workdir/dir1/roots-dir1"
, "test/workdir/dir1/roots-dir1/roots-file1"
, "test/workdir/dir1/sub1"
, "test/workdir/dir1/sub1/file1"
, "test/workdir/dir1/sub1/file2"
, "test/workdir/dir1/sub2"
, "test/workdir/dir1/sub2/file1"
, "test/workdir/dir1/sub2/file2"
, "test/workdir/dir1/sub2/file3"
, "test/workdir/dir1/sub2/roots-file1"
, "test/workdir/dir2"
, "test/workdir/dir2/file1"
, "test/workdir/dir2/sym1"
, "test/workdir/dir2/sym2"
, "test/workdir/dir3"
, "test/workdir/dir3/sub1"
, "test/workdir/dir3/sub1/file1"
, "test/workdir/dir3/sub2"
, "test/workdir/dir3/sub2/broken-sym1"
, "test/workdir/file1"
, "test/workdir/file2"
, "test/workdir/only-roots-dir1"
]
res `shouldMatchList` expected
describe "listAll" $ do
it "returns list excluding files & dirs ending with `3`" $ do
res :: [a] <- listMatching (not . filter "3") "test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir1"
, "test/workdir/dir1/roots-dir1"
, "test/workdir/dir1/roots-dir1/roots-file1"
, "test/workdir/dir1/sub1"
, "test/workdir/dir1/sub1/file1"
, "test/workdir/dir1/sub1/file2"
, "test/workdir/dir1/sub2"
, "test/workdir/dir1/sub2/file1"
, "test/workdir/dir1/sub2/file2"
, "test/workdir/dir1/sub2/roots-file1"
, "test/workdir/dir2"
, "test/workdir/dir2/file1"
, "test/workdir/dir2/sym1"
, "test/workdir/dir2/sym2"
, "test/workdir/file1"
, "test/workdir/file2"
, "test/workdir/only-roots-dir1"
]
res `shouldMatchList` expected
describe "listEverythingAccessible" $ do
it "returns everything that is accessible in workdir" $ do
res :: [a] <- listAccessible "test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir1"
, "test/workdir/dir1/roots-dir1"
, "test/workdir/dir1/roots-dir1/roots-file1"
, "test/workdir/dir1/sub1"
, "test/workdir/dir1/sub1/file1"
, "test/workdir/dir1/sub1/file2"
, "test/workdir/dir1/sub2"
, "test/workdir/dir1/sub2/file1"
, "test/workdir/dir1/sub2/file2"
, "test/workdir/dir1/sub2/file3"
, "test/workdir/dir1/sub2/roots-file1"
, "test/workdir/dir2"
, "test/workdir/dir2/file1"
, "test/workdir/dir2/sym1"
, "test/workdir/dir2/sym2"
, "test/workdir/dir3"
, "test/workdir/dir3/sub1"
, "test/workdir/dir3/sub1/file1"
, "test/workdir/dir3/sub2"
, "test/workdir/dir3/sub2/broken-sym1"
, "test/workdir/file1"
, "test/workdir/file2"
]
res `shouldMatchList` expected
describe "listDirectories" $ do
it "returns only directories" $ do
res :: [a] <- listDirectories "test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir1"
, "test/workdir/dir1/roots-dir1"
, "test/workdir/dir1/sub1"
, "test/workdir/dir1/sub2"
, "test/workdir/dir2"
, "test/workdir/dir3"
, "test/workdir/dir3/sub1"
, "test/workdir/dir3/sub2"
]
res `shouldMatchList` expected
describe "listFiles" $ do
it "returns only files" $ do
res :: [a] <- listRegularFiles "test/workdir"
let expected =
[ "test/workdir/dir1/roots-dir1/roots-file1"
, "test/workdir/dir1/sub1/file1"
, "test/workdir/dir1/sub1/file2"
, "test/workdir/dir1/sub2/file1"
, "test/workdir/dir1/sub2/file2"
, "test/workdir/dir1/sub2/file3"
, "test/workdir/dir1/sub2/roots-file1"
, "test/workdir/dir2/file1"
, "test/workdir/dir3/sub1/file1"
, "test/workdir/file1"
, "test/workdir/file2"
]
res `shouldMatchList` expected
describe "listSymbolicLinks" $ do
it "returns only symlinks" $ do
res :: [a] <- listSymbolicLinks "test/workdir"
let expected =
[ "test/workdir/dir2/sym1"
, "test/workdir/dir2/sym2"
, "test/workdir/dir3/sub2/broken-sym1"
]
res `shouldMatchList` expected
describe "listCustom" $ do
it "return everything except for symlinks and not within dir1" $ do
res :: [a] <-
listCustom
(not . filter "dir1")
(\file _ -> pure $ not $ Posix.isSymbolicLink file)
"test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir2"
, "test/workdir/dir2/file1"
, "test/workdir/dir3"
, "test/workdir/dir3/sub1"
, "test/workdir/dir3/sub1/file1"
, "test/workdir/dir3/sub2"
, "test/workdir/file1"
, "test/workdir/file2"
]
res `shouldMatchList` expected
context "Following symlinks" $ do
describe "followListEverything" $ do
it "returns expected list of everything in workdir" $ do
res :: [a] <- followList "test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir1"
, "test/workdir/dir1/roots-dir1"
, "test/workdir/dir1/roots-dir1/roots-file1"
, "test/workdir/dir1/sub1"
, "test/workdir/dir1/sub1/file1"
, "test/workdir/dir1/sub1/file2"
, "test/workdir/dir1/sub2"
, "test/workdir/dir1/sub2/file1"
, "test/workdir/dir1/sub2/file2"
, "test/workdir/dir1/sub2/file3"
, "test/workdir/dir1/sub2/roots-file1"
, "test/workdir/dir2"
, "test/workdir/dir2/file1"
, "test/workdir/dir2/sym1"
, "test/workdir/dir2/sym2"
, "test/workdir/dir2/sym2/sub1"
, "test/workdir/dir2/sym2/sub1/file1"
, "test/workdir/dir2/sym2/sub2"
, "test/workdir/dir2/sym2/sub2/broken-sym1"
, "test/workdir/dir3"
, "test/workdir/dir3/sub1"
, "test/workdir/dir3/sub1/file1"
, "test/workdir/dir3/sub2"
, "test/workdir/dir3/sub2/broken-sym1"
, "test/workdir/file1"
, "test/workdir/file2"
, "test/workdir/only-roots-dir1"
]
res `shouldMatchList` expected
describe "followListAll" $ do
it "returns list excluding files & dirs ending with `3`" $ do
res <- followListMatching (not . filter "3") "test/workdir"
let expected =
[ "test/workdir"
, "test/workdir/dir1"
, "test/workdir/dir1/roots-dir1"
, "test/workdir/dir1/roots-dir1/roots-file1"
, "test/workdir/dir1/sub1"
, "test/workdir/dir1/sub1/file1"
, "test/workdir/dir1/sub1/file2"
, "test/workdir/dir1/sub2"
, "test/workdir/dir1/sub2/file1"
, "test/workdir/dir1/sub2/file2"
, "test/workdir/dir1/sub2/roots-file1"
, "test/workdir/dir2"
, "test/workdir/dir2/file1"
, "test/workdir/dir2/sym1"
, "test/workdir/dir2/sym2"
, "test/workdir/dir2/sym2/sub1"
, "test/workdir/dir2/sym2/sub1/file1"
, "test/workdir/dir2/sym2/sub2"
, "test/workdir/dir2/sym2/sub2/broken-sym1"
, "test/workdir/file1"
, "test/workdir/file2"
, "test/workdir/only-roots-dir1"
]
res `shouldMatchList` expected