acl_test.cc 4.26 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 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>
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
17
#include <cassert>
18

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
34
        for (size_t i(0); i < LOG_SIZE; ++i) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
35
36
37
38
39
40
41
42
43
            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");
44
            for (size_t i(0); i < amount; ++i) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
45
46
47
48
49
50
                EXPECT_TRUE(run[i]) << "Check #" << i << " did not run.";
            }
        }

        {
            SCOPED_TRACE("Checking that the rest did not run");
51
            for (size_t i(amount); i < LOG_SIZE; ++i) {
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
52
53
54
55
56
57
58
59
60
61
                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:
62
63
    ConstCheck(bool accepts, size_t log_num) :
        log_num_(log_num),
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
64
65
        accepts_(accepts)
    {
66
        assert(log_num < LOG_SIZE); // If this fails, the LOG_SIZE is too small
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
67
68
69
    }
    typedef Log* LPtr;
    virtual bool matches(const LPtr& log) const {
70
        log->run[log_num_] = true;
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
71
72
73
        return (accepts_);
    }
private:
74
    size_t log_num_;
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
75
76
77
78
79
80
81
82
83
    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*> {
public:
    TestAcl() :
        Acl(DROP)
84
    {}
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
85
86
87
88
89
90
91
92
93
94
95
    // Check the stored policy there
    void checkPolicy(Action ac) {
        EXPECT_EQ(policy_, ac);
    }
};

// The test fixture. Contains some members so they don't need to be manually
// created each time and some convenience functions.
class AclTest : public ::testing::Test {
public:
    AclTest() :
96
97
        next_check_(0)
    {}
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
98
99
    TestAcl acl_;
    Log log_;
100
    size_t next_check_;
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
101
102
    shared_ptr<Check<Log*> > getCheck(bool accepts) {
        return (shared_ptr<Check<Log*> >(new ConstCheck(accepts,
103
                                                        next_check_++)));
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    }
};

/*
 * This tests the policy (default return value) and that nothing is run
 * if nothing is inserted (it's hard to imagine otherwise though).
 *
 * We use the default ACL unchanged from the test class.
 */
TEST_F(AclTest, emptyPolicy) {
    acl_.checkPolicy(DROP);
    EXPECT_EQ(DROP, acl_.execute(&log_));
    // No test was run
    log_.checkFirst(0);
}

/*
 * This tests the policy in case no check matches.
 */
TEST_F(AclTest, policy) {
    acl_.append(getCheck(false), ACCEPT);
    acl_.append(getCheck(false), REJECT);
    EXPECT_EQ(DROP, acl_.execute(&log_));
    // The first two checks were actually run (and didn't match)
    log_.checkFirst(2);
}

/*
 * Checks that it takes the first matching check and returns the
 * value. Also checks that the others aren't run at all.
 */
TEST_F(AclTest, check) {
    acl_.append(getCheck(false), ACCEPT);
    acl_.append(getCheck(true), REJECT);
    acl_.append(getCheck(true), ACCEPT);
    EXPECT_EQ(REJECT, acl_.execute(&log_));
    log_.checkFirst(2);
}

}