packages feed

happstack-state-0.1: tests/HAppS/State/Tests/SaverProperties.hs

module HAppS.State.Tests.SaverProperties
    ( checkSaverProperties
    , saverProperties
    ) where

import HAppS.State.Saver
import HAppS.State.Saver.Impl.Memory
import HAppS.State.Tests.Helpers
import HAppS.Util.Testing (qctest, qcrun)

import System.Directory
import System.Random
import System.FilePath
import System.IO.Unsafe
import Control.Monad
import Control.Exception
import Control.Concurrent
import Data.List

import Test.QuickCheck
import Test.QuickCheck.Batch
import Test.HUnit (Test(TestCase),(~:), assertFailure)

--------------------------------------------------------------
-- Tests
--------------------------------------------------------------

-- read (write values) == values
prop_getSetId withSaver key cutoff values
    = not (null key) ==>
      cutoff > 0 ==>
      ioProperty $ withSaver $ \saver ->
      do writer <- createWriter saver key cutoff
         forM_ values $ \value -> writerAdd writer (value::Int) $ return ()
         writerClose writer

         reader <- createReader saver key cutoff
         out <- readerGetUncut reader
         return $ values == out

prop_seqReadWrite withSaver (NonEmpty key) (Abs cutoff) valss
    = ioProperty $ withSaver $ \saver ->
      do writer <- createWriter saver key cutoff
         forM_ valss $ \vals -> do forM_ vals $ \val -> writerAdd writer (val::Int) $ return ()
                                   writerCut writer
         writerClose writer

         reader <- createReader saver key cutoff
         (out,newCut) <- readerGet reader
         return $ out == concat valss && newCut == length valss + 1

prop_cutDrop withSaver (NonEmpty key) (Abs cutoff) a b
    = ioProperty $ withSaver $ \saver ->
      do writer <- createWriter saver key cutoff
         forM_ a $ \val -> writerAdd writer (val::Int) $ return ()
         newCut <- writerCut writer
         forM_ b $ \val -> writerAdd writer (val::Int) $ return ()
         writerClose writer

         reader <- createReader saver key newCut
         (out,_) <- readerGet reader
         return $ b `isSuffixOf` out

prop_atomic withSaver (NonEmpty key) (Abs cutoff) value
    = ioProperty $ withSaver $ \saver ->
      do writer <- createWriter saver key cutoff
         writerAtomicReplace writer (value::Int)
         writerClose writer

         reader <- createReader saver key cutoff
         out <- readerGetUncut reader
         readerClose reader
         return $ out == [value]

checkSaverProperties :: IO ()
checkSaverProperties
    = forEachSaver_ $ \name withSaver ->
      tryTests (name ++ " saver") options [run (prop_getSetId withSaver)
                                          ,run (prop_seqReadWrite withSaver)
                                          ,run (prop_cutDrop withSaver)
                                          ,run (prop_atomic withSaver)]
  where options = defOpt{length_of_tests=5}

saverProperties :: Test
saverProperties 
    = "saverProperties" ~:
       ((forEachSaver $ \name withSaver ->
             name ~:
              [ "prop_getSetId"     ~: qcrun (prop_getSetId withSaver) options
              , "prop_seqReadWrite" ~: qcrun (prop_seqReadWrite withSaver) options
              , "prop_cutDrop"      ~: qcrun (prop_cutDrop withSaver) options
              , "prop_atomic"       ~: qcrun (prop_atomic withSaver) options
              ]))
  where options = defOpt{length_of_tests=5}