NMDanny

RWH Chapter 15 ex1

Apr 5th, 2016
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module WriterIOTests where
  2.  
  3. import System.IO (IOMode(..))
  4. import WriterIO
  5. import qualified Data.Map as Map
  6. import MonadHandle
  7. import Test.QuickCheck
  8.  
  9.  
  10. type ActiveFileMap = Map.Map FilePath IOMode
  11. type Snapshot = (Event,ActiveFileMap)
  12.  
  13. -- | Zip each event with a map of active files(to their mode) after that event's execution
  14. buildSnapshots :: [Event] -> [Snapshot]
  15. buildSnapshots events =
  16.   let
  17.     foldF :: [Snapshot] -> Event -> [Snapshot]
  18.     foldF snapshots@((prevEvent,prevActiveFiles):_) curEvent =
  19.       let newActiveFiles = processEvent curEvent prevActiveFiles
  20.       in  (curEvent,newActiveFiles) : snapshots
  21.     foldF [] curEvent = [(curEvent,processEvent curEvent Map.empty)]
  22.     -- For a given event and the active files map, update the active files map if
  23.     -- the event opens a new file or closes a previous one.
  24.     processEvent :: Event -> ActiveFileMap -> ActiveFileMap
  25.     processEvent (Open fp mode) curMap =  Map.insert fp mode curMap
  26.     processEvent (Close fp) curMap = Map.delete fp curMap
  27.     processEvent _ curMap = curMap
  28.   in
  29.     reverse $ foldl foldF [] events -- we must reverse the snapshots, because they were built in a reverse order.
  30.  
  31. -- | given a list of snapshots, validate them according to the rules:
  32. --     when putting to a file, that file must be open and writable
  33. --     when reading a file, that file must be open and readable
  34. validateSnapshots :: [Snapshot] -> Bool
  35. validateSnapshots = all isValid where
  36.   isWriteable mode = mode == WriteMode || mode == ReadWriteMode || mode == AppendMode
  37.   isReadable mode = mode == ReadMode || mode == ReadWriteMode
  38.   isValid :: Snapshot -> Bool
  39.   isValid (Put fp _,activeFiles) = maybe False isWriteable (Map.lookup fp activeFiles)
  40.   isValid (GetContents fp, activeFiles) = maybe False isReadable (Map.lookup fp activeFiles)
  41.   isValid _ = True
  42.  
  43. -- | given a WriterIO, validate it.
  44. validateIO :: WriterIO a -> Bool
  45. validateIO = validateSnapshots . buildSnapshots . snd . runWriterIO
  46.  
  47.  
  48. validIOSession1 :: MonadHandle h m => FilePath -> m ()
  49. validIOSession1 path =
  50.   do
  51.     file <- openFile path WriteMode
  52.     hPutStr file "should be ok"
  53.     hPutStr file "still be ok"
  54.     hClose file
  55.  
  56. validIOSession2 :: MonadHandle h m => FilePath -> m ()
  57. validIOSession2 path =
  58.   do
  59.     file <- openFile path WriteMode
  60.     hPutStr file "inserting as expected"
  61.     hClose file
  62.     sameFile <- openFile path WriteMode
  63.     hPutStr sameFile "should still work"
  64.     hClose file
  65.     sameFileInReadMode <- openFile path ReadMode
  66.     _ <- hGetContents sameFileInReadMode
  67.     hClose sameFileInReadMode
  68.  
  69. invalidIOSession1 :: MonadHandle h m => FilePath -> m ()
  70. invalidIOSession1 path =
  71.   do
  72.     file <- openFile path ReadMode
  73.     hPutStr file "inserting to a file without write permissions! better call the police"
  74.     hClose file
  75.  
  76. invalidIOSession2 :: MonadHandle h m => FilePath -> m ()
  77. invalidIOSession2 path =
  78.   do
  79.     file <- openFile path WriteMode
  80.     hPutStr file "should be ok"
  81.     hClose file
  82.     hPutStr file "writing to a closed file! thats a paddlin'"
  83.  
  84.  
  85. doTests :: IO ()
  86. doTests = do
  87.   quickCheck (validateIO . validIOSession1)
  88.   quickCheck (validateIO . validIOSession2)
  89.   quickCheck (not . validateIO . invalidIOSession1)
  90.   quickCheck (not . validateIO . invalidIOSession2)
Add Comment
Please, Sign In to add comment