packages feed

hunit-dejafu (empty) → 0.2.0.0

raw patch · 4 files changed

+252/−0 lines, 4 filesdep +HUnitdep +basedep +dejafusetup-changed

Dependencies added: HUnit, base, dejafu

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015, Michael Walker <mike@barrucadu.co.uk>++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Test/HUnit/DejaFu.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE RankNTypes #-}++-- | This module allows using Deja Fu predicates with HUnit to test+-- the behaviour of concurrent systems.+module Test.HUnit.DejaFu+  ( -- * Testing+    testAuto+  , testDejafu+  , testDejafus+  , testAutoIO+  , testDejafuIO+  , testDejafusIO++  -- * Testing under Alternative Memory Models+  , MemType(..)+  , testAuto'+  , testAutoIO'+  , testDejafu'+  , testDejafus'+  , testDejafuIO'+  , testDejafusIO'+  ) where++import Test.DejaFu+import Test.DejaFu.Deterministic (ConcST, ConcIO, showFail, showTrace)+import Test.DejaFu.SCT (sctBound, sctBoundIO)+import Test.HUnit (Test(..), assertString)++--------------------------------------------------------------------------------+-- Automated testing++-- | Automatically test a computation. In particular, look for+-- deadlocks, uncaught exceptions, and multiple return values.+-- +-- This uses the 'Conc' monad for testing, which is an instance of+-- 'MonadConc'. If you need to test something which also uses+-- 'MonadIO', use 'testAutoIO'.+testAuto :: (Eq a, Show a)+  => (forall t. ConcST t a)+  -- ^ The computation to test+  -> Test+testAuto = testAuto' defaultMemType++-- | Variant of 'testAuto' which tests a computation under a given+-- memory model.+testAuto' :: (Eq a, Show a)+  => MemType+  -- ^ The memory model to use for non-synchronised @CRef@ operations.+  -> (forall t. ConcST t a)+  -- ^ The computation to test+  -> Test+testAuto' memtype conc = testDejafus' memtype defaultBounds conc autocheckCases++-- | Variant of 'testAuto' for computations which do 'IO'.+testAutoIO :: (Eq a, Show a) => ConcIO a -> Test+testAutoIO = testAutoIO' defaultMemType++-- | Variant of 'testAuto'' for computations which do 'IO'.+testAutoIO' :: (Eq a, Show a) => MemType -> ConcIO a -> Test+testAutoIO' memtype concio = testDejafusIO' memtype defaultBounds concio autocheckCases++-- | Predicates for the various autocheck functions.+autocheckCases :: Eq a => [(String, Predicate a)]+autocheckCases =+  [("Never Deadlocks", representative deadlocksNever)+  , ("No Exceptions", representative exceptionsNever)+  , ("Consistent Result", alwaysSame)+  ]++--------------------------------------------------------------------------------+-- Manual testing++-- | Check that a predicate holds.+testDejafu :: Show a+  => (forall t. ConcST t a)+  -- ^ The computation to test+  -> String+  -- ^ The name of the test.+  -> Predicate a+  -- ^ The predicate to check+  -> Test+testDejafu = testDejafu' defaultMemType defaultBounds++-- | Variant of 'testDejafu' which takes a memory model and+-- pre-emption bound.+testDejafu' :: Show a+  => MemType+  -- ^ The memory model to use for non-synchronised @CRef@ operations.+  -> Bounds+  -- ^ The schedule bound.+  -> (forall t. ConcST t a)+  -- ^ The computation to test+  -> String+  -- ^ The name of the test.+  -> Predicate a+  -- ^ The predicate to check+  -> Test+testDejafu' memtype cb conc name p = testDejafus' memtype cb conc [(name, p)]++-- | Variant of 'testDejafu' which takes a collection of predicates to+-- test. This will share work between the predicates, rather than+-- running the concurrent computation many times for each predicate.+testDejafus :: Show a+  => (forall t. ConcST t a)+  -- ^ The computation to test+  -> [(String, Predicate a)]+  -- ^ The list of predicates (with names) to check+  -> Test+testDejafus = testDejafus' defaultMemType defaultBounds++-- | Variant of 'testDejafus' which takes a memory model and pre-emption+-- bound.+testDejafus' :: Show a+  => MemType+  -- ^ The memory model to use for non-synchronised @CRef@ operations.+  -> Bounds+  -- ^ The schedule bounds+  -> (forall t. ConcST t a)+  -- ^ The computation to test+  -> [(String, Predicate a)]+  -- ^ The list of predicates (with names) to check+  -> Test+testDejafus' = test++-- | Variant of 'testDejafu' for computations which do 'IO'.+testDejafuIO :: Show a => ConcIO a -> String -> Predicate a -> Test+testDejafuIO = testDejafuIO' defaultMemType defaultBounds++-- | Variant of 'testDejafu'' for computations which do 'IO'.+testDejafuIO' :: Show a => MemType -> Bounds -> ConcIO a -> String -> Predicate a -> Test+testDejafuIO' memtype cb concio name p = testDejafusIO' memtype cb concio [(name, p)]++-- | Variant of 'testDejafus' for computations which do 'IO'.+testDejafusIO :: Show a => ConcIO a -> [(String, Predicate a)] -> Test+testDejafusIO = testDejafusIO' defaultMemType defaultBounds++-- | Variant of 'dejafus'' for computations which do 'IO'.+testDejafusIO' :: Show a => MemType -> Bounds -> ConcIO a -> [(String, Predicate a)] -> Test+testDejafusIO' = testio++--------------------------------------------------------------------------------+-- HUnit integration++-- | Produce a HUnit 'Test' from a Deja Fu test.+test :: Show a => MemType -> Bounds -> (forall t. ConcST t a) -> [(String, Predicate a)] -> Test+test memtype cb conc tests = case map toTest tests of+  [t] -> t+  ts  -> TestList ts++  where+    toTest (name, p) = TestLabel name . TestCase $+      assertString . showErr $ p traces++    traces = sctBound memtype cb conc++-- | Produce a HUnit 'Test' from an IO-using Deja Fu test.+testio :: Show a => MemType -> Bounds -> ConcIO a -> [(String, Predicate a)] -> Test+testio memtype cb concio tests = case map toTest tests of+  [t] -> t+  ts  -> TestList ts++  where+    toTest (name, p) = TestLabel name . TestCase $ do+      -- Sharing of traces probably not possible (without something+      -- really unsafe) here, as 'test' doesn't allow side-effects+      -- (eg, constructing an 'MVar' to share the traces after one+      -- test computed them).+      traces <- sctBoundIO memtype cb concio+      assertString . showErr $ p traces++-- | Convert a test result into an error message on failure (empty+-- string on success).+showErr :: Show a => Result a -> String+showErr res+  | _pass res = ""+  | otherwise = "Failed after " ++ show (_casesChecked res) ++ " cases:\n" ++ msg ++ unlines failures ++ rest where++  msg = if null (_failureMsg res) then "" else _failureMsg res ++ "\n"++  failures = map (\(r, t) -> "\t" ++ either showFail show r ++ " " ++ showTrace t) . take 5 $ _failures res++  rest = if moreThan (_failures res) 5 then "\n\t..." else ""++-- | Check if a list has more than some number of elements.+moreThan :: [a] -> Int -> Bool+moreThan [] n = n < 0+moreThan _ 0  = True+moreThan (_:xs) n = moreThan xs (n-1)+
+ hunit-dejafu.cabal view
@@ -0,0 +1,41 @@+-- Initial hunit-dejafu.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                hunit-dejafu+version:             0.2.0.0+synopsis:            Deja Fu support for the HUnit test framework.++description:+  Integration between the <https://hackage.haskell.org/package/dejafu dejafu>+  library for concurrency testing and+  <https://hackage.haskell.org/package/HUnit HUnit>. This lets you+  easily incorporate concurrency testing into your existing test+  suites.+  .+  See the <https://github.com/barrucadu/dejafu README> for more+  details.++homepage:            https://github.com/barrucadu/dejafu+license:             MIT+license-file:        LICENSE+author:              Michael Walker+maintainer:          mike@barrucadu.co.uk+-- copyright:           +category:            Testing+build-type:          Simple+-- extra-source-files:  +cabal-version:       >=1.10++source-repository head+  type:     git+  location: https://github.com/barrucadu/dejafu.git++library+  exposed-modules:     Test.HUnit.DejaFu+  -- other-modules:       +  -- other-extensions:    +  build-depends:       base >=4.5 && <5+                     , dejafu == 0.2.*+                     , HUnit+  -- hs-source-dirs:      +  default-language:    Haskell2010