content: {-# LANGUAGE BangPatterns      #-}
  {-# LANGUAGE OverloadedStrings #-}
  
  module System.IO.Streams.Tests.Internal (tests) where
  
  ------------------------------------------------------------------------------
  import           Control.Applicative
  import           Control.Monad                  hiding (mapM)
  import           Control.Monad.IO.Class         (liftIO)
  import           Data.IORef
  import           Prelude                        hiding (mapM, read)
  import           Test.Framework
  import           Test.Framework.Providers.HUnit
  import           Test.HUnit                     hiding (Test)
  ------------------------------------------------------------------------------
  import           System.IO.Streams.Internal
  import           System.IO.Streams.List
  import           System.IO.Streams.Tests.Common
  
  tests :: [Test]
  tests = [ testAppendInput
          , testConst
          , testCoverLockingStream
          , testPeek
          , testNullInput
          , testGenerator
          , testGeneratorInstances
          , testConsumer
          , testTrivials
          ]
  
  
  ------------------------------------------------------------------------------
  testAppendInput :: Test
  testAppendInput = testCase "internal/appendInputStream" $ do
      s1 <- fromList [1::Int, 2, 3]
      s2 <- fromList [5, 6, 7]
  
      is <- appendInputStream s1 s2
      l  <- toList is
  
      assertEqual "appendInputStream" [1,2,3,5,6,7] l
  
  
  ------------------------------------------------------------------------------
  testConst :: Test
  testConst = testCase "internal/const" $ do
      is <- makeInputStream (return (Just (1::Int)))
      read is >>= assertEqual "const" (Just 1)
  
      unRead 7 is
      read is >>= assertEqual "unRead" (Just 7)
      read is >>= assertEqual "const2" (Just 1)
  
  
  ------------------------------------------------------------------------------
  testNullInput :: Test
  testNullInput = testCase "internal/nullInput" $ do
      is <- nullInput
      xs <- replicateM 10 $ read (is :: InputStream Int)
      assertEqual "nullInput" (replicate 10 Nothing) xs
  
  
  ------------------------------------------------------------------------------
  testCoverLockingStream :: Test
  testCoverLockingStream = testCase "internal/coverLockingStreams" $ do
      is <- fromList [1::Int, 2, 3] >>= lockingInputStream
      (os0, grab) <- listOutputStream
      os <- lockingOutputStream os0
  
      connect is os
      xs <- grab
  
      assertEqual "lockingStreams" [1,2,3] xs
  
      write Nothing os
      write Nothing os
  
      unRead 7 is
      y <- read is
      assertEqual "unRead" (Just 7) y
  
  
  ------------------------------------------------------------------------------
  testPeek :: Test
  testPeek = testCase "internal/peek" $ do
      is <- fromList [1::Int, 2, 3]
      b   <- atEOF is
      assertEqual "eof1" False b
  
      x0  <- peek is
      x1  <- peek is
  
      unRead 7 is
      x2  <- peek is
  
      assertEqual "peek" (map Just [1, 1, 7]) [x0, x1, x2]
  
      l   <- toList is
      assertEqual "toList" [7, 1, 2, 3] l
  
      z   <- peek is
      assertEqual "peekEOF" Nothing z
  
      b'  <- atEOF is
      assertEqual "eof2" True b'
  
  
  ------------------------------------------------------------------------------
  testGenerator :: Test
  testGenerator = testCase "internal/generator" $ do
      is <- fromGenerator $ sequence $
            Prelude.map ((>>= yield) . (liftIO . return)) [1..5::Int]
      toList is >>= assertEqual "generator" [1..5]
      read is >>= assertEqual "read after EOF" Nothing
  
  
  ------------------------------------------------------------------------------
  testGeneratorInstances :: Test
  testGeneratorInstances = testCase "internal/generatorInstances" $ do
      fromGenerator g1 >>= toList
                       >>= assertEqual "generator" [2,4..10]
  
      fromGenerator g2 >>= toList
                       >>= assertEqual "generator" [2,4..10]
  
    where
      g1 = do
          l <- fmap (map (*2)) $ return [1..5::Int]
          fmap id $ sequence_ $ Prelude.map yield l
  
      g2 = pure id <*> g1
  
  
  ------------------------------------------------------------------------------
  testConsumer :: Test
  testConsumer = testCase "internal/consumer" $ do
      is  <- fromList [1..10::Int]
      ref <- newIORef 0
      os  <- fromConsumer (fmap id (pure id <*> c ref))
      connect is os
      readIORef ref >>= assertEqual "sum" (sum [1..10])
  
      -- should be nullsink after receiving Nothing
      write (Just 2) os
      readIORef ref >>= assertEqual "sum" (sum [1..10])
  
      is2 <- fromList [1..10::Int]
      os2 <- fromConsumer (return ())
      connect is2 os2
  
    where
      c ref = await >>= maybe (return ())
                              (\x -> do
                                   !t <- liftIO $ readIORef ref
                                   liftIO $ writeIORef ref $! t + x
                                   c ref)
  
  
  ------------------------------------------------------------------------------
  testTrivials :: Test
  testTrivials = testCase "internal/trivials" $ do
      coverTypeableInstance (undefined :: InputStream Int)
      coverTypeableInstance (undefined :: OutputStream Int)
      coverTypeableInstance (undefined :: Generator Int ())
      coverTypeableInstance (undefined :: Consumer Int ())
      coverTypeableInstance (undefined :: SP Int Int)
  