File: Directory.hs

package info (click to toggle)
haskell-glob 0.10.2-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 220 kB
  • sloc: haskell: 1,583; makefile: 2
file content (174 lines) | stat: -rw-r--r-- 5,794 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
{-# LANGUAGE CPP #-}
module Tests.Directory where

import Test.Framework
import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2
import Test.QuickCheck (Property, (===))
import Test.HUnit.Base hiding (Test)
import Data.Function (on)
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid (mappend)
#endif
import Data.List ((\\), sort)
import qualified Data.DList as DList

import System.FilePath.Glob.Base
import System.FilePath.Glob.Directory
import System.FilePath.Glob.Primitive
import System.FilePath.Glob.Utils
import Tests.Base (PString, unPS)

tests :: Test
tests = testGroup "Directory"
   [ testCase "includeUnmatched" caseIncludeUnmatched
   , testCase "onlyMatched" caseOnlyMatched
   , testGroup "commonDirectory"
       [ testGroup "edge-cases" testsCommonDirectoryEdgeCases
       , testProperty "property" prop_commonDirectory
       ]
   , testCase "globDir1" caseGlobDir1
   , testGroup "repeated-path-separators" testsRepeatedPathSeparators
   ]

caseIncludeUnmatched :: Assertion
caseIncludeUnmatched = do
   let pats = ["**/D*.hs", "**/[MU]*.hs"]
   everything <- getRecursiveContentsDir "System"
   let expectedMatches =
          [ [ "System/FilePath/Glob/Directory.hs" ]
          , [ "System/FilePath/Glob/Match.hs"
            , "System/FilePath/Glob/Utils.hs"
            ]
          ]
   let everythingElse = everything \\ concat expectedMatches

   result <- globDirWith (GlobOptions matchDefault True)
                         (map compile pats)
                         "System"
   mapM_ (uncurry assertEqualUnordered) (zip expectedMatches (fst result))

   case snd result of
       Nothing -> assertFailure "Expected Just a list of unmatched files"
       Just unmatched -> assertEqualUnordered everythingElse unmatched

caseOnlyMatched :: Assertion
caseOnlyMatched = do
   let pats = ["**/D*.hs", "**/[MU]*.hs"]
   let expectedMatches =
          [ [ "System/FilePath/Glob/Directory.hs" ]
          , [ "System/FilePath/Glob/Match.hs"
            , "System/FilePath/Glob/Utils.hs"
            ]
          ]

   result <- globDirWith globDefault
                         (map compile pats)
                         "System"

   mapM_ (uncurry assertEqualUnordered) (zip expectedMatches (fst result))
   assertEqual "" Nothing (snd result)

caseGlobDir1 :: Assertion
caseGlobDir1 = do
   -- this is little a bit of a hack; we pass the same pattern twice to ensure
   -- that the optimization in the single pattern case is bypassed
   let naiveGlobDir1 p = fmap head . globDir [p, p]
   let pat = compile "FilePath/*/*.hs"
   let dir = "System"

   actual <- globDir1 pat dir
   expected <- naiveGlobDir1 pat dir
   assertEqual "" expected actual

assertEqualUnordered :: (Ord a, Show a) => [a] -> [a] -> Assertion
assertEqualUnordered = assertEqual "" `on` sort

-- Like 'getRecursiveContents', except this function removes the root directory
-- from the returned list, so that it should match* the union of matched and
-- unmatched files returned from 'globDirWith', where the same directory was
-- given as the directory argument.
--
-- * to be a little more precise, these files will only match up to
-- normalisation of paths e.g. some patterns will cause the list of matched
-- files to contain repeated slashes, whereas the list returned by this
-- function will not have repeated slashes.
getRecursiveContentsDir :: FilePath -> IO [FilePath]
getRecursiveContentsDir root =
  fmap (filter (/= root) . DList.toList) (getRecursiveContents root)

-- These two patterns should always be equal
prop_commonDirectory' :: String -> (Pattern, Pattern)
prop_commonDirectory' str =
   let pat    = compile str
       (a, b) = commonDirectory pat
    in (pat, literal a `mappend` b)

prop_commonDirectory :: PString -> Property
prop_commonDirectory = uncurry (===) . prop_commonDirectory' . unPS

testsCommonDirectoryEdgeCases :: [Test]
testsCommonDirectoryEdgeCases = zipWith mkTest [1 :: Int ..] testData
 where
   mkTest i (input, expected) =
      testCase (show i) $ do
         assertEqual "" expected (commonDirectory (compile input))
         uncurry (assertEqual "") (prop_commonDirectory' input)

   testData =
      [ ("[.]/*", ("", compile "[.]"))
      , ("foo/[.]bar/*", ("", compile "[.]"))
      , ("[.]foo/bar/*", ("", compile "[.]foo/bar/*"))
      , ("foo.bar/baz/*", ("foo.bar/baz/", compile "*"))
      , ("[f]oo[.]/bar/*", ("foo./bar/", compile "*"))
      , ("foo[.]bar/baz/*", ("foo.bar/baz/", compile "*"))
      , (".[.]/foo/*", ("../foo/", compile "*"))
      ]

-- see #16
testsRepeatedPathSeparators :: [Test]
testsRepeatedPathSeparators = zipWith mkTest [1 :: Int ..] testData
 where
   mkTest i (dir, pat, expected) =
      testCase (show i) $ do
         actual <- globDir1 (compile pat) dir
         assertEqualUnordered expected actual

   testData =
      [ ( "System"
        , "*//Glob///[U]*.hs"
        , [ "System/FilePath//Glob///Utils.hs"
          ]
        )
      , ( "System"
        , "**//[GU]*.hs"
        , [ "System/FilePath//Glob.hs"
          , "System/FilePath/Glob//Utils.hs"
          ]
        )
      , ( "System"
        , "File**/"
        , [ "System/FilePath/"
          ]
        )
      , ( "System"
        , "File**//"
        , [ "System/FilePath//"
          ]
        )
      , ( "System"
        , "File**///"
        , [ "System/FilePath///"
          ]
        )
      , ( "System/FilePath"
        , "**//Glob.hs"
        , [ "System/FilePath//Glob.hs"
          ]
        )
      , ( "System"
        , "**Path/Glob//Utils.hs"
        , [ "System/FilePath/Glob//Utils.hs"
          ]
        )
      ]