snap-server-0.2.10: test/suite/Data/HashMap/Concurrent/Tests.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PackageImports #-}
module Data.HashMap.Concurrent.Tests
( tests ) where
import Data.ByteString.Char8 (ByteString)
import Data.List
import Data.Word
import Test.Framework
import Test.Framework.Providers.QuickCheck2
import Test.QuickCheck
import Test.QuickCheck.Monadic
import qualified Data.HashMap.Concurrent as H
import Snap.Test.Common ()
tests :: [Test]
tests = [ testFromTo
, testLookup
, testDeletes
, testUpdate
]
-- make sure we generate two strings which hash to the same bucket.
bogoHash :: ByteString -> Word
bogoHash "qqq" = 12345
bogoHash "zzz" = 12345
bogoHash x = H.hashBS x
testFromTo :: Test
testFromTo = testProperty "HashMap/fromList/toList" $
monadicIO $ forAllM arbitrary prop
where
prop :: [(Int,Int)] -> PropertyM IO ()
prop l = do
ht <- run $ H.fromList H.hashInt l
l' <- run $ H.toList ht
let s1 = sort l
let s2 = sort l'
assert $ s1 == s2
testDeletes :: Test
testDeletes = testProperty "HashMap/deletes" $
monadicIO $ forAllM arbitrary prop
where
prop :: [(ByteString,ByteString)] -> PropertyM IO ()
prop l' = do
pre (not $ null l')
let l = [("qqq","QQQ"),("zzz","ZZZ")] ++ l'
let h = head l'
ht <- run $ H.fromList bogoHash l
v1 <- run $ H.lookup "qqq" ht
v2 <- run $ H.lookup "zzz" ht
run $ H.delete "qqq" ht
v3 <- run $ H.lookup "qqq" ht
v4 <- run $ H.lookup "zzz" ht
run $ H.delete (fst h) ht
run $ H.delete (fst h) ht
v5 <- run $ H.lookup (fst h) ht
assert $ v1 == Just "QQQ"
assert $ v2 == Just "ZZZ"
assert $ v3 == Nothing
assert $ v4 == Just "ZZZ"
assert $ v5 == Nothing
testLookup :: Test
testLookup = testProperty "HashMap/lookup" $
monadicIO $ forAllM arbitrary prop
where
prop :: [(ByteString,ByteString)] -> PropertyM IO ()
prop l' = do
pre (not $ null l')
let h = head l'
let l = filter ((/= (fst h)) . fst) $ tail l'
ht <- run $ H.fromList H.hashBS (h:l)
v1 <- run $ H.lookup (fst h) ht
run $ H.delete (fst h) ht
v2 <- run $ H.lookup (fst h) ht
assert $ v1 == (Just $ snd h)
assert $ v2 == Nothing
testUpdate :: Test
testUpdate = testProperty "HashMap/update" $
monadicIO $ forAllM arbitrary prop
where
prop :: [(ByteString,ByteString)] -> PropertyM IO ()
prop l' = do
pre (not $ null l')
let h = head l'
let l = filter ((/= (fst h)) . fst) $ tail l'
ht <- run $ H.fromList H.hashBS (h:l)
e1 <- run $ H.update (fst h) "qqq" ht
v1 <- run $ H.lookup (fst h) ht
run $ H.delete (fst h) ht
v2 <- run $ H.lookup (fst h) ht
e2 <- run $ H.update (fst h) "zzz" ht
v3 <- run $ H.lookup (fst h) ht
assert e1
assert $ v1 == Just "qqq"
assert $ v2 == Nothing
assert $ not e2
assert $ v3 == Just "zzz"