Skip to content

Commit 02cd0ef

Browse files
Updating the documentation and semantics testing for MustExist.
1 parent a3aec0e commit 02cd0ef

File tree

5 files changed

+53
-39
lines changed

5 files changed

+53
-39
lines changed

fs-api/src-win32/System/FS/IO/Windows.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ open filename openMode = do
6060
ReadWriteMode ex -> (gENERIC_READ .|. gENERIC_WRITE, createNew ex)
6161
createNew AllowExisting = oPEN_ALWAYS
6262
createNew MustBeNew = cREATE_NEW
63-
createNew MustExist = oPEN_ALWAYS
63+
createNew MustExist = oPEN_EXISTING
6464

6565
write :: FHandle -> Ptr Word8 -> Int64 -> IO Word32
6666
write fh data' bytes = withOpenHandle "write" fh $ \h ->

fs-api/src/System/FS/API/Types.hs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ import System.FS.Condense
7070
-------------------------------------------------------------------------------}
7171

7272
-- | How to 'System.FS.API.hOpen' a new file.
73+
--
74+
-- Each mode of file operation has an associated 'AllowExisting' parameter which
75+
-- specifies the semantics of how to handle the existence or non-existence of
76+
-- the file.
77+
--
78+
-- /Notably however/, opening a file in read mode with the @ReadMode@ value
79+
-- /implicitly/ has the associated 'AllowExisting' value of 'MustExist'.
80+
-- This is beacause opening a non-existing file in 'ReadMode' provides access to
81+
-- exactly 0 bytes of data and is hence a useless operation.
7382
data OpenMode
7483
= ReadMode
7584
| WriteMode AllowExisting
@@ -88,11 +97,14 @@ data AllowExisting
8897
| MustExist
8998
-- ^ The file must already exist. If it does not, an error
9099
-- ('FsResourceDoesNotExist') is thrown.
100+
--
101+
-- /Note:/ If opening a file in 'ReadMode', then the file must exist
102+
-- or an exception is thrown.
91103
deriving (Eq, Show)
92104

93105
allowExisting :: OpenMode -> AllowExisting
94106
allowExisting openMode = case openMode of
95-
ReadMode -> AllowExisting
107+
ReadMode -> MustExist
96108
WriteMode ex -> ex
97109
AppendMode ex -> ex
98110
ReadWriteMode ex -> ex

fs-sim/src/System/FS/Sim/FsTree.hs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,18 +231,23 @@ getDir fp =
231231
Specific file system functions
232232
-------------------------------------------------------------------------------}
233233

234-
-- | Open a file based on an 'AllowExisting'.
234+
-- | Open a file: create it if necessary or throw an error if either:
235+
-- 1. It existed already while we were supposed to create it from scratch
236+
-- (when passed 'MustBeNew').
237+
-- 2. It did not already exists when we expected to (when passed 'MustExist').
235238
openFile :: Monoid a
236239
=> FsPath -> AllowExisting -> FsTree a -> Either FsTreeError (FsTree a)
237240
openFile fp ex = alterFile fp Left caseDoesNotExist caseAlreadyExist
238241
where
239242
caseAlreadyExist a = case ex of
243+
AllowExisting -> Right a
240244
MustBeNew -> Left (FsExists fp)
241-
_ -> Right a
245+
MustExist -> Right a
242246

243247
caseDoesNotExist = case ex of
248+
AllowExisting -> Right mempty
249+
MustBeNew -> Right mempty
244250
MustExist -> Left (FsMissing fp (pathLast fp :| []))
245-
_ -> Right mempty
246251

247252
-- | Replace the contents of the specified file (which must exist)
248253
replace :: FsPath -> a -> FsTree a -> Either FsTreeError (FsTree a)

fs-sim/src/System/FS/Sim/MockFS.hs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ module System.FS.Sim.MockFS (
6565
, hPutBufSomeAt
6666
) where
6767

68-
import Control.Monad (forM, forM_, unless, void, when)
68+
import Control.Monad (forM, forM_, unless, when)
6969
import Control.Monad.Except (MonadError, throwError)
7070
import Control.Monad.Primitive (PrimMonad (..))
7171
import Control.Monad.State.Strict (MonadState, get, gets, put)
@@ -479,11 +479,7 @@ hOpen fp openMode = do
479479
, fsLimitation = True
480480
}
481481
modifyMockFS $ \fs -> do
482-
let assumedExistance (WriteMode MustExist) = True
483-
assumedExistance (AppendMode MustExist) = True
484-
assumedExistance (ReadWriteMode MustExist) = True
485-
assumedExistance _ = False
486-
alreadyHasWriter =
482+
let alreadyHasWriter =
487483
any (\hs -> openFilePath hs == fp && isWriteHandle hs) $
488484
openHandles fs
489485
when (openMode /= ReadMode && alreadyHasWriter) $
@@ -495,8 +491,6 @@ hOpen fp openMode = do
495491
, fsErrorStack = prettyCallStack
496492
, fsLimitation = True
497493
}
498-
when (openMode == ReadMode || assumedExistance openMode) $ void $
499-
checkFsTree $ FS.getFile fp (mockFiles fs)
500494
files' <- checkFsTree $ FS.openFile fp ex (mockFiles fs)
501495
return $ newHandle (fs { mockFiles = files' })
502496
(OpenHandle fp (filePtr openMode))

fs-sim/test/Test/System/FS/StateMachine.hs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,92 +1004,94 @@ data Tag =
10041004
-- > Get ..
10051005
| TagPutTruncateGet
10061006

1007-
-- Close a handle 2 times
1007+
-- | Close a handle 2 times
10081008
--
10091009
-- > h <- Open ..
10101010
-- > close h
10111011
-- > close h
10121012
| TagClosedTwice
10131013

1014-
-- Open an existing file with ReadMode and then with WriteMode
1014+
-- | Open an existing file with ReadMode and then with WriteMode
10151015
--
10161016
-- > open fp ReadMode
10171017
-- > open fp Write
10181018
| TagOpenReadThenWrite
10191019

1020-
-- Open 2 Readers of a file.
1020+
-- | Open 2 Readers of a file.
10211021
--
10221022
-- > open fp ReadMode
10231023
-- > open fp ReadMode
10241024
| TagOpenReadThenRead
10251025

1026-
-- ListDir on a non empty dirextory.
1026+
-- | ListDir on a non empty dirextory.
10271027
--
10281028
-- > CreateDirIfMissing True a/b
10291029
-- > ListDirectory a
10301030
| TagCreateDirWithParentsThenListDirNotNull
10311031

1032-
-- Read from an AppendMode file
1032+
-- | Read from an AppendMode file
10331033
--
10341034
-- > h <- Open fp AppendMode
10351035
-- > Read h ..
10361036
| TagReadInvalid
10371037

1038-
-- Write to a read only file
1038+
-- | Write to a read only file
10391039
--
10401040
-- > h <- Open fp ReadMode
10411041
-- > Put h ..
10421042
| TagWriteInvalid
10431043

1044-
-- Put Seek and Get
1044+
-- | Put Seek and Get
10451045
--
10461046
-- > Put ..
10471047
-- > Seek ..
10481048
-- > Get ..
10491049
| TagPutSeekGet
10501050

1051-
-- Put Seek (negative) and Get
1051+
-- | Put Seek (negative) and Get
10521052
--
10531053
-- > Put ..
10541054
-- > Seek .. (negative)
10551055
-- > Get ..
10561056
| TagPutSeekNegGet
10571057

1058-
1059-
-- Open with MustBeNew (O_EXCL flag), but the file already existed.
1058+
-- | Open with MustBeNew (O_EXCL flag), but the file already existed.
10601059
--
10611060
-- > h <- Open fp (AppendMode _)
10621061
-- > Close h
10631062
-- > Open fp (AppendMode MustBeNew)
10641063
| TagExclusiveFail
10651064

1066-
1067-
-- Open with MustExist, but the file does not exist.
1065+
-- | Open with MustExist, but the file does not exist.
10681066
--
10691067
-- > DoesFileExist fp
10701068
-- > h <- Open fp (AppendMode _)
10711069
| TagAssumeExists
10721070

1071+
-- | Open in ReadMode, but the file does not exist.
1072+
--
1073+
-- > DoesFileExist fp
1074+
-- > h <- Open fp ReadMode
1075+
| TagReadMustExist
10731076

1074-
-- Reading returns an empty bytestring when EOF
1077+
-- | Reading returns an empty bytestring when EOF
10751078
--
10761079
-- > h <- open fp ReadMode
10771080
-- > Get h 1 == ""
10781081
| TagReadEOF
10791082

1080-
1081-
-- GetAt
1083+
-- | GetAt
10821084
--
10831085
-- > GetAt ...
10841086
| TagPread
10851087

1086-
-- Roundtrip for I/O with user-supplied buffers
1088+
-- | Roundtrip for I/O with user-supplied buffers
10871089
--
10881090
-- > PutBuf h bs c
10891091
-- > GetBuf h c (==bs)
10901092
| TagPutGetBuf
10911093

1092-
-- Roundtrip for I/O with user-supplied buffers
1094+
-- | Roundtrip for I/O with user-supplied buffers
10931095
--
10941096
-- > PutBufAt h bs c o
10951097
-- > GetBufAt h c o (==bs)
@@ -1144,7 +1146,8 @@ tag = C.classify [
11441146
, tagPutSeekGet Set.empty Set.empty
11451147
, tagPutSeekNegGet Set.empty Set.empty
11461148
, tagExclusiveFail
1147-
-- , tagAssumeExistsFail -- Set.empty
1149+
, tagAssumeExistsFail
1150+
, tagReadMustExistFail
11481151
, tagReadEOF
11491152
, tagPread
11501153
, tagPutGetBuf Set.empty
@@ -1492,21 +1495,21 @@ tag = C.classify [
14921495

14931496
tagAssumeExistsFail :: EventPred
14941497
tagAssumeExistsFail = C.predicate $ \ev ->
1495-
{-
1496-
tagClosedTwice closed = successful $ \ev _suc ->
1497-
case eventMockCmd ev of
1498-
Close (Handle h _) | Set.member h closed -> Left TagClosedTwice
1499-
Close (Handle h _) -> Right $ tagClosedTwice $ Set.insert h closed
1500-
_otherwise -> Right $ tagClosedTwice closed
1501-
(DoesFileExist _, Bool False) -> Left TagDoesFileExistKO
1502-
-}
15031498
case (eventMockCmd ev, eventMockResp ev) of
15041499
(Open _ mode, Resp (Left fsError))
15051500
| MustExist <- allowExisting mode
15061501
, fsErrorType fsError == FsResourceDoesNotExist ->
15071502
Left TagAssumeExists
15081503
_otherwise -> Right tagAssumeExistsFail
15091504

1505+
tagReadMustExistFail :: EventPred
1506+
tagReadMustExistFail = C.predicate $ \ev ->
1507+
case (eventMockCmd ev, eventMockResp ev) of
1508+
(Open _ ReadMode, Resp (Left fsError))
1509+
| fsErrorType fsError == FsResourceDoesNotExist ->
1510+
Left TagReadMustExist
1511+
_otherwise -> Right tagReadMustExistFail
1512+
15101513
tagReadEOF :: EventPred
15111514
tagReadEOF = successful $ \ev suc ->
15121515
case (eventMockCmd ev, suc) of

0 commit comments

Comments
 (0)