BIND 10 trac978, updated. 79143dc457f23670d860a2fa134b13eb62db490b [trac978] Tests for the ACL loading

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Jun 16 11:41:13 UTC 2011


The branch, trac978 has been updated
       via  79143dc457f23670d860a2fa134b13eb62db490b (commit)
      from  3eb58c78cacf7686435e963d423c6c035a737bc0 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 79143dc457f23670d860a2fa134b13eb62db490b
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu Jun 16 13:40:39 2011 +0200

    [trac978] Tests for the ACL loading

-----------------------------------------------------------------------

Summary of changes:
 src/lib/acl/tests/acl_test.cc    |   61 +---------------
 src/lib/acl/tests/loader_test.cc |  153 ++++++++++++++++++++++++++++++++++----
 src/lib/acl/tests/logcheck.h     |   82 ++++++++++++++++++++
 3 files changed, 222 insertions(+), 74 deletions(-)
 create mode 100644 src/lib/acl/tests/logcheck.h

-----------------------------------------------------------------------
diff --git a/src/lib/acl/tests/acl_test.cc b/src/lib/acl/tests/acl_test.cc
index 571257a..dde6f4e 100644
--- a/src/lib/acl/tests/acl_test.cc
+++ b/src/lib/acl/tests/acl_test.cc
@@ -12,69 +12,10 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <gtest/gtest.h>
-#include <acl/acl.h>
-#include <cassert>
-
-using namespace isc::acl;
-using boost::shared_ptr;
+#include "logcheck.h"
 
 namespace {
 
-// This is arbitrary guess of size for the log. If it's too small for your
-// test, just make it bigger.
-const size_t LOG_SIZE = 10;
-
-// This will remember which checks did run already.
-struct Log {
-    // The actual log cells, if i-th check did run
-    bool run[LOG_SIZE];
-    Log() {
-        // Nothing run yet
-        for (size_t i(0); i < LOG_SIZE; ++ i) {
-            run[i] = false;
-        }
-    }
-    // Checks that the first amount of checks did run and the rest didn't.
-    void checkFirst(size_t amount) const {
-        ASSERT_LE(amount, LOG_SIZE) << "Wrong test: amount bigger than size "
-            "of log";
-        {
-            SCOPED_TRACE("Checking that the first amount of checks did run");
-            for (size_t i(0); i < amount; ++ i) {
-                EXPECT_TRUE(run[i]) << "Check #" << i << " did not run.";
-            }
-        }
-
-        {
-            SCOPED_TRACE("Checking that the rest did not run");
-            for (size_t i(amount); i < LOG_SIZE; ++ i) {
-                EXPECT_FALSE(run[i]) << "Check #" << i << "did run.";
-            }
-        }
-    }
-};
-
-// This returns true or false every time, no matter what is passed to it.
-// But it logs that it did run.
-class ConstCheck : public Check<Log*> {
-public:
-    ConstCheck(bool accepts, size_t logNum) :
-        logNum_(logNum),
-        accepts_(accepts)
-    {
-        assert(logNum < LOG_SIZE); // If this fails, the LOG_SIZE is too small
-    }
-    typedef Log* LPtr;
-    virtual bool matches(const LPtr& log) const {
-        log->run[logNum_] = true;
-        return (accepts_);
-    }
-private:
-    size_t logNum_;
-    bool accepts_;
-};
-
 // Test version of the Acl class. It adds few methods to examine the protected
 // data, but does not change the implementation.
 class TestAcl : public Acl<Log*> {
diff --git a/src/lib/acl/tests/loader_test.cc b/src/lib/acl/tests/loader_test.cc
index 686ea50..31f8dd4 100644
--- a/src/lib/acl/tests/loader_test.cc
+++ b/src/lib/acl/tests/loader_test.cc
@@ -12,12 +12,11 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include "logcheck.h"
 #include <acl/loader.h>
-
 #include <string>
 #include <gtest/gtest.h>
 
-using namespace isc::acl;
 using namespace std;
 using namespace boost;
 using isc::data::ConstElementPtr;
@@ -62,24 +61,22 @@ TEST(LoaderHelpers, DefaultActionLoader) {
     testActionLoaderException("{}");
 }
 
-// We need to pass a context, but it doesn't matter here which one
-class NullContext {};
-
 // A check that doesn't check anything but remembers it's own name
 // and data
-class NamedCheck : public Check<NullContext> {
+class NamedCheck : public Check<Log*> {
 public:
     NamedCheck(const string& name, ConstElementPtr data) :
         name_(name),
         data_(data)
     {}
-    virtual bool matches(const NullContext&) const { return (true); }
+    typedef Log* LogPtr;
+    virtual bool matches(const LogPtr&) const { return (true); }
     const string name_;
     const ConstElementPtr data_;
 };
 
 // The creator of NamedCheck
-class NamedCreator : public Loader<NullContext>::CheckCreator {
+class NamedCreator : public Loader<Log*>::CheckCreator {
 public:
     NamedCreator(const string& name, bool abbreviatedList = true) :
         abbreviated_list_(abbreviatedList)
@@ -93,7 +90,7 @@ public:
     vector<string> names() const {
         return (names_);
     }
-    shared_ptr<Check<NullContext> > create(const string& name,
+    shared_ptr<Check<Log*> > create(const string& name,
                                            ConstElementPtr data)
     {
         bool found(false);
@@ -106,7 +103,7 @@ public:
         }
         EXPECT_TRUE(found) << "Name " << name << " passed to creator which "
             "doesn't handle it.";
-        return (shared_ptr<Check<NullContext> >(new NamedCheck(name, data)));
+        return (shared_ptr<Check<Log*> >(new NamedCheck(name, data)));
     }
     bool allowListAbbreviation() const {
         return (abbreviated_list_);
@@ -120,21 +117,66 @@ private:
 class TestCreatorError {};
 
 // This will throw every time it should create something
-class ThrowCreator : public Loader<NullContext>::CheckCreator {
+class ThrowCreator : public Loader<Log*>::CheckCreator {
 public:
     vector<string> names() const {
         vector<string> result;
         result.push_back("throw");
         return (result);
     }
-    shared_ptr<Check<NullContext> > create(const string&, ConstElementPtr) {
+    shared_ptr<Check<Log*> > create(const string&, ConstElementPtr) {
         throw TestCreatorError();
     }
 };
 
+// This throws whenever the match is called on it
+class ThrowCheck : public Check<Log*> {
+public:
+    typedef Log* LogPtr;
+    virtual bool matches(const LogPtr&) const {
+        throw TestCreatorError();
+    }
+};
+
+// And creator for it
+class ThrowCheckCreator : public Loader<Log*>::CheckCreator {
+public:
+    vector<string> names() const {
+        vector<string> result;
+        result.push_back("throwcheck");
+        return (result);
+    }
+    shared_ptr<Check<Log*> > create(const string&, ConstElementPtr) {
+        return (shared_ptr<Check<Log*> >(new ThrowCheck()));
+    }
+};
+
+class LogCreator : public Loader<Log*>::CheckCreator {
+public:
+    vector<string> names() const {
+        vector<string> result;
+        result.push_back("logcheck");
+        return (result);
+    }
+    /*
+     * For simplicity, we just take two values as a list, first is the
+     * logging cell used, the second is result of the check. No error checking
+     * is done, if there's bug in the test, it will throw TypeError for us.
+     */
+    shared_ptr<Check<Log*> > create(const string&,
+                                    ConstElementPtr definition)
+    {
+        vector<ConstElementPtr> list(definition->listValue());
+        int logpos(list[0]->intValue());
+        bool accept(list[1]->boolValue());
+        return (shared_ptr<ConstCheck>(new ConstCheck(accept, logpos)));
+    }
+};
+
 class LoaderTest : public ::testing::Test {
 public:
-    Loader<NullContext> loader_;
+    Loader<Log*> loader_;
+    Log log_;
     // Some convenience functions to set up
 
     // Create a NamedCreator, convert to shared pointer
@@ -152,7 +194,7 @@ public:
     // Load a check and convert it to named check to examine it
     shared_ptr<NamedCheck> loadCheck(const string& definition) {
         SCOPED_TRACE("Loading check " + definition);
-        shared_ptr<Check<NullContext> > loaded;
+        shared_ptr<Check<Log*> > loaded;
         EXPECT_NO_THROW(loaded = loader_.loadCheck(el(definition)));
         shared_ptr<NamedCheck> result(dynamic_pointer_cast<NamedCheck>(
             loaded));
@@ -173,6 +215,29 @@ public:
             EXPECT_EQ(input, e.element());
         }
     }
+    // Insert the throw, throwcheck and logcheck checks into the loader
+    void aclSetup() {
+        loader_.registerCreator(shared_ptr<ThrowCreator>(new ThrowCreator()));
+        loader_.registerCreator(shared_ptr<ThrowCheckCreator>(
+            new ThrowCheckCreator()));
+        loader_.registerCreator(shared_ptr<LogCreator>(new LogCreator()));
+    }
+    // Create an ACL, run it, check it's result and how many first
+    // log items it marked
+    //
+    // Works with preset names throw and logcheck
+    void aclRun(const string& JSON, Action expectedResult, size_t logged) {
+        aclSetup();
+        shared_ptr<Acl<Log*> > acl;
+        EXPECT_NO_THROW(acl = loader_.load(el(JSON)));
+        EXPECT_EQ(expectedResult, acl->execute(&log_));
+        log_.checkFirst(logged);
+    }
+    // Check it throws an error when creating the ACL
+    void aclException(const string& JSON) {
+        aclSetup();
+        EXPECT_THROW(loader_.load(el(JSON)), LoaderError);
+    }
 };
 
 // Test that it does not accept duplicate creator
@@ -281,4 +346,64 @@ TEST_F(LoaderTest, CheckNoAction) {
     EXPECT_TRUE(check->data_->equals(*el("1")));
 }
 
+// The empty ACL can be created and run, providing the default action
+TEST_F(LoaderTest, EmptyACL) {
+    aclRun("[]", REJECT, 0);
+}
+
+// We can create a simple ACL, which will return the correct default
+// action
+TEST_F(LoaderTest, NoMatchACL) {
+    aclRun("[{\"logcheck\": [0, false], \"action\": \"ACCEPT\"}]",
+           REJECT, 1);
+}
+
+// We can created more complicated ACL, it will match at the second
+// check
+TEST_F(LoaderTest, MatchACL) {
+    aclRun("["
+           "  {\"logcheck\": [0, false], \"action\": \"DROP\"},"
+           "  {\"logcheck\": [1, true], \"action\": \"ACCEPT\"}"
+           "]", ACCEPT, 2);
+}
+
+// ACL without a check (matches unconditionally)
+// We add another one check after it, to make sure it is really not run
+TEST_F(LoaderTest, NoCheckACL) {
+    aclRun("["
+           "  {\"acton\": \"DROP\"},"
+           "  {\"throwcheck\": 1, \"action\": \"ACCEPT\"}"
+           "]", DROP, 0);
+}
+
+// Malformed things are rejected
+TEST_F(LoaderTest, InvalidACLFormat) {
+    // Not a list
+    aclException("{}");
+    aclException("42");
+    aclException("true");
+    aclException("null");
+    aclException("\"hello\"");
+    // Malformed element
+    aclException("[42]");
+    aclException("[\"hello\"]");
+    aclException("[[]]");
+    aclException("[true]");
+    aclException("[null]");
+}
+
+// If there's no action keyword, it is rejected
+TEST_F(LoaderTest, NoAction) {
+    aclException("[{}]");
+    aclException("[{\"logcheck\": [0, true]}]");
+}
+
+// Exceptions from check creation is propagated
+TEST_F(LoaderTest, ACLPropagate) {
+    aclSetup();
+    EXPECT_THROW(loader_.load(el("[{\"action\": \"ACCEPT\", \"throw\": 1]")),
+                 TestCreatorError);
+
+}
+
 }
diff --git a/src/lib/acl/tests/logcheck.h b/src/lib/acl/tests/logcheck.h
new file mode 100644
index 0000000..235cb94
--- /dev/null
+++ b/src/lib/acl/tests/logcheck.h
@@ -0,0 +1,82 @@
+// 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 <gtest/gtest.h>
+#include <acl/acl.h>
+#include <cassert>
+
+// This is not a public header, it is used only inside the tests. Therefore
+// we lower the standards a bit and use anonymous namespace in the header
+// and "using", just for convenience. This is just to share little bit of code
+// between multiple tests.
+using namespace isc::acl;
+using boost::shared_ptr;
+
+namespace {
+
+// This is arbitrary guess of size for the log. If it's too small for your
+// test, just make it bigger.
+const size_t LOG_SIZE = 10;
+
+// This will remember which checks did run already.
+struct Log {
+    // The actual log cells, if i-th check did run
+    bool run[LOG_SIZE];
+    Log() {
+        // Nothing run yet
+        for (size_t i(0); i < LOG_SIZE; ++ i) {
+            run[i] = false;
+        }
+    }
+    // Checks that the first amount of checks did run and the rest didn't.
+    void checkFirst(size_t amount) const {
+        ASSERT_LE(amount, LOG_SIZE) << "Wrong test: amount bigger than size "
+            "of log";
+        {
+            SCOPED_TRACE("Checking that the first amount of checks did run");
+            for (size_t i(0); i < amount; ++ i) {
+                EXPECT_TRUE(run[i]) << "Check #" << i << " did not run.";
+            }
+        }
+
+        {
+            SCOPED_TRACE("Checking that the rest did not run");
+            for (size_t i(amount); i < LOG_SIZE; ++ i) {
+                EXPECT_FALSE(run[i]) << "Check #" << i << "did run.";
+            }
+        }
+    }
+};
+
+// This returns true or false every time, no matter what is passed to it.
+// But it logs that it did run.
+class ConstCheck : public Check<Log*> {
+public:
+    ConstCheck(bool accepts, size_t logNum) :
+        logNum_(logNum),
+        accepts_(accepts)
+    {
+        assert(logNum < LOG_SIZE); // If this fails, the LOG_SIZE is too small
+    }
+    typedef Log* LPtr;
+    virtual bool matches(const LPtr& log) const {
+        log->run[logNum_] = true;
+        return (accepts_);
+    }
+private:
+    size_t logNum_;
+    bool accepts_;
+};
+
+}




More information about the bind10-changes mailing list