{-# LANGUAGE OverloadedLists #-} -- | Directly ported from puppet specs module Interpreter.CollectorSpec (spec) where import Test.Hspec import Control.Lens import Control.Monad.Except import Data.Text (Text) import qualified Data.Text as T import Helpers import Puppet.Interpreter.Types shouldNotify :: [Text] -> [PValue] -> Expectation shouldNotify content expectedMessages = do cat <- case runExcept (getCatalog (T.unlines content)) of Left rr -> fail rr Right x -> return x let messages = itoList cat ^.. folded . filtered (\rp -> rp ^. _1 . itype == "notify") . _2 . rattributes . ix "message" messages `shouldMatchList` expectedMessages shouldFail :: [Text] -> Expectation shouldFail content = let cat :: Either String FinalCatalog cat = runExcept (getCatalog (T.unlines content)) in cat `shouldSatisfy` has _Left spec :: Spec spec = do it "matches everything when no query given" $ [ "@notify { 'testing': message => 'the message' }" , "@notify { 'other': message => 'the other message' }" , "Notify <| |>" ] `shouldNotify` ["the other message", "the message"] it "matches regular resources" $ [ "notify { \"testing\": message => \"the message\" }" , "notify { \"other\": message => \"the other message\" }" , "Notify <| |> { message => \"changed\" }" ] `shouldNotify` ["changed", "changed"] it "matches on tags" $ [ "@notify { \"testing\": tag => [\"one\"], message => \"wanted\" }" , "@notify { \"other\": tag => [\"two\"], message => \"unwanted\" }" , "Notify <| tag == one |>" ] `shouldNotify` ["wanted"] it "matches on title" $ [ "@notify { \"testing\": message => \"the message\" }" , "Notify <| title == \"testing\" |>" ] `shouldNotify` ["the message"] it "matches on other parameters" $ [ "@notify { \"testing\": message => \"the message\" }" , "@notify { \"other testing\": message => \"the wrong message\" }" , "Notify <| message == \"the message\" |>" ] `shouldNotify` ["the message"] it "matches against elements of an array valued parameter" $ [ "@notify { \"testing\": message => [\"the\", \"message\"] }" , "@notify { \"other testing\": message => [\"not\", \"here\"] }" , "Notify <| message == \"message\" |>" ] `shouldNotify` [PArray ["the", "message"]] it "matches with bare word" $ [ "@notify { \"testing\": tag => [\"one\"], message => \"wanted\" }" , "Notify <| tag == one |>" ] `shouldNotify` ["wanted"] it "matches with single quoted string" $ [ "@notify { \"testing\": tag => [\"one\"], message => \"wanted\" }" , "Notify <| tag == 'one' |>" ] `shouldNotify` ["wanted"] it "matches with double quoted string" $ [ "@notify { \"testing\": tag => [\"one\"], message => \"wanted\" }" , "Notify <| tag == \"one\" |>" ] `shouldNotify` ["wanted"] it "matches with double quoted string with interpolated expression" $ [ "@notify { \"testing\": tag => [\"one\"], message => \"wanted\" }" , "$x = 'one'" , "Notify <| tag == \"$x\" |>" ] `shouldNotify` ["wanted"] it "matches with resource references" $ do pending shouldNotify [ "@notify { \"foobar\": }" , "@notify { \"testing\": require => Notify[\"foobar\"], message => \"wanted\" }" , "Notify <| require == Notify[\"foobar\"] |>" ] ["wanted"] it "allows criteria to be combined with 'and'" $ [ "@notify { \"testing\": message => \"the message\" }" , "@notify { \"other\": message => \"the message\" }" , "Notify <| title == \"testing\" and message == \"the message\" |>" ] `shouldNotify` ["the message"] it "allows criteria to be combined with 'or'" $ [ "@notify { \"testing\": message => \"the message\" }" , "@notify { \"other\": message => \"other message\" }" , "@notify { \"yet another\": message => \"different message\" }" , "Notify <| title == \"testing\" or message == \"other message\" |>" ] `shouldNotify` ["the message", "other message"] it "allows criteria to be grouped with parens" $ [ "@notify { \"testing\": message => \"different message\", withpath => true }" , "@notify { \"other\": message => \"the message\" }" , "@notify { \"yet another\": message => \"the message\", withpath => true }" , "Notify <| (title == \"testing\" or message == \"the message\") and withpath == true |>" ] `shouldNotify` ["the message", "different message"] it "does not do anything if nothing matches" $ [ "@notify { \"testing\": message => \"different message\" }" , "Notify <| title == \"does not exist\" |>" ] `shouldNotify` [] it "excludes items with inequalities" $ [ "@notify { \"testing\": message => \"good message\" }" , "@notify { \"the wrong one\": message => \"bad message\" }" , "Notify <| title != \"the wrong one\" |>" ] `shouldNotify` ["good message"] it "does not exclude resources with unequal arrays" $ [ "@notify { \"testing\": message => \"message\" }" , "@notify { \"the wrong one\": message => [\"not this message\", \"or this one\"] }" , "Notify <| message != \"not this message\" |>" ] `shouldNotify` ["message", PArray ["not this message", "or this one"]] it "does not exclude tags with inequalities" $ [ "@notify { \"testing\": tag => [\"wanted\"], message => \"wanted message\" }" , "@notify { \"other\": tag => [\"why\"], message => \"the way it works\" }" , "Notify <| tag != \"why\" |>" ] `shouldNotify` ["wanted message", "the way it works"] it "does not collect classes" $ shouldFail $ [ "class theclass {" , " @notify { \"testing\": message => \"good message\" }" , "}" , "Class <| |>" ] it "does not collect resources that don't exist" $ do pending shouldFail $ [ "class theclass {" , " @notify { \"testing\": message => \"good message\" }" , "}" , "SomeResource <| |>" ] it "modifies an existing array" $ [ "@notify { \"testing\": message => [\"original message\"] }" , "Notify <| |> {" , " message +> \"extra message\"" , "}"] `shouldNotify` [PArray ["original message", "extra message"]] it "converts a scalar to an array" $ [ "@notify { \"testing\": message => \"original message\" }" , "Notify <| |> {" , " message +> \"extra message\"" , "}"] `shouldNotify` [PArray ["original message", "extra message"]] it "collects and overrides virtual resources multiple times using multiple collects" $ [ "@notify { \"testing\": message => \"original\" }" , "Notify <| |> { message => 'overridden1' }" , "Notify <| |> { message => 'overridden2' }" ] `shouldNotify` ["overridden2"] it "collects and overrides non virtual resources multiple times using multiple collects" $ [ "notify { \"testing\": message => \"original\" }" , "Notify <| |> { message => 'overridden1' }" , "Notify <| |> { message => 'overridden2' }" ] `shouldNotify` ["overridden2"]