diff --git a/fencer.cabal b/fencer.cabal index 66e9c89..4cf9587 100644 --- a/fencer.cabal +++ b/fencer.cabal @@ -114,6 +114,8 @@ test-suite test-fencer Fencer.Logic.Test Fencer.Types.Test Fencer.Rules.Test + Fencer.Rules.Test.Helpers + Fencer.Rules.Test.Types Fencer.Server.Test default-language: Haskell2010 diff --git a/test/Fencer/Rules/Test.hs b/test/Fencer/Rules/Test.hs index 99d1255..f706920 100644 --- a/test/Fencer/Rules/Test.hs +++ b/test/Fencer/Rules/Test.hs @@ -6,29 +6,24 @@ -- | Tests for "Fencer.Rules". module Fencer.Rules.Test ( tests - , writeAndLoadRules -- example values , domain1Text , domain2Text - , RuleFile(..) - , simpleRuleFile ) where import BasePrelude -import Data.List (sortOn) import Data.Text (Text) -import qualified Data.Text.IO as TIO import qualified Data.Yaml as Yaml -import Named ((:!), arg) import NeatInterpolation (text) -import qualified System.IO.Temp as Temp -import System.FilePath (takeDirectory, ()) import qualified System.Directory as Dir +import System.FilePath (()) import Test.Tasty (TestTree, testGroup) -import Test.Tasty.HUnit (assertBool, assertEqual, Assertion, testCase) +import Test.Tasty.HUnit (testCase) import Fencer.Rules +import Fencer.Rules.Test.Helpers (expectLoadRules) +import Fencer.Rules.Test.Types import Fencer.Types @@ -190,101 +185,6 @@ test_rulesLoadRulesReadPermissions = ("domain2" "config" "config.yml") domain2Text ----------------------------------------------------------------------------- --- Helpers ----------------------------------------------------------------------------- - --- | Get a list of values on the Left or an empty list if it is a --- Right value. -toErrorList :: Either [a] [b] -> [a] -toErrorList (Right _) = [] -toErrorList (Left xs) = xs - --- | A record useful in testing, which groups together a file path, --- its contents and file permissions. -data RuleFile = MkRuleFile - { -- | The path to the file - ruleFilePath :: FilePath - -- | The contents of the file in plain text - , ruleFileContents :: Text - -- | A function specifying how the file permissions should be - -- changed, i.e., what they should be once the file is written to - -- disk. - , ruleFileModifyPermissions :: Dir.Permissions -> Dir.Permissions - } - -simpleRuleFile :: FilePath -> Text -> RuleFile -simpleRuleFile p c = MkRuleFile p c id - --- | Write contents to a path in the given root and modify file --- permissions. -writeFile - :: "root" :! FilePath - -> "file" :! RuleFile - -> IO () -writeFile - (arg #root -> root) - (arg #file -> file) = do - - let - dir = takeDirectory (ruleFilePath file) - fullPath = root (ruleFilePath file) - Dir.createDirectoryIfMissing True (root dir) - TIO.writeFile fullPath (ruleFileContents file) - perms <- Dir.getPermissions fullPath - Dir.setPermissions fullPath (ruleFileModifyPermissions file perms) - --- | Write the content of files at the given root and load the files. -writeAndLoadRules - :: "ignoreDotFiles" :! Bool - -> "root" :! FilePath - -> "files" :! [RuleFile] - -> IO (Either [LoadRulesError] [DomainDefinition]) -writeAndLoadRules - (arg #ignoreDotFiles -> ignoreDotFiles) - (arg #root -> root) - (arg #files -> files) = do - - forM_ files $ \file -> Fencer.Rules.Test.writeFile - (#root root) - (#file file) - loadRulesFromDirectory - (#rootDirectory root) - (#subDirectory ".") - (#ignoreDotFiles ignoreDotFiles) - --- | Create given directory structure and check that --- 'loadRulesFromDirectory' produces expected result such that file --- permissions are configurable. -expectLoadRules - :: "ignoreDotFiles" :! Bool - -> "files" :! [RuleFile] - -> "result" :! Either [LoadRulesError] [DomainDefinition] - -> Assertion -expectLoadRules - (arg #ignoreDotFiles -> ignoreDotFiles) - (arg #files -> files) - (arg #result -> result) = - Temp.withSystemTempDirectory "fencer-config" $ \tempDir -> - writeAndLoadRules - (#ignoreDotFiles ignoreDotFiles) - (#root tempDir) - (#files files) - >>= \case - f@(Left _) -> - -- Paths to temporary files vary and there is not much point - -- in writing down exact expected exception messages so the - -- only assertion made is that the number of exceptions is the - -- same. - assertEqual - "unexpected failure" - (length . toErrorList $ result) - (length . toErrorList $ f) - Right definitions -> assertBool "unexpected definitions" - (((==) `on` show) - (sortOn domainDefinitionId <$> result) - (Right $ sortOn domainDefinitionId definitions)) - ---------------------------------------------------------------------------- -- Sample definitions ---------------------------------------------------------------------------- diff --git a/test/Fencer/Rules/Test/Helpers.hs b/test/Fencer/Rules/Test/Helpers.hs new file mode 100644 index 0000000..eda2491 --- /dev/null +++ b/test/Fencer/Rules/Test/Helpers.hs @@ -0,0 +1,100 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE OverloadedLabels #-} + +-- | Module with helper functions used in rules and other testing. +module Fencer.Rules.Test.Helpers + ( toErrorList + , writeContentsToFile + , writeAndLoadRules + , expectLoadRules + ) +where + +import BasePrelude + +import qualified Data.Text.IO as TIO +import Named ((:!), arg) +import qualified System.Directory as Dir +import System.FilePath (FilePath, takeDirectory, ()) +import qualified System.IO.Temp as Temp +import Test.Tasty.HUnit (assertBool, assertEqual, Assertion) + +import Fencer.Rules (LoadRulesError(..), loadRulesFromDirectory) +import Fencer.Rules.Test.Types (RuleFile(..)) +import Fencer.Types (DomainDefinition(..)) + +-- | Get a list of values on the Left or an empty list if it is a +-- Right value. +toErrorList :: Either [a] [b] -> [a] +toErrorList (Right _) = [] +toErrorList (Left xs) = xs + +-- | Write contents to a path in the given root and modify file +-- permissions. +writeContentsToFile + :: "root" :! FilePath + -> "file" :! RuleFile + -> IO () +writeContentsToFile + (arg #root -> root) + (arg #file -> file) = do + + let + dir = takeDirectory (ruleFilePath file) + fullPath = root (ruleFilePath file) + Dir.createDirectoryIfMissing True (root dir) + TIO.writeFile fullPath (ruleFileContents file) + perms <- Dir.getPermissions fullPath + Dir.setPermissions fullPath (ruleFileModifyPermissions file perms) + +-- | Write the content of files at the given root and load the files. +writeAndLoadRules + :: "ignoreDotFiles" :! Bool + -> "root" :! FilePath + -> "files" :! [RuleFile] + -> IO (Either [LoadRulesError] [DomainDefinition]) +writeAndLoadRules + (arg #ignoreDotFiles -> ignoreDotFiles) + (arg #root -> root) + (arg #files -> files) = do + + forM_ files $ \file -> writeContentsToFile + (#root root) + (#file file) + loadRulesFromDirectory + (#rootDirectory root) + (#subDirectory ".") + (#ignoreDotFiles ignoreDotFiles) + +-- | Create given directory structure and check that +-- 'loadRulesFromDirectory' produces expected result such that file +-- permissions are configurable. +expectLoadRules + :: "ignoreDotFiles" :! Bool + -> "files" :! [RuleFile] + -> "result" :! Either [LoadRulesError] [DomainDefinition] + -> Assertion +expectLoadRules + (arg #ignoreDotFiles -> ignoreDotFiles) + (arg #files -> files) + (arg #result -> result) = + Temp.withSystemTempDirectory "fencer-config" $ \tempDir -> + writeAndLoadRules + (#ignoreDotFiles ignoreDotFiles) + (#root tempDir) + (#files files) + >>= \case + f@(Left _) -> + -- Paths to temporary files vary and there is not much point + -- in writing down exact expected exception messages so the + -- only assertion made is that the number of exceptions is the + -- same. + assertEqual + "unexpected failure" + (length . toErrorList $ result) + (length . toErrorList $ f) + Right definitions -> assertBool "unexpected definitions" + (((==) `on` show) + (sortOn domainDefinitionId <$> result) + (Right $ sortOn domainDefinitionId definitions)) + diff --git a/test/Fencer/Rules/Test/Types.hs b/test/Fencer/Rules/Test/Types.hs new file mode 100644 index 0000000..af2e3df --- /dev/null +++ b/test/Fencer/Rules/Test/Types.hs @@ -0,0 +1,27 @@ +-- | Types useful for rule testing. +module Fencer.Rules.Test.Types + ( RuleFile(..) + , simpleRuleFile) +where + +import BasePrelude + +import Data.Text (Text) +import qualified System.Directory as Dir +import System.FilePath (FilePath) + +-- | A record useful in testing, which groups together a file path, +-- its contents and file permissions. +data RuleFile = MkRuleFile + { -- | The path to the file + ruleFilePath :: FilePath + -- | The contents of the file in plain text + , ruleFileContents :: Text + -- | A function specifying how the file permissions should be + -- changed, i.e., what they should be once the file is written to + -- disk. + , ruleFileModifyPermissions :: Dir.Permissions -> Dir.Permissions + } + +simpleRuleFile :: FilePath -> Text -> RuleFile +simpleRuleFile p c = MkRuleFile p c id diff --git a/test/Fencer/Server/Test.hs b/test/Fencer/Server/Test.hs index c3b4e1a..36304a4 100644 --- a/test/Fencer/Server/Test.hs +++ b/test/Fencer/Server/Test.hs @@ -32,6 +32,8 @@ import Fencer.Settings (defaultGRPCPort, getLogLevel, newLogger) import Fencer.Types import Fencer.Rules import qualified Fencer.Rules.Test as RTest +import Fencer.Rules.Test.Helpers (writeAndLoadRules) +import Fencer.Rules.Test.Types (RuleFile(..), simpleRuleFile) import qualified Fencer.Proto as Proto {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} @@ -142,7 +144,7 @@ test_serverResponseReadPermissions = testCase "OK response with one YAML file without read permissions" $ Temp.withSystemTempDirectory "fencer-config" $ \tempDir -> do server <- serverIO - RTest.writeAndLoadRules + writeAndLoadRules (#ignoreDotFiles False) (#root tempDir) (#files files) @@ -158,13 +160,13 @@ test_serverResponseReadPermissions = (expectedResponse, Grpc.StatusOk) response where - files :: [RTest.RuleFile] + files :: [RuleFile] files = - [ RTest.MkRuleFile + [ MkRuleFile ("domain1" "config.yml") RTest.domain1Text (const Dir.emptyPermissions) - , RTest.simpleRuleFile + , simpleRuleFile ("domain2" "config" "config.yml") RTest.domain2Text ]