123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include "creators.h"
- #include <acl/logic_check.h>
- #include <typeinfo>
- #include <boost/shared_ptr.hpp> // for static_pointer_cast
- using namespace std;
- using namespace boost;
- using namespace isc::acl;
- using namespace isc::acl::tests;
- using isc::data::Element;
- namespace {
- // Test the defs in AnyOfSpec
- TEST(LogicOperators, AnyOfSpec) {
- EXPECT_FALSE(AnyOfSpec::start());
- EXPECT_FALSE(AnyOfSpec::terminate(false));
- EXPECT_TRUE(AnyOfSpec::terminate(true));
- }
- // Test the defs in AllOfSpec
- TEST(LogicOperators, AllOfSpec) {
- EXPECT_TRUE(AllOfSpec::start());
- EXPECT_TRUE(AllOfSpec::terminate(false));
- EXPECT_FALSE(AllOfSpec::terminate(true));
- }
- // Generic test of one check
- template<typename Mode>
- void
- testCheck(bool emptyResult) {
- // It can be created
- LogicOperator<Mode, Log> oper;
- // It is empty by default
- EXPECT_EQ(0, oper.getSubexpressions().size());
- // And returns true, as all 0 of the subexpressions return true
- Log log;
- EXPECT_EQ(emptyResult, oper.matches(log));
- log.checkFirst(0);
- // Fill it with some subexpressions
- typedef shared_ptr<ConstCheck> CheckPtr;
- oper.addSubexpression(CheckPtr(new ConstCheck(emptyResult, 0)));
- oper.addSubexpression(CheckPtr(new ConstCheck(emptyResult, 1)));
- // Check what happens when only the default-valued are there
- EXPECT_EQ(2, oper.getSubexpressions().size());
- EXPECT_EQ(emptyResult, oper.matches(log));
- log.checkFirst(2);
- oper.addSubexpression(CheckPtr(new ConstCheck(!emptyResult, 2)));
- oper.addSubexpression(CheckPtr(new ConstCheck(!emptyResult, 3)));
- // They are listed there
- EXPECT_EQ(4, oper.getSubexpressions().size());
- // Now, the last one kills it, but the first ones will run, the fourth
- // won't
- EXPECT_EQ(!emptyResult, oper.matches(log));
- log.checkFirst(3);
- }
- TEST(LogicOperators, AllOf) {
- testCheck<AllOfSpec>(true);
- }
- TEST(LogicOperators, AnyOf) {
- testCheck<AnyOfSpec>(false);
- }
- // Fixture for the tests of the creators
- class LogicCreatorTest : public ::testing::Test {
- private:
- typedef shared_ptr<Loader<Log>::CheckCreator> CreatorPtr;
- public:
- // Register some creators, both tested ones and some auxiliary ones for
- // help
- LogicCreatorTest():
- loader_(REJECT)
- {
- loader_.registerCreator(CreatorPtr(new
- LogicCreator<AnyOfSpec, Log>("ANY")));
- loader_.registerCreator(CreatorPtr(new
- LogicCreator<AllOfSpec, Log>("ALL")));
- loader_.registerCreator(CreatorPtr(new ThrowCreator));
- loader_.registerCreator(CreatorPtr(new LogCreator));
- }
- // To mark which parts of the check did run
- Log log_;
- // The loader
- Loader<Log> loader_;
- // Some convenience shortcut names
- typedef LogicOperator<AnyOfSpec, Log> AnyOf;
- typedef LogicOperator<AllOfSpec, Log> AllOf;
- typedef shared_ptr<AnyOf> AnyOfPtr;
- typedef shared_ptr<AllOf> AllOfPtr;
- // Loads the JSON as a check and tries to convert it to the given check
- // subclass
- template<typename Result> shared_ptr<Result> load(const string& JSON) {
- shared_ptr<Check<Log> > result;
- EXPECT_NO_THROW(result = loader_.loadCheck(Element::fromJSON(JSON)));
- /*
- * Optimally, we would use a dynamic_pointer_cast here to both
- * convert the pointer and to check the type is correct. However,
- * clang++ seems to be confused by templates and creates two typeids
- * for the same templated type (even with the same parameters),
- * therfore considering the types different, even if they are the same.
- * This leads to false alarm in the test. Luckily, it generates the
- * same name for both typeids, so we use them instead (which is enough
- * to test the correct type of Check is returned). Then we can safely
- * cast statically, as we don't use any kind of nasty things like
- * multiple inheritance.
- */
- EXPECT_STREQ(typeid(Result).name(), typeid(*result.get()).name());
- shared_ptr<Result>
- resultConverted(static_pointer_cast<Result>(result));
- EXPECT_NE(shared_ptr<Result>(), resultConverted);
- return (resultConverted);
- }
- };
- // Test it can load empty ones
- TEST_F(LogicCreatorTest, empty) {
- AnyOfPtr emptyAny(load<AnyOf>("{\"ANY\": []}"));
- EXPECT_EQ(0, emptyAny->getSubexpressions().size());
- AllOfPtr emptyAll(load<AllOf>("{\"ALL\": []}"));
- EXPECT_EQ(0, emptyAll->getSubexpressions().size());
- }
- // Test it rejects invalid inputs (not a list as a parameter)
- TEST_F(LogicCreatorTest, invalid) {
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ANY\": null}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ANY\": {}}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ANY\": true}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ANY\": 42}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ANY\": \"hello\"}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ALL\": null}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ALL\": {}}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ALL\": true}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ALL\": 42}")),
- LoaderError);
- EXPECT_THROW(loader_.loadCheck(Element::fromJSON("{\"ALL\": \"hello\"}")),
- LoaderError);
- }
- // Exceptions from subexpression creation isn't caught
- TEST_F(LogicCreatorTest, propagate) {
- EXPECT_THROW(loader_.loadCheck(
- Element::fromJSON("{\"ANY\": [{\"throw\": null}]}")),
- TestCreatorError);
- EXPECT_THROW(loader_.loadCheck(
- Element::fromJSON("{\"ALL\": [{\"throw\": null}]}")),
- TestCreatorError);
- }
- // We can create more complex ANY check and run it correctly
- TEST_F(LogicCreatorTest, anyRun) {
- AnyOfPtr any(load<AnyOf>("{\"ANY\": ["
- " {\"logcheck\": [0, false]},"
- " {\"logcheck\": [1, true]},"
- " {\"logcheck\": [2, true]}"
- "]}"));
- EXPECT_EQ(3, any->getSubexpressions().size());
- EXPECT_TRUE(any->matches(log_));
- log_.checkFirst(2);
- }
- // We can create more complex ALL check and run it correctly
- TEST_F(LogicCreatorTest, allRun) {
- AllOfPtr any(load<AllOf>("{\"ALL\": ["
- " {\"logcheck\": [0, true]},"
- " {\"logcheck\": [1, false]},"
- " {\"logcheck\": [2, false]}"
- "]}"));
- EXPECT_EQ(3, any->getSubexpressions().size());
- EXPECT_FALSE(any->matches(log_));
- log_.checkFirst(2);
- }
- // Or is able to return false
- TEST_F(LogicCreatorTest, anyFalse) {
- AnyOfPtr any(load<AnyOf>("{\"ANY\": ["
- " {\"logcheck\": [0, false]},"
- " {\"logcheck\": [1, false]},"
- " {\"logcheck\": [2, false]}"
- "]}"));
- EXPECT_EQ(3, any->getSubexpressions().size());
- EXPECT_FALSE(any->matches(log_));
- log_.checkFirst(3);
- }
- // And is able to return true
- TEST_F(LogicCreatorTest, andTrue) {
- AllOfPtr all(load<AllOf>("{\"ALL\": ["
- " {\"logcheck\": [0, true]},"
- " {\"logcheck\": [1, true]},"
- " {\"logcheck\": [2, true]}"
- "]}"));
- EXPECT_EQ(3, all->getSubexpressions().size());
- EXPECT_TRUE(all->matches(log_));
- log_.checkFirst(3);
- }
- // We can nest them together
- TEST_F(LogicCreatorTest, nested) {
- AllOfPtr all(load<AllOf>("{\"ALL\": ["
- " {\"ANY\": ["
- " {\"logcheck\": [0, true]},"
- " {\"logcheck\": [2, true]},"
- " ]},"
- " {\"logcheck\": [1, false]}"
- "]}"));
- EXPECT_EQ(2, all->getSubexpressions().size());
- /*
- * This has the same problem as load function above, and we use the
- * same solution here.
- */
- ASSERT_STREQ(typeid(LogicOperator<AnyOfSpec, Log>).name(),
- typeid(*all->getSubexpressions()[0]).name());
- const LogicOperator<AnyOfSpec, Log>*
- any(static_cast<const LogicOperator<AnyOfSpec, Log>*>
- (all->getSubexpressions()[0]));
- EXPECT_EQ(2, any->getSubexpressions().size());
- EXPECT_FALSE(all->matches(log_));
- log_.checkFirst(2);
- }
- }
|