{-# LANGUAGE OverloadedStrings #-} module Main where import Control.Monad (liftM) import Data.Monoid ((<>)) import Data.Hashable (Hashable) import Data.Text (Text) import Data.List as List import Data.Text as Text import qualified Data.Text as ST import Test.Framework (defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck (Gen, Property, Arbitrary(..), elements, sized, oneof, listOf) import Test.QuickCheck.Monadic (assert) import Data.Yaml(Object, Value(Object, Null)) import qualified Data.HashMap.Strict as HashMap import Data.Yaml.Config.Internal (Config(Config), Key, lookupSubconfig, keys, fullpath) type CorrectPath = [Key] data DeepObject = DeepObject Config CorrectPath deriving (Eq, Show) instance Arbitrary Text where arbitrary = liftM Text.pack arbitrary instance Arbitrary DeepObject where arbitrary = deepConfig newObject :: [(Key, Value)] -> Object newObject = HashMap.fromList deepConfig :: Gen DeepObject deepConfig = sized deepConfig' >>= \(keys, obj) -> return $ DeepObject (Config [] obj) $ List.tail keys deepConfig' :: Int -> Gen ([Key], Object) deepConfig' 0 = arbitrary >>= \newKey -> return $ ([newKey], newObject []) deepConfig' n | n > 0 = do newKey <- arbitrary (keys, newNode) <- deepConfig' (pred n) return $ (newKey : keys, newObject [(List.head keys , Object newNode)]) testCorrectSubconfigPath :: DeepObject -> Bool testCorrectSubconfigPath (DeepObject _ []) = True testCorrectSubconfigPath (DeepObject config (key : others)) = maybe False (`subcheck` others) $ lookupSubconfig config key where subcheck sc keys = testCorrectSubconfigPath $ DeepObject sc keys testWrongSubconfigPath :: DeepObject -> Bool testWrongSubconfigPath (DeepObject config []) = List.null $ keys config testWrongSubconfigPath (DeepObject config (nextKey : others)) = maybe nextCheck (const False) $ lookupSubconfig config wrongKey where nextCheck = maybe False (testWrongSubconfigPath . nextDeep) $ lookupSubconfig config nextKey nextDeep = flip DeepObject others wrongKey = nextKey <> "_" testCorrectPath :: DeepObject -> Bool testCorrectPath = testCorrectPath' [] testCorrectPath' path (DeepObject config (nextKey : others)) = checkPath config && (maybe False (`subcheck` others) $ lookupSubconfig config nextKey) where subcheck sc keys = testCorrectPath' (nextKey : path) $ DeepObject sc keys checkPath c = fullpath c nextKey == (ST.intercalate "." $ List.reverse $ nextKey : path) testCorrectPath' _ (DeepObject config []) = List.null $ keys config main :: IO () main = defaultMain [ testGroup "lookup" [ testProperty "wrongSubconfigPath" testWrongSubconfigPath , testProperty "correctSubconfigPath" testCorrectSubconfigPath , testProperty "correctPath" testCorrectPath ] ]