packages feed

entwine-0.0.3: test/Test/Entwine/Parallel.hs

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module Test.Entwine.Parallel where

import           Control.Concurrent.MVar
import           Control.Monad.Catch
import           Control.Monad.IO.Class
import           Control.Monad.Trans.Either

import           Test.Disorder (testIO)

import           Entwine.P

import           System.IO
import           System.IO.Error

import           Test.QuickCheck

import           Entwine.Data
import           Entwine.Parallel

data Fail =
  IFailed

prop_consume = forAll (choose (1, 10 :: Int)) $ \n -> testIO $ do
  r <- newMVar ([] :: [Int])

  let pro = \q -> forM_ [1..n] (writeQueue q)

      work :: Int -> EitherT Fail IO ()
      work i =
        liftIO $ modifyMVar_ r (\l -> pure $ i : l)

  _ <- runEitherT $ consume_ pro 1 work

  g <- readMVar r

  pure $ length g === n

prop_worker_fail = forAll (choose (1, 1000 :: Int)) $ \n -> testIO $ do
  let pro = \q -> forM_ [1..n] (writeQueue q)
      work = const $ left IFailed

  r <- runEitherT $ consume_ pro 1 work
  z <- pure $ case r of
    (Left (WorkerError IFailed)) ->
      True
    _ ->
      False
  pure $ z === True

prop_worker_blow_up_worker = forAll (choose (1, 1000 :: Int)) $ \n -> testIO $ do
  let pro = \q -> forM_ [1..n] (writeQueue q)
      work = const . throwM . userError $ "what is this?"

  r <- runEitherT $ consume_ pro 1 work
  z <- pure $ case r of
    (Left (BlowUpError _)) ->
      True
    _ ->
      False
  pure $ z === True

prop_worker_blow_up_producer = testIO $ do
  let pro = const . throwM . userError $ "producer"
      work = const $ pure ()

  r <- runEitherT $ consume_ pro 1 work
  z <- pure $ case r of
    (Left (BlowUpError _)) ->
      True
    _ ->
      False
  pure $ z === True

prop_empty_producer = testIO $ do
  let pro = const $ pure ()
      work = const $ pure ()

  r <- runEitherT $ consume_ pro 1 work
  pure $ isRight r === True

prop_empty_producer_consume = testIO $ do
  let pro = const . pure . Right $ (1 :: Int)
      work = const . pure . Right $ (1 :: Int)

  r <- runEitherT $ consume pro 1 work
  pure $ isRight r === True

return []
tests :: IO Bool
tests = $forAllProperties $ quickCheckWithResult (stdArgs { maxSuccess = 10 })