packages feed

log4hs-0.5.0.0: test/LoggingTest/InternalSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE RecordWildCards   #-}
{-# LANGUAGE TemplateHaskell   #-}

module LoggingTest.InternalSpec ( spec ) where

import           Control.Monad
import           Data.Default            (def)
import           Data.List               (intercalate)
import qualified Data.Map                as M
import           Data.Word
import           Prelude                 hiding (error)
import           System.IO
import           System.IO.Unsafe        (unsafePerformIO)
import           System.Process          (createPipe)
import           Test.Hspec
import           Test.Hspec.QuickCheck
import           Test.QuickCheck
import           Test.QuickCheck.Monadic
import           Text.Format

import           Logging                 hiding (run)
import           Logging.TH
import           LoggingTest.Prelude

spec :: Spec
spec = describe "run & log" $ do
  let levels = ["DEBUG", "INFO", "WARN", "ERROR", "FATAL"]
      loggers = [ ("root", "DEBUG", [], ["DEBUG"], False, False)
                , ("Disabled", "DEBUG", [], ["DEBUG"], True, False)
                , ("Debug", "DEBUG", [], ["DEBUG", "INFO"], False, False)
                , ("Info", "INFO", ["Info.A"], ["DEBUG", "INFO"], False, False)
                , ("Warn", "WARN", [], ["WARN"], False, False)
                , ("Warn.Error", "ERROR", [], ["ERROR"], False, False)
                , ("Error", "ERROR", [], ["ERROR"], False, True)
                , ("Error.Fatal", "FATAL", [], ["FATAL"], False, True)
                ]
  handlers <- fmap M.fromList $ runIO $ forM levels $ \level -> do
    (read, write) <- createPipe
    hSetEncoding read utf8 >> hSetEncoding write utf8
    let handler = toHandler $ StreamHandler level [] "{message}" write
    return $ (level, (handler, read))
  sinks <- fmap M.fromList $ runIO $ forM loggers $ \item -> do
    let (logger, level, fs, hs, disabled, propagate) = item
        logger' = if logger == "root" then "" else logger
        hs' = [fst (handlers M.! h) | h <- hs]
        sink = Sink logger' level fs hs' disabled propagate
    return (logger, sink)

  let root = sinks M.! "root"
      sinks' = M.delete "root" sinks
      disabledManager = Manager root sinks' True False
      manager = Manager root sinks' False False

  prop "filter" $ \(MessageString message) -> monadicIO $ do
    -- manager disabled
    run $ runLog disabledManager $ $(info) "Debug" message
    msgs <- run $ forM ["DEBUG", "INFO"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ ["", ""] ==  msgs
    -- sink disabled
    run $ runLog manager $ $(debug) "Disabled" message
    msg1 <- run $ hTryGetLine $ snd $ handlers M.! "DEBUG"
    assert $ msg1 == ""
    -- sink level reject
    run $ runLog manager $ $(debug) "Info.A" message
    msgs1 <- run $ forM ["DEBUG", "INFO"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ ["", ""] == msgs1
    -- sink filterer reject
    run $ runLog manager $ $(info) "Info.B" message
    msgs2 <- run $ forM ["DEBUG", "INFO"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ ["", ""] ==  msgs2
    -- pass 1
    run $ runLog manager $ $(info) "Debug" message
    msgs3 <- run $ forM ["DEBUG", "INFO"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ [message, message] == msgs3
    -- pass 2
    run $ runLog manager $ $(info) "Info.A" message
    msgs4 <- run $ forM ["DEBUG", "INFO"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ [message, message] == msgs4

  prop "propagate" $ \(MessageString message) -> monadicIO $ do
    -- propagation disabled 1
    run $ runLog manager $ $(warn) "Warn" message
    msgs <- run $ forM ["DEBUG", "WARN"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ ["", message] == msgs
    -- propagation disabled 2
    run $ runLog manager $ $(error) "Warn.Error" message
    msgs1 <- run $ forM ["DEBUG", "WARN", "ERROR"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ ["", "", message] == msgs1
    -- propagation enabled 1
    run $ runLog manager $ $(error) "Error" message
    msgs2 <- run $ forM ["DEBUG", "ERROR"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ [message, message] == msgs2
    -- propagation enabled 2
    run $ runLog manager $ $(fatal) "Error.Fatal" message
    msgs3 <- run $ forM ["DEBUG", "ERROR", "FATAL"] $ \level ->
      hTryGetLine $ snd $ handlers M.! level
    assert $ [message, message, message] == msgs3