hspec2 0.3.0 → 0.3.1
raw patch · 3 files changed
+100/−7 lines, 3 filesdep −io-memoize
Dependencies removed: io-memoize
Files
- hspec2.cabal +2/−3
- src/Test/Hspec.hs +14/−4
- src/Test/Hspec/Memoize.hs +84/−0
hspec2.cabal view
@@ -1,5 +1,5 @@ name: hspec2-version: 0.3.0+version: 0.3.1 license: MIT license-file: LICENSE copyright: (c) 2011-2014 Simon Hengel,@@ -50,7 +50,6 @@ , quickcheck-io , hspec-expectations == 0.5.0.* , async >= 2- , io-memoize exposed-modules: Test.Hspec Test.Hspec.Core@@ -60,6 +59,7 @@ Test.Hspec.QuickCheck other-modules: Test.Hspec.Util+ Test.Hspec.Memoize Test.Hspec.Compat Test.Hspec.Core.Type Test.Hspec.Core.QuickCheckUtil@@ -110,7 +110,6 @@ , quickcheck-io , hspec-expectations , async- , io-memoize , hspec-meta >= 1.9.1 , process
src/Test/Hspec.hs view
@@ -27,6 +27,7 @@ , before , beforeWith , beforeAll+, beforeAllWith , after , after_ , around@@ -38,6 +39,7 @@ , hspec ) where +import Control.Applicative import Control.Exception (finally) import Test.Hspec.Core.Type hiding (describe, it)@@ -45,7 +47,7 @@ import Test.Hspec.HUnit () import Test.Hspec.Expectations import qualified Test.Hspec.Core as Core-import System.IO.Memoize+import Test.Hspec.Memoize -- | Combine a list of specs into a larger spec. describe :: String -> SpecWith a -> SpecWith a@@ -98,11 +100,19 @@ -- | Run a custom action before all spec items. beforeAll :: IO a -> SpecWith a -> SpecWith ()-beforeAll action = fromSpecList . return . BuildSpecs . go . runSpecM+beforeAll action = fromSpecList . return . BuildSpecs . go where- go xs = do+ go spec = do action_ <- ioMemo action- return . runSpecM $ before action_ (fromSpecList xs)+ return . runSpecM $ before action_ spec++-- | Run a custom action before all spec items.+beforeAllWith :: (b -> IO a) -> SpecWith a -> SpecWith b+beforeAllWith action = fromSpecList . return . BuildSpecs . go+ where+ go spec = do+ action_ <- (. action) <$> newIOMemoizer+ return . runSpecM $ aroundWith (\e x -> action_ x >>= e) spec -- | Run a custom action after every spec item. after :: ActionWith a -> SpecWith a -> SpecWith a
+ src/Test/Hspec/Memoize.hs view
@@ -0,0 +1,84 @@+-- Taken from:+--+-- * https://github.com/DanBurton/io-memoize/+-- * http://hackage.haskell.org/package/io-memoize+--+-- Copyright (c) 2012, Dan Burton+--+-- All rights reserved.+--+-- Redistribution and use in source and binary forms, with or without+-- modification, are permitted provided that the following conditions are met:+--+-- * Redistributions of source code must retain the above copyright+-- notice, this list of conditions and the following disclaimer.+--+-- * Redistributions in binary form must reproduce the above+-- copyright notice, this list of conditions and the following+-- disclaimer in the documentation and/or other materials provided+-- with the distribution.+--+-- * Neither the name of Dan Burton nor the names of other+-- contributors may be used to endorse or promote products derived+-- from this software without specific prior written permission.+--+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+module Test.Hspec.Memoize (ioMemo, newIOMemoizer) where++import Control.Concurrent.MVar+import Data.IORef++-- | Memoize an IO action.+-- The action will be performed+-- the first time that it its value is demanded;+-- all subsequent invocations+-- will simply recall the value acquired+-- from the first call.+-- If the value is never demanded,+-- then the action will never be performed.+--+-- This is basically a safe version of+-- 'System.IO.Unsafe.unsafeInterleaveIO'.+-- This function is also thread-safe:+-- it is guaranteed that the action passed in+-- will be performed exactly 0 or 1 times+-- by this code. Exceptions will be propagated+-- to the caller.+--+-- Example usage:+--+-- >>> getLine' <- ioMemo getLine+--+-- >>> replicateM 3 getLine'+-- Hello+-- ["Hello", "Hello", "Hello"]+ioMemo :: IO a -> IO (IO a)+ioMemo action = do+ memo <- newIOMemoizer+ return (memo action)++newIOMemoizer :: IO (IO a -> IO a)+newIOMemoizer = do+ b <- newMVar True+ r <- newIORef undefined+ return (ioMemoizer b r)++ioMemoizer :: MVar Bool -> IORef a -> IO a -> IO a+ioMemoizer b r action = do+ modifyMVar_ b $ \isEmpty ->+ if isEmpty+ then do v <- action+ writeIORef r v+ return False+ else return False+ readIORef r