system-filepath 0.3.3 → 0.3.4
raw patch · 11 files changed
+334/−116 lines, 11 filesdep +deepseqdep ~text
Dependencies added: deepseq
Dependency ranges changed: text
Files
- lib/Filesystem/Path.hs +5/−9
- lib/Filesystem/Path/CurrentOS.hs +7/−1
- lib/Filesystem/Path/Internal.hs +87/−31
- lib/Filesystem/Path/Rules.hs +105/−66
- scripts/common.bash +23/−0
- scripts/run-benchmarks +21/−0
- scripts/run-coverage +21/−0
- scripts/run-tests +17/−0
- system-filepath.cabal +12/−3
- tests/Tests.hs +35/−6
- tests/system-filepath-tests.cabal +1/−0
lib/Filesystem/Path.hs view
@@ -132,11 +132,8 @@ dirname :: FilePath -> FilePath dirname p = case reverse (pathDirectories p) of [] -> FilePath Nothing [] Nothing []- (d:_) -> let- d':exts = T.split (== '.') (chunkText d)- chunk txt = d { chunkText = txt }- in FilePath Nothing [] (Just (chunk d')) (map chunk exts)-+ (d:_) -> case parseFilename d of+ (base, exts) -> FilePath Nothing [] base exts -- | Retrieve a 'FilePath'’s basename component. --@@ -183,7 +180,7 @@ directories = xDirectories ++ pathDirectories y xDirectories = (pathDirectories x ++) $ if null (filename x) then []- else [filenameChunk True x]+ else [filenameText x] -- | An alias for 'append'. (</>) :: FilePath -> FilePath -> FilePath@@ -285,7 +282,7 @@ -- | Get a 'FilePath'’s full extension list. extensions :: FilePath -> [T.Text]-extensions = map chunkText . pathExtensions+extensions = map unescape' . pathExtensions -- | Get whether a 'FilePath'’s last extension is the predicate. hasExtension :: FilePath -> T.Text -> Bool@@ -298,8 +295,7 @@ -- | Append many extensions to the end of a 'FilePath'. addExtensions :: FilePath -> [T.Text] -> FilePath addExtensions p exts = p { pathExtensions = newExtensions } where- newExtensions = pathExtensions p ++ chunks- chunks = map (\e -> Chunk e True) exts+ newExtensions = pathExtensions p ++ exts -- | An alias for 'addExtension'. (<.>) :: FilePath -> T.Text -> FilePath
lib/Filesystem/Path/CurrentOS.hs view
@@ -41,7 +41,7 @@ import qualified Filesystem.Path as F import qualified Filesystem.Path.Rules as R -#if defined(CABAL_OS_WINDOWS)+#if defined(CABAL_OS_WINDOWS) || defined(CABAL_OS_DARWIN) #define PLATFORM_PATH_FORMAT T.Text #else #define PLATFORM_PATH_FORMAT B.ByteString@@ -50,6 +50,12 @@ currentOS :: R.Rules PLATFORM_PATH_FORMAT #if defined(CABAL_OS_WINDOWS) currentOS = R.windows+#elif defined(CABAL_OS_DARWIN)+#if __GLASGOW_HASKELL__ >= 702+currentOS = R.darwin_ghc702+#else+currentOS = R.darwin+#endif #else #if __GLASGOW_HASKELL__ >= 702 currentOS = R.posix_ghc702
lib/Filesystem/Path/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} -- |@@ -12,29 +13,27 @@ import Prelude hiding (FilePath) +import Control.DeepSeq (NFData, rnf)+import qualified Control.Exception as Exc+import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8+import Data.Char (chr, ord) import Data.Data (Data) import Data.List (intersperse)+import Data.Ord (comparing) import qualified Data.Text as T import qualified Data.Text.Encoding as TE+import Data.Text.Encoding.Error (UnicodeException) import Data.Typeable (Typeable)+import System.IO.Unsafe (unsafePerformIO) ------------------------------------------------------------------------------- -- File Paths ------------------------------------------------------------------------------- -data Chunk = Chunk- { chunkText :: T.Text- , chunkGood :: Bool- }- deriving (Ord, Data, Typeable)--instance Eq Chunk where- (Chunk x _) == (Chunk y _) = x == y--type Directory = Chunk-type Basename = Chunk-type Extension = Chunk+type Directory = T.Text+type Basename = T.Text+type Extension = T.Text data Root = RootPosix@@ -48,34 +47,42 @@ , pathBasename :: Maybe Basename , pathExtensions :: [Extension] }- deriving (Eq, Ord, Data, Typeable)+ deriving (Data, Typeable) +instance Eq FilePath where+ x == y = compare x y == EQ++instance Ord FilePath where+ compare = comparing (\p ->+ (pathRoot p+ , fmap unescape' (pathDirectories p)+ , fmap unescape' (pathBasename p)+ , fmap unescape' (pathExtensions p)+ ))++instance NFData Root where+ rnf (RootWindowsVolume c) = rnf c+ rnf _ = ()++instance NFData FilePath where+ rnf p = rnf (pathRoot p) `seq` rnf (pathDirectories p) `seq` rnf (pathBasename p) `seq` rnf (pathExtensions p)+ -- | A file path with no root, directory, or filename empty :: FilePath empty = FilePath Nothing [] Nothing [] -dot :: Chunk-dot = Chunk (T.pack ".") True+dot :: T.Text+dot = T.pack "." -dots :: Chunk-dots = Chunk (T.pack "..") True+dots :: T.Text+dots = T.pack ".." -filenameChunk :: Bool -> FilePath -> Chunk-filenameChunk strict p = Chunk (T.concat texts) allGood where- name = maybe (Chunk T.empty True) id (pathBasename p)+filenameText :: FilePath -> T.Text+filenameText p = T.concat (name:exts) where+ name = maybe T.empty id (pathBasename p) exts = case pathExtensions p of [] -> []- exts' -> intersperse dot ((Chunk T.empty True):exts')- chunks = name:exts- - texts = map chunkText' chunks- allGood = and (map chunkGood chunks)- - chunkText' c = if chunkGood c- then if allGood || not strict- then chunkText c- else T.pack (B8.unpack (TE.encodeUtf8 (chunkText c)))- else chunkText c+ exts' -> intersperse dot (T.empty:exts') ------------------------------------------------------------------------------- -- Rules@@ -157,3 +164,52 @@ instance Show (Rules a) where showsPrec d r = showParen (d > 10) (showString "Rules " . shows (rulesName r))++textSplitBy :: (Char -> Bool) -> T.Text -> [T.Text]+#if MIN_VERSION_text(0,11,0)+textSplitBy = T.split+#else+textSplitBy = T.splitBy+#endif++unescape :: T.Text -> (T.Text, Bool)+unescape t = if T.any (\c -> ord c >= 0xEF00 && ord c <= 0xEFFF) t+ then (T.map (\c -> if ord c >= 0xEF00 && ord c <= 0xEFFF+ then chr (ord c - 0xEF00)+ else c) t, False)+ else (t, True)++unescape' :: T.Text -> T.Text+unescape' = fst . unescape++unescapeBytes' :: T.Text -> B8.ByteString+unescapeBytes' t = B8.concat (map (\c -> if ord c >= 0xEF00 && ord c <= 0xEFFF+ then B8.singleton (chr (ord c - 0xEF00))+ else TE.encodeUtf8 (T.singleton c)) (T.unpack t))++parseFilename :: T.Text -> (Maybe Basename, [Extension])+parseFilename filename = parsed where+ parsed = if T.null filename+ then (Nothing, [])+ else case textSplitBy (== '.') filename of+ [] -> (Nothing, [])+ (name':exts') -> (Just (checkChunk name'), map checkChunk exts')+ + checkChunk t = if chunkGood t+ then t+ else case maybeDecodeUtf8 (unescapeBytes' t) of+ Just text -> text+ Nothing -> t+ + chunkGood t = not (T.any (\c -> ord c >= 0xEF00 && ord c <= 0xEFFF) t)++maybeDecodeUtf8 :: B.ByteString -> Maybe T.Text+maybeDecodeUtf8 = excToMaybe . TE.decodeUtf8 where+ excToMaybe :: a -> Maybe a+ excToMaybe x = unsafePerformIO $ Exc.catch+ (fmap Just (Exc.evaluate x))+ unicodeError+ + unicodeError :: UnicodeException -> IO (Maybe a)+ unicodeError _ = return Nothing+
lib/Filesystem/Path/Rules.hs view
@@ -11,6 +11,8 @@ , posix , posix_ghc702 , windows+ , darwin+ , darwin_ghc702 -- * Type conversions , toText@@ -28,16 +30,13 @@ import Prelude hiding (FilePath, null) import qualified Prelude as P -import qualified Control.Exception as Exc import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8-import Data.Char (toUpper, chr)+import Data.Char (toUpper, chr, ord) import Data.List (intersperse) import qualified Data.Text as T import qualified Data.Text.Encoding as TE-import Data.Text.Encoding.Error (UnicodeException) import System.IO ()-import System.IO.Unsafe (unsafePerformIO) import Filesystem.Path hiding (root, filename, basename) import Filesystem.Path.Internal@@ -52,24 +51,14 @@ RootWindowsVolume c -> c : ":\\" RootWindowsCurrentVolume -> "\\" -directoryChunks :: Bool -> FilePath -> [Chunk]-directoryChunks strict path = pathDirectories path ++ [filenameChunk strict path]--maybeDecodeUtf8 :: B.ByteString -> Maybe T.Text-maybeDecodeUtf8 = excToMaybe . TE.decodeUtf8 where- excToMaybe :: a -> Maybe a- excToMaybe x = unsafePerformIO $ Exc.catch- (fmap Just (Exc.evaluate x))- unicodeError- - unicodeError :: UnicodeException -> IO (Maybe a)- unicodeError _ = return Nothing+directoryChunks :: FilePath -> [T.Text]+directoryChunks path = pathDirectories path ++ [filenameText path] ------------------------------------------------------------------------------- -- POSIX ------------------------------------------------------------------------------- --- | Linux, BSD, OS X, and other UNIX or UNIX-like operating systems.+-- | Linux, BSD, and other UNIX or UNIX-like operating systems. posix :: Rules B.ByteString posix = Rules { rulesName = T.pack "POSIX"@@ -83,75 +72,78 @@ , decodeString = posixFromBytes . B8.pack } --- | Linux, BSD, OS X, and other UNIX or UNIX-like operating systems.+-- | Linux, BSD, and other UNIX or UNIX-like operating systems. ----- This variant is for use with GHC 7.2 or later, which tries to decode--- file paths in its IO computations.+-- This is a variant of 'posix' for use with GHC 7.2 or later, which tries to+-- decode file paths in its IO computations.+--+-- Since: 0.3.3 posix_ghc702 :: Rules B.ByteString posix_ghc702 = posix- { encodeString = T.unpack . either id id . posixToText- , decodeString = posixFromText . T.pack+ { rulesName = T.pack "POSIX (GHC 7.2)"+ , encodeString = posixToGhcString+ , decodeString = posixFromGhcString } posixToText :: FilePath -> Either T.Text T.Text posixToText p = if good then Right text else Left text where- good = and (map chunkGood chunks)- text = T.concat (root : map chunkText chunks)+ good = and (map snd chunks)+ text = T.concat (root : map fst chunks) root = rootText (pathRoot p)- chunks = intersperse (Chunk (T.pack "/") True) (directoryChunks False p)+ chunks = intersperse (T.pack "/", True) (map unescape (directoryChunks p)) -posixFromChunks :: [Chunk] -> FilePath+posixFromChunks :: [T.Text] -> FilePath posixFromChunks chunks = FilePath root directories basename exts where- (root, pastRoot) = if T.null (chunkText (head chunks))+ (root, pastRoot) = if T.null (head chunks) then (Just RootPosix, tail chunks) else (Nothing, chunks) (directories, filename)- | P.null pastRoot = ([], Chunk T.empty True)+ | P.null pastRoot = ([], T.empty) | otherwise = case last pastRoot of- fn | fn == dot -> (goodDirs pastRoot, Chunk T.empty True)- fn | fn == dots -> (goodDirs pastRoot, Chunk T.empty True)+ fn | fn == dot -> (goodDirs pastRoot, T.empty)+ fn | fn == dots -> (goodDirs pastRoot, T.empty) fn -> (goodDirs (init pastRoot), fn) - goodDirs = filter (not . T.null . chunkText)- - (basename, exts) = if T.null (chunkText filename)- then (Nothing, [])- else case T.split (== '.') (chunkText filename) of- [] -> (Nothing, [])- (name':exts') -> if chunkGood filename- then (Just (Chunk name' True), map (\e -> Chunk e True) exts')- else (Just (checkChunk name'), map checkChunk exts')+ goodDirs = filter (not . T.null) - checkChunk raw = case maybeDecodeUtf8 (B8.pack (T.unpack raw)) of- Just text -> Chunk text True- Nothing -> Chunk raw False+ (basename, exts) = parseFilename filename posixFromText :: T.Text -> FilePath posixFromText text = if T.null text then empty- else posixFromChunks (map (\t -> Chunk t True) (T.split (== '/') text))+ else posixFromChunks (textSplitBy (== '/') text) posixToBytes :: FilePath -> B.ByteString posixToBytes p = B.concat (root : chunks) where root = TE.encodeUtf8 (rootText (pathRoot p))- chunks = intersperse (B8.pack "/") (map chunkBytes (directoryChunks True p))- chunkBytes c = if chunkGood c- then TE.encodeUtf8 (chunkText c)- else B8.pack (T.unpack (chunkText c))+ chunks = intersperse (B8.pack "/") (map chunkBytes (directoryChunks p))+ chunkBytes t = if T.any (\c -> ord c >= 0xEF00 && ord c <= 0xEFFF) t+ then unescapeBytes' t+ else TE.encodeUtf8 t posixFromBytes :: B.ByteString -> FilePath posixFromBytes bytes = if B.null bytes then empty else posixFromChunks $ flip map (B.split 0x2F bytes) $ \b -> case maybeDecodeUtf8 b of- Just text -> Chunk text True- Nothing -> Chunk (T.pack (B8.unpack b)) False+ Just text -> text+ Nothing -> T.pack (map (\c -> if ord c >= 0x80+ then chr (ord c + 0xEF00)+ else c) (B8.unpack b)) +posixToGhcString :: FilePath -> String+posixToGhcString p = P.concat (root : chunks) where+ root = T.unpack (rootText (pathRoot p))+ chunks = intersperse "/" (map T.unpack (directoryChunks p))++posixFromGhcString :: String -> FilePath+posixFromGhcString = posixFromText . T.pack+ posixValid :: FilePath -> Bool posixValid p = validRoot && validDirectories where- validDirectories = all validChunk (directoryChunks True p)- validChunk ch = not (T.any (\c -> c == '\0' || c == '/') (chunkText ch))+ validDirectories = all validChunk (directoryChunks p)+ validChunk ch = not (T.any (\c -> c == '\0' || c == '/') ch) validRoot = case pathRoot p of Nothing -> True Just RootPosix -> True@@ -162,6 +154,57 @@ normSearch bytes = if B.null bytes then B8.pack "." else bytes -------------------------------------------------------------------------------+-- Darwin+-------------------------------------------------------------------------------++-- | Darwin and Mac OS X.+--+-- This is almost identical to 'posix', but with a native path type of 'T.Text'+-- rather than 'B.ByteString'.+--+-- Since: 0.3.4+darwin :: Rules T.Text+darwin = Rules+ { rulesName = T.pack "Darwin"+ , valid = posixValid+ , splitSearchPath = darwinSplitSearch+ , toText = Right . darwinToText+ , fromText = posixFromText+ , encode = darwinToText+ , decode = posixFromText+ , encodeString = darwinToString+ , decodeString = darwinFromString+ }++-- | Darwin and Mac OS X.+--+-- This is a variant of 'darwin' for use with GHC 7.2 or later, which tries to+-- decode file paths in its IO computations.+--+-- Since: 0.3.4+darwin_ghc702 :: Rules T.Text+darwin_ghc702 = darwin+ { rulesName = T.pack "Darwin (GHC 7.2)"+ , encodeString = T.unpack . darwinToText+ , decodeString = posixFromText . T.pack+ }++darwinToText :: FilePath -> T.Text+darwinToText p = T.concat (root : chunks) where+ root = rootText (pathRoot p)+ chunks = intersperse (T.pack "/") (directoryChunks p)++darwinToString :: FilePath -> String+darwinToString = B8.unpack . TE.encodeUtf8 . darwinToText++darwinFromString :: String -> FilePath+darwinFromString = posixFromText . TE.decodeUtf8 . B8.pack++darwinSplitSearch :: T.Text -> [FilePath]+darwinSplitSearch = map (posixFromText . normSearch) . textSplitBy (== ':') where+ normSearch text = if T.null text then T.pack "." else text++------------------------------------------------------------------------------- -- Windows ------------------------------------------------------------------------------- @@ -182,13 +225,13 @@ winToText :: FilePath -> T.Text winToText p = T.concat (root : chunks) where root = rootText (pathRoot p)- chunks = intersperse (T.pack "\\") (map chunkText (directoryChunks False p))+ chunks = intersperse (T.pack "\\") (directoryChunks p) winFromText :: T.Text -> FilePath winFromText text = if T.null text then empty else path where path = FilePath root directories basename exts - split = T.split (\c -> c == '/' || c == '\\') text+ split = textSplitBy (\c -> c == '/' || c == '\\') text (root, pastRoot) = let head' = head split@@ -204,17 +247,13 @@ (directories, filename) | P.null pastRoot = ([], T.empty) | otherwise = case last pastRoot of- fn | fn == chunkText dot -> (goodDirs pastRoot, T.empty)- fn | fn == chunkText dots -> (goodDirs pastRoot, T.empty)+ fn | fn == dot -> (goodDirs pastRoot, T.empty)+ fn | fn == dots -> (goodDirs pastRoot, T.empty) fn -> (goodDirs (init pastRoot), fn) - goodDirs = map (\t -> Chunk t True) . filter (not . T.null)+ goodDirs = filter (not . T.null) - (basename, exts) = if T.null filename- then (Nothing, [])- else case T.split (== '.') filename of- [] -> (Nothing, [])- (name':exts') -> (Just (Chunk name' True), map (\e -> Chunk e True) exts')+ (basename, exts) = parseFilename filename winValid :: FilePath -> Bool winValid p = validRoot && noReserved && validCharacters where@@ -233,11 +272,11 @@ _ -> False noExt = p { pathExtensions = [] }- noReserved = flip all (directoryChunks False noExt)- $ \fn -> notElem (T.toUpper (chunkText fn)) reservedNames+ noReserved = flip all (directoryChunks noExt)+ $ \fn -> notElem (T.toUpper fn) reservedNames - validCharacters = flip all (directoryChunks False p)- $ not . T.any (`elem` reservedChars) . chunkText+ validCharacters = flip all (directoryChunks p)+ $ not . T.any (`elem` reservedChars) winSplit :: T.Text -> [FilePath]-winSplit = map winFromText . filter (not . T.null) . T.split (== ';')+winSplit = map winFromText . filter (not . T.null) . textSplitBy (== ';')
+ scripts/common.bash view
@@ -0,0 +1,23 @@+PATH="$PATH:$PWD/cabal-dev/bin/"++VERSION=$(awk '/^version:/{print $2}' system-filepath.cabal)++CABAL_DEV=$(which cabal-dev)+XZ=$(which xz)++require_cabal_dev()+{+ if [ -z "$CABAL_DEV" ]; then+ echo "Can't find 'cabal-dev' executable; make sure it exists on your "'$PATH'+ echo "Cowardly refusing to fuck with the global package database"+ exit 1+ fi+}++clean_dev_install()+{+ require_cabal_dev+ + rm -rf dist+ $CABAL_DEV install || exit 1+}
+ scripts/run-benchmarks view
@@ -0,0 +1,21 @@+#!/bin/bash+if [ ! -f 'system-filepath.cabal' ]; then+ echo -n "Can't find system-filepath.cabal; please run this script as"+ echo -n " ./scripts/run-benchmarks from within the system-filepath source"+ echo " directory"+ exit 1+fi++. scripts/common.bash++require_cabal_dev++rm -rf dist+cabal-dev install || exit 1++pushd benchmarks+rm -rf dist+$CABAL_DEV -s ../cabal-dev install || exit 1+popd++cabal-dev/bin/system-filepath_benchmarks $@
+ scripts/run-coverage view
@@ -0,0 +1,21 @@+#!/bin/bash+if [ ! -f 'system-filepath.cabal' ]; then+ echo -n "Can't find system-filepath.cabal; please run this script as"+ echo -n " ./scripts/run-coverage from within the system-filepath source"+ echo " directory"+ exit 1+fi++. scripts/common.bash++require_cabal_dev++pushd tests+$CABAL_DEV -s ../cabal-dev install --flags="coverage" || exit 1+popd++rm -f system-filepath_tests.tix+cabal-dev/bin/system-filepath_tests $@++hpc markup --srcdir=src --srcdir=tests/ system-filepath_tests.tix --destdir=hpc-markup --exclude=Main+hpc report --srcdir=src --srcdir=tests/ system-filepath_tests.tix --exclude=Main
+ scripts/run-tests view
@@ -0,0 +1,17 @@+#!/bin/bash+if [ ! -f 'system-filepath.cabal' ]; then+ echo -n "Can't find system-filepath.cabal; please run this script as"+ echo -n " ./scripts/run-tests from within the system-filepath source"+ echo " directory"+ exit 1+fi++. scripts/common.bash++require_cabal_dev++pushd tests+$CABAL_DEV -s ../cabal-dev install || exit 1+popd++cabal-dev/bin/system-filepath_tests $@
system-filepath.cabal view
@@ -1,5 +1,5 @@ name: system-filepath-version: 0.3.3+version: 0.3.4 synopsis: High-level, byte-based file and directory path manipulations license: MIT license-file: license.txt@@ -14,6 +14,11 @@ bug-reports: mailto:jmillikin@gmail.com extra-source-files:+ scripts/common.bash+ scripts/run-benchmarks+ scripts/run-coverage+ scripts/run-tests+ -- tests/system-filepath-tests.cabal tests/Tests.hs @@ -24,7 +29,7 @@ source-repository this type: bzr location: https://john-millikin.com/branches/hs-filepath/0.3/- tag: system-filepath_0.3.3+ tag: system-filepath_0.3.4 library ghc-options: -Wall -O2@@ -33,10 +38,14 @@ build-depends: base >= 3 && < 5 , bytestring >= 0.9 && < 0.10- , text >= 0.3 && < 0.12+ , deepseq >= 1.1 && < 1.3+ , text >= 0.7.1 && < 0.12 if os(windows) cpp-options: -DCABAL_OS_WINDOWS++ if os(darwin)+ cpp-options: -DCABAL_OS_DARWIN exposed-modules: Filesystem.Path
tests/Tests.hs view
@@ -5,8 +5,8 @@ import Prelude hiding (FilePath) -import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as B8+import Data.Char (toUpper) import Data.List (intercalate) import qualified Data.Text as T import Data.Text (Text)@@ -64,6 +64,7 @@ , test_EncodeString , test_DecodeString , test_EqualsIgnoresPosixEncoding+ , test_ShowRules ] test_Empty :: Suite@@ -137,7 +138,7 @@ $expect $ equal (dirnameExts "foo.d/bar") ["d"] -- reparsing preserves good/bad encoding state- $expect $ equal (dirnameExts "foo.\xB1.\xDD\xAA/bar") ["\xB1", "\xDD\xAA"]+ $expect $ equal (dirnameExts "foo.\xB1.\xDD\xAA/bar") ["\xB1", "\x76A"] test_Basename :: Suite test_Basename = assertions "basename" $ do@@ -201,7 +202,7 @@ $expect $ equal (toText posix (p "\xF0\x9D\x84\x9E/\xED\xA0\x80")) (Left (T.pack "\x1D11E/\xED\xA0\x80")) $expect $ equal (toText posix (p "\xED.\xF0\x9D\x84\x9E.\xA0\x80")) (Left (T.pack "\xED.\x1D11E.\xA0\x80")) $expect $ equal (toText posix (p "\xB1.\xDD\xAA")) (Left (T.pack "\xB1.\x76A"))- $expect $ equal (toText posix (p "\xB1.\xDD\xAA" </> p "foo")) (Left (T.pack "\xB1.\xDD\xAA/foo"))+ $expect $ equal (toText posix (p "\xB1.\xDD\xAA" </> p "foo")) (Left (T.pack "\xB1.\x76A/foo")) test_FromText :: Suite test_FromText = assertions "fromText" $ do@@ -384,8 +385,8 @@ test_EncodeString_Posix_Ghc702 = assertions "posix_ghc702" $ do let enc = encodeString posix_ghc702 $expect $ equal (enc (fromChar8 "test")) "test"- $expect $ equal (enc (fromChar8 "test\xA1\xA2")) "test\xA1\xA2"- $expect $ equal (enc (fromChar8 "\xC2\xA1\xC2\xA2/test\xA1\xA2")) "\xA1\xA2/test\xA1\xA2"+ $expect $ equal (enc (fromChar8 "test\xA1\xA2")) "test\xEFA1\xEFA2"+ $expect $ equal (enc (fromChar8 "\xC2\xA1\xC2\xA2/test\xA1\xA2")) "\xA1\xA2/test\xEFA1\xEFA2" $expect $ equal (enc (fromText posix_ghc702 "test\xA1\xA2")) "test\xA1\xA2" test_EncodeString_Win32 :: Suite@@ -399,6 +400,8 @@ test_DecodeString = suite "decodeString" [ test_DecodeString_Posix , test_DecodeString_Posix_Ghc702+ , test_DecodeString_Darwin+ , test_DecodeString_Darwin_Ghc702 , test_DecodeString_Win32 ] @@ -417,7 +420,25 @@ $expect $ equal (dec r "test") (fromText r "test") $expect $ equal (dec r "test\xC2\xA1\xC2\xA2") (fromText r "test\xC2\xA1\xC2\xA2") $expect $ equal (dec r "test\xA1\xA2") (fromText r "test\xA1\xA2")+ $expect $ equal (dec r "test\xEFA1\xEFA2") (fromChar8 "test\xA1\xA2")+ $expect $ equal+ (toText r (dec r "test\xEFA1\xEFA2"))+ (Left "test\xA1\xA2") +test_DecodeString_Darwin :: Suite+test_DecodeString_Darwin = assertions "darwin" $ do+ let r = darwin+ let dec = decodeString+ $expect $ equal (dec r "test\xC2\xA1\xC2\xA2") (fromText r "test\xA1\xA2")++test_DecodeString_Darwin_Ghc702 :: Suite+test_DecodeString_Darwin_Ghc702 = assertions "darwin_ghc702" $ do+ let r = darwin_ghc702+ let dec = decodeString+ $expect $ equal (dec r "test\xC2\xA1\xC2\xA2") (fromText r "test\xC2\xA1\xC2\xA2")+ $expect $ equal (dec r "test\xA1\xA2") (fromText r "test\xA1\xA2")+ $expect $ equal (dec r "test\xEFA1\xEFA2") (fromChar8 "test\xA1\xA2")+ test_DecodeString_Win32 :: Suite test_DecodeString_Win32 = assertions "windows" $ do let r = windows@@ -432,6 +453,14 @@ (fromChar8 "test\xA1\xA2") (fromText posix "test\xA1\xA2") +test_ShowRules :: Suite+test_ShowRules = assertions "show-rules" $ do+ $expect $ equal (showsPrec 11 darwin "") "(Rules \"Darwin\")"+ $expect $ equal (showsPrec 11 darwin_ghc702 "") "(Rules \"Darwin (GHC 7.2)\")"+ $expect $ equal (showsPrec 11 posix "") "(Rules \"POSIX\")"+ $expect $ equal (showsPrec 11 posix_ghc702 "") "(Rules \"POSIX (GHC 7.2)\")"+ $expect $ equal (showsPrec 11 windows "") "(Rules \"Windows\")"+ posixPaths :: Gen FilePath posixPaths = sized $ fmap merge . genComponents where merge = fromChar8 . intercalate "/"@@ -458,7 +487,7 @@ , "LPT7", "LPT8", "LPT9", "NUL", "PRN" ] validChar c = not (elem c reserved)- validComponent c = not (elem c reservedNames)+ validComponent c = not (elem (map toUpper c) reservedNames) component = do size <- choose (0, 10) vectorOf size $ arbitrary `suchThat` validChar
tests/system-filepath-tests.cabal view
@@ -20,5 +20,6 @@ , bytestring , chell >= 0.2 && < 0.3 , chell-quickcheck >= 0.1 && < 0.2+ , deepseq >= 1.1 && < 1.3 , QuickCheck , text