streamly-0.11.0: test/Streamly/Test/FileSystem/DirIO.hs
-- |
-- Module : Streamly.Test.FileSystem.DirIO
-- Copyright : (c) 2019 Composewell Technologies
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -Wno-unrecognised-warning-flags #-}
{-# OPTIONS_GHC -Wno-x-partial #-}
module Main (main) where
--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------
import Control.Exception (try, IOException)
import Data.Word (Word8)
import GHC.IO.Encoding (setLocaleEncoding, utf8)
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
import Streamly.Data.Array (Array)
#endif
import System.Directory (createDirectoryLink)
import qualified Streamly.Unicode.Stream as Unicode
import qualified Streamly.Internal.Unicode.Stream as Unicode (lines)
import qualified Streamly.Data.Stream.Prelude as Stream
import qualified Streamly.Data.Fold as Fold
import qualified Streamly.Data.StreamK as StreamK
import qualified Streamly.Internal.FileSystem.DirIO as Dir
import Prelude hiding (last, length)
import BenchTestLib.DirIO
import Test.Hspec as H
--------------------------------------------------------------------------------
-- Main
--------------------------------------------------------------------------------
moduleName :: String
moduleName = "FileSystem.DirIO"
testCorrectness
:: [FilePath] -> Stream.Stream IO Word8 -> Expectation
testCorrectness expectation lister = do
reality <-
Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream
$ Unicode.lines Fold.toList
$ Unicode.decodeUtf8 lister
reality `shouldBe` expectation
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
testCorrectnessByteChunked
:: [FilePath] -> Stream.Stream IO (Array Word8) -> Expectation
testCorrectnessByteChunked expectation lister = do
reality <-
Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream
$ Unicode.lines Fold.toList
$ Unicode.decodeUtf8Chunks lister
reality `shouldBe` expectation
#endif
ignoringError :: IO a -> IO ()
ignoringError act = do
(_ :: Either IOException a) <- try act
pure ()
testSymLinkFollow :: Spec
testSymLinkFollow = do
let fp = "benchmark-tmp/dir-structure-small-sym"
-- We create and use a different directory tree here for these tests because
-- of convinence.
pathsUnsorted <- runIO $ createDirStucture fp 2 3
paths <-
runIO
$ Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream $ Stream.fromList pathsUnsorted
runIO $ ignoringError $ do
createDirectoryLink "./dir_1" (fp ++ "/sym-link-1")
createDirectoryLink "./dir_1/dir_2" (fp ++ "/sym-link-2")
createDirectoryLink "./broken_link" (fp ++ "/sym-link-3")
let answerFollowSym =
(fp ++ "/sym-link-1")
: (fp ++ "/sym-link-1/dir_1")
: (fp ++ "/sym-link-1/dir_2")
: (fp ++ "/sym-link-1/dir_3")
: (fp ++ "/sym-link-2")
: paths
answerNoFollowSym =
(fp ++ "/sym-link-1")
: (fp ++ "/sym-link-2")
: (fp ++ "/sym-link-3")
: paths
sortedAnswerFollowSym <-
Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream $ Stream.fromList answerFollowSym
sortedAnswerNoFollowSym <-
Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream $ Stream.fromList answerNoFollowSym
describe "Symlink" $ do
it "followSymlinks True" $
testCorrectness
sortedAnswerFollowSym
(listDirUnfoldDfs
(Dir.followSymlinks True . Dir.ignoreMissing True)
fp)
it "followSymlinks False" $
testCorrectness
sortedAnswerNoFollowSym
(listDirUnfoldDfs
(Dir.followSymlinks False . Dir.ignoreMissing True)
fp)
-- | List the current directory recursively
main :: IO ()
main = do
setLocaleEncoding utf8
let smallTree = "benchmark-tmp/dir-structure-small"
bigTree = "benchmark-tmp/dir-structure-big"
pathsSmallUnsorted <- createDirStucture smallTree 2 3
pathsBigUnsorted <- createDirStucture bigTree 5 5
pathsSmall <-
Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream $ Stream.fromList pathsSmallUnsorted
pathsBig <-
Stream.fold Fold.toList
$ StreamK.toStream
$ StreamK.sortBy compare
$ StreamK.fromStream $ Stream.fromList pathsBigUnsorted
hspec $
describe moduleName $ do
describe "Sanity" $ do
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
it "listDirByteChunked" $
testCorrectnessByteChunked
(tail pathsBig) (listDirByteChunked bigTree)
#endif
-- NOTE: The BFS traversal fails with:
-- openDirStream: resource exhausted (Too many open files)
-- if a bigger directory tree is used
it "listDirUnfoldDfs" $
testCorrectness pathsBig (listDirUnfoldDfs id bigTree)
it "listDirUnfoldBfs" $
testCorrectness pathsSmall (listDirUnfoldBfs id smallTree)
it "listDirUnfoldBfsRev" $
testCorrectness pathsSmall (listDirUnfoldBfsRev id smallTree)
it "listDirConcatDfs" $
testCorrectness pathsBig (listDirConcatDfs id bigTree)
it "listDirConcatBfs" $
testCorrectness pathsSmall (listDirConcatBfs id smallTree)
it "listDirConcatBfsRev" $
testCorrectness pathsSmall (listDirConcatBfsRev id smallTree)
it "listDirAppend" $
testCorrectness pathsBig (listDirAppend id bigTree)
it "listDirInterleave" $
testCorrectness pathsBig (listDirInterleave id bigTree)
it "listDirPar" $
testCorrectness pathsBig (listDirPar id bigTree)
it "listDirParInterleaved" $
testCorrectness pathsBig (listDirParInterleaved id bigTree)
it "listDirParOrdered" $
testCorrectness pathsBig (listDirParOrdered id bigTree)
it "listDirChunkDfs" $
testCorrectness pathsBig (listDirChunkDfs id bigTree)
it "listDirChunkBfs" $
testCorrectness pathsSmall (listDirChunkBfs id smallTree)
it "listDirChunkBfsRev" $
testCorrectness pathsSmall (listDirChunkBfsRev id smallTree)
it "listDirChunkAppend" $
testCorrectness pathsBig (listDirChunkAppend id bigTree)
it "listDirChunkInterleave" $
testCorrectness pathsBig (listDirChunkInterleave id bigTree)
it "listDirChunkPar" $
testCorrectness pathsBig (listDirChunkPar id bigTree)
it "listDirChunkParInterleaved" $
testCorrectness pathsBig (listDirChunkParInterleaved id bigTree)
it "listDirChunkParOrdered" $
testCorrectness pathsBig (listDirChunkParOrdered id bigTree)
testSymLinkFollow