1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
module Tests.Conc
( concTests
) where
import Control.Concurrent
import Control.Monad
import Data.Bit.ThreadSafe
import Data.Bits
import qualified Data.Vector.Generic as V
import qualified Data.Vector.Generic.Mutable as M
import qualified Data.Vector.Unboxed as U
import Test.Tasty
import Test.Tasty.QuickCheck
concTests :: TestTree
concTests = testGroup "Concurrency"
[ testProperty "invertInPlace" case_conc_invert
, testProperty "reverseInPlace" case_conc_reverse
, testProperty "zipInPlace" case_conc_zip
]
runConcurrently :: IO () -> IO () -> IO ()
runConcurrently action1 action2 = do
m <- newEmptyMVar
_ <- forkIO $ do
action1
putMVar m ()
action2
takeMVar m
case_conc_invert :: Property
case_conc_invert = ioProperty $ replicateM_ 1000 $ do
let len = 64
len' = 37
vec <- M.replicate len (Bit True)
ref <- V.freeze vec :: IO (U.Vector Bit)
runConcurrently
(replicateM_ 1000 $ invertInPlace (M.take len' vec))
(replicateM_ 1000 $ invertInPlace (M.drop len' vec))
wec <- V.unsafeFreeze vec
pure $ ref === wec
case_conc_reverse :: Property
case_conc_reverse = ioProperty $ replicateM_ 1000 $ do
let len = 128
len' = 66
vec <- M.new len
forM_ [0 .. len - 1] $ \i -> M.write vec i (Bit $ odd i)
ref <- V.freeze vec :: IO (U.Vector Bit)
runConcurrently
(replicateM_ 1000 $ reverseInPlace (M.take len' vec))
(replicateM_ 1000 $ reverseInPlace (M.drop len' vec))
wec <- V.unsafeFreeze vec
pure $ ref === wec
case_conc_zip :: Property
case_conc_zip = ioProperty $ replicateM_ 1000 $ do
let len = 128
len' = 37
vec <- M.replicate len (Bit True)
let ref = V.replicate len (Bit False)
runConcurrently
(replicateM_ 1001 $ zipInPlace (const complement) ref (M.take len' vec))
(replicateM_ 1001 $ zipInPlace (const complement) ref (M.drop len' vec))
wec <- V.unsafeFreeze vec
pure $ ref === wec
|