{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE DataKinds, TypeFamilies #-} {-# LANGUAGE CPP #-} -- | Tests for the Data.LVar.PureMap and Data.LVar.SLMap modules. module PureMapTests(tests, runTests) where import Data.LVar.PureSet as IS import Data.LVar.PureMap as IM #include "CommonMapTests.hs" -------------------------------------------------------------------------------- tests :: Test tests = testGroup "" [tests_here, tests_common ] tests_here :: Test tests_here = $(testGroupGenerator) runTests :: IO () runTests = defaultMainSeqTests [tests] -------------------------------------------------------------------------------- -- [2013.08.05] RRN: Observing nondeterministic blocked-indefinitely -- exception here. case_i7b :: Assertion case_i7b = do allowSomeExceptions ["Multiple puts"] $ assertEqual "racing insert and modify" (M.fromList [(1,S.fromList [3.33]), (2,S.fromList [0.11,4.44])]) =<< i7b return () -- | A quasi-deterministic example. i7b :: IO (M.Map Int (S.Set Float)) -- A manual nested freeze instead of DeepFrz: i7b = runParIO $ do mp <- IM.newEmptyMap s1 <- IS.newEmptySet s2 <- IS.newEmptySet IS.insert 0.11 s2 f1 <- IV.spawn_ $ do IM.insert 1 s1 mp IM.insert 2 s2 mp f2 <- IV.spawn_ $ do s <- IM.getKey 1 mp IS.insert 3.33 s -- RACE: this modify is racing with the insert of s2: IM.modify mp 2 IS.newEmptySet (IS.insert 4.44) IV.get f1; IV.get f2 mp2 <- IM.freezeMap mp traverse IS.freezeSet mp2 -- | This example is valid because two modifies may race. v7c :: IO (M.Map Int (S.Set Float)) -- Do we need a "deep freeze" that freezes nested structures? v7c = runParIO $ do mp <- IM.newEmptyMap s1 <- IS.newEmptySet f1 <- IV.spawn_ $ IM.insert 1 s1 mp f2 <- IV.spawn_ $ do s <- IM.getKey 1 mp IS.insert 3.33 s IM.modify mp 2 IS.newEmptySet (IS.insert 4.44) f3 <- IV.spawn_ $ IM.modify mp 3 IS.newEmptySet (IS.insert 5.55) f4 <- IV.spawn_ $ IM.modify mp 3 IS.newEmptySet (IS.insert 6.6) -- No easy way to wait on the total size of all contained sets... -- -- Need a barrier here.. should have a monad-transformer that provides cilk "sync" -- Global quiesce is convenient too.. IV.get f1; IV.get f2; IV.get f3; IV.get f4 mp2 <- IM.freezeMap mp traverse IS.freezeSet mp2 case_v7c :: Assertion case_v7c = assertEqual "imap test - racing modifies" (M.fromList [(1,S.fromList [3.33]), (2,S.fromList [4.44]), (3,S.fromList [5.55,6.6])]) =<< v7c ------------------------------------------------------------------------------------------ -- Show instances ------------------------------------------------------------------------------------------ case_show03 :: Assertion case_show03 = assertEqual "show for PureMap" "{IMap: (\"key1\",33), (\"key2\",44)}" show03 show03 :: String show03 = show$ runParThenFreeze $ do mp <- IM.newEmptyMap IM.insert "key1" (33::Int) mp IM.insert "key2" (44::Int) mp return mp