----------------------------------------------------------------------------
-- |
-- Module : TomlReaderTests
-- Copyright : (c) Sergey Vinokurov 2022
-- License : Apache-2.0 (see LICENSE)
-- Maintainer : serg.foo@gmail.com
----------------------------------------------------------------------------
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module TomlReaderTests (main) where
import Control.Arrow (left)
import Data.Text (Text)
import Options.Applicative as Opts
import Prettyprinter
import Prettyprinter.Combinators
import Prettyprinter.Generics
import System.Exit
import System.IO
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.Options qualified as Tasty
import Test.Tasty.Runners qualified as Tasty
import TOML as Toml
import TOML.Parse as Toml
data Config = Config
{ cfgTastyOpts :: !Tasty.OptionSet
}
optsParser :: Opts.Parser Tasty.OptionSet -> Opts.Parser Config
optsParser tastyParser = do
cfgTastyOpts <- tastyParser
pure Config{..}
progInfo :: Opts.Parser Tasty.OptionSet -> Opts.ParserInfo Config
progInfo tastyParser = info
(helper <*> optsParser tastyParser)
(fullDesc <> header "My new shiny test suite!")
main :: IO ()
main = do
Tasty.installSignalHandlers
let allTests = tests
ingredients = defaultIngredients
tastyParser = snd $ Tasty.suiteOptionParser ingredients allTests
Config{cfgTastyOpts} <-
customExecParser (prefs (showHelpOnEmpty <> noBacktrack <> multiSuffix "*")) (progInfo tastyParser)
case Tasty.tryIngredients ingredients cfgTastyOpts allTests of
Nothing -> do
hPutStrLn stderr
"No ingredients agreed to run. Something is wrong either with your ingredient set or the options."
exitFailure
Just act -> do
ok <- act
if ok then exitSuccess else exitFailure
data Sample1 = Sample1
{ _sample1Bar :: String
, _sample1Frob :: [Int]
} deriving (Eq, Show)
instance FromToml Toml.Value Sample1 where
fromToml x = do
(foo :: L Table) <- x .: "foo"
Sample1 <$> foo .: "bar" <*> foo .: "frob"
data Sample2 = Sample2
{ _sample2Bar :: String
, _sample2Frob :: [Int]
} deriving (Eq, Show)
instance FromToml Toml.Value Sample2 where
fromToml x = do
foo <- x .: "foo" >>= pTableL
Sample2 <$> foo .: "bar" <*> foo .: "frob"
newtype SpecialString = SpecialString { unSpecialString :: String }
deriving (Eq, Show, FromToml Value)
data Sample3 = Sample3
{ _sample3Bar :: SpecialString
, _sample3Frob :: [Int]
} deriving (Eq, Show)
instance FromToml Toml.Value Sample3 where
fromToml x = do
(foo :: L Table) <- x .: "foo"
Sample3 <$> foo .: "bar" <*> foo .: "frob"
sample :: Text
sample =
"\
\[foo]\n\
\bar = \"quux\"\n\
\frob = [1, 2]\n\
\"
deriving instance Generic Value
deriving instance Generic ContextItem
deriving instance Generic DecodeError
deriving instance Generic NormalizeError
deriving instance Generic TOMLError
instance Pretty Value where
pretty = ppToml
instance Pretty ContextItem where
pretty = ppGeneric
instance Pretty DecodeError where
pretty = ppGeneric
instance Pretty NormalizeError where
pretty = ppGeneric
instance Pretty TOMLError where
pretty = ppGeneric
tests :: TestTree
tests = testGroup "Tests"
[ testCase "Test 1" $
(left renderString (left pretty (Toml.decode sample) >>= (\x -> Toml.runParser (x :: Value) Toml.fromToml))) @?=
Right (Sample1 "quux" [1, 2])
, testCase "Test 2" $
(left renderString (left pretty (Toml.decode sample) >>= (\x -> Toml.runParser (x :: Value) Toml.fromToml))) @?=
Right (Sample2 "quux" [1, 2])
, testCase "Test 3" $
(left renderString (left pretty (Toml.decode sample) >>= (\x -> Toml.runParser (x :: Value) Toml.fromToml))) @?=
Right (Sample3 (SpecialString "quux") [1, 2])
]