{-# LANGUAGE OverloadedStrings #-} module Main (main) where import Control.Monad (unless) import qualified Data.Map.Lazy as Map import qualified Data.Text as T import Data.Text.IO (readFile) import Lens.Family2 import Lens.Family2.Stock (at, _Just) import Lens.Family2.Unchecked (iso) import Prelude hiding (readFile) import System.Exit (exitFailure) import Test.Dwergaz import qualified TOML import TOML.Lens allEqual :: Eq a => [a] -> Bool allEqual (x:xs) = all (== x) xs allEqual [] = error "allEqual: empty list" alist :: (Ord k1, Ord k2, Functor f) => LensLike f [(k1, v1)] [(k2, v2)] (Map.Map k1 v1) (Map.Map k2 v2) alist = iso Map.fromList Map.toList mapAt :: Applicative f => T.Text -> (Map.Map T.Text TOML.Value -> f (Map.Map T.Text TOML.Value)) -> Map.Map T.Text TOML.Value -> f (Map.Map T.Text TOML.Value) mapAt k = at k . _Just . _Table . alist listAt :: Applicative f => T.Text -> ([TOML.Value] -> f [TOML.Value]) -> Map.Map T.Text TOML.Value -> f (Map.Map T.Text TOML.Value) listAt k = at k . _Just . _List testTableKey :: [(T.Text, TOML.Value)] -> Test testTableKey kv = Expect "'key' from 'table' == Just \"value\"" (==) expected actual where expected = Just "value" actual = kv ^? alist . mapAt "table" . at "key" . _Just . _String testTableZoo :: [(T.Text, TOML.Value)] -> Test testTableZoo kv = Expect "'zoo' from 'table' == Nothing" (==) expected actual where expected = Nothing actual = kv ^? alist . mapAt "table" . at "zoo" . _Just . _String testTableSubtableKey :: [(T.Text, TOML.Value)] -> Test testTableSubtableKey kv = Expect "'key' from 'subtable' from 'table' == Just \"another value\"" (==) expected actual where expected = Just "another value" actual = kv ^? alist . mapAt "table" . mapAt "subtable" . at "key" . _Just . _String testTableInlineNameFirst :: [(T.Text, TOML.Value)] -> Test testTableInlineNameFirst kv = Expect "'first' from 'name' from 'inline' from 'table' == \"Tom\"" (==) expected actual where expected = Just "Tom" actual = kv ^? alist . mapAt "table" . mapAt "inline" . mapAt "name" . at "first" . _Just . _String testTableInlinePointY :: [(T.Text, TOML.Value)] -> Test testTableInlinePointY kv = Expect "'y' from 'point' from 'inline' from 'table' == Just 2" (==) expected actual where expected = Just 2 actual = kv ^? alist . mapAt "table" . mapAt "inline" . mapAt "point" . at "y" . _Just . _Integer testStringBasicBasic :: [(T.Text, TOML.Value)] -> Test testStringBasicBasic kv = Expect "'basic' from 'basic' from 'string' == " (==) expected actual where expected = Just "I'm a string. \"You can quote me\". Name\tJos\233\nLocation\tSF." actual = kv ^? alist . mapAt "string" . mapAt "basic" . at "basic" . _Just . _String testStringMultiline :: [(T.Text, TOML.Value)] -> Test testStringMultiline kv = Predicate "'key1', 'key2', and 'key3' from 'multiline' from 'string' are all the same" allEqual [actual1, actual2, actual3] where actual1 = kv ^? alist . mapAt "string" . mapAt "multiline" . at "key1" . _Just . _String actual2 = kv ^? alist . mapAt "string" . mapAt "multiline" . at "key2" . _Just . _String actual3 = kv ^? alist . mapAt "string" . mapAt "multiline" . at "key3" . _Just . _String testStringMultilineContinued :: [(T.Text, TOML.Value)] -> Test testStringMultilineContinued kv = Predicate "'key1', 'key2', and 'key3' from 'continued' from 'multiline' from 'string' are all the same" allEqual [actual1, actual2, actual3] where actual1 = kv ^? alist . mapAt "string" . mapAt "multiline" . mapAt "continued" . at "key1" . _Just . _String actual2 = kv ^? alist . mapAt "string" . mapAt "multiline" . mapAt "continued" . at "key2" . _Just . _String actual3 = kv ^? alist . mapAt "string" . mapAt "multiline" . mapAt "continued" . at "key3" . _Just . _String testArrayKey1 :: [(T.Text, TOML.Value)] -> Test testArrayKey1 kv = Expect "'key1' from 'array' == [1, 2, 3]" (==) expected actual where expected = [1, 2, 3] actual = kv ^.. alist . mapAt "array" . listAt "key1" . traverse . _Integer runTests :: [(T.Text, TOML.Value)] -> [Result] runTests kv = runTest . ($ kv) <$> tests where tests = [ testTableKey , testTableZoo , testTableSubtableKey , testTableInlineNameFirst , testTableInlinePointY , testStringBasicBasic , testStringMultiline , testStringMultilineContinued , testArrayKey1 ] readTOMLFile :: String -> IO [(T.Text, TOML.Value)] readTOMLFile file = readFile file >>= parse >>= handleError where parse = pure . TOML.parseTOML handleError = either (error . show) pure main :: IO () main = do ex <- readTOMLFile "./example/example-v0.4.0.toml" let rs = runTests ex mapM_ print rs unless (all isPassed rs) exitFailure