1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (C) 2022-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Kea Hooks Basic
// Commercial End User License Agreement v2.0. See COPYING file in the premium/
// directory.

#include <config.h>

#include <rbac_api.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <testutils/gtest_utils.h>

using namespace isc;
using namespace isc::data;
using namespace isc::rbac;
using namespace std;

namespace {

/// @brief Test fixture for checking RBAC API commands.
class ApiTest : public ::testing::Test {
public:

    /// @brief Constructor.
    ApiTest() {
        apiTable.clear();
    }

    /// @brief Destructor.
    virtual ~ApiTest() {
        apiTable.clear();
    }
};

/// @brief This test verifies that API command object works as expected.
TEST_F(ApiTest, basic) {<--- syntax error
    ApiPtr api;
    EXPECT_NO_THROW(api.reset(new Api("foo", "bar", "xyz")));
    ASSERT_TRUE(api);
    EXPECT_EQ("foo", api->getName());
    EXPECT_EQ("bar", api->getAccess());
    EXPECT_EQ("xyz", api->getHook());

    api->setAccess("my-access");
    api->setHook("my-hook");
    EXPECT_EQ("my-access", api->getAccess());
    EXPECT_EQ("my-hook", api->getHook());
    api->setHook("");
    EXPECT_TRUE(api->getHook().empty());

    // Even it makes no sense empty strings are allowed for all parameters.
    ApiPtr empty;
    EXPECT_NO_THROW(empty.reset(new Api("", "", "")));
    ASSERT_TRUE(empty);
    EXPECT_TRUE(empty->getName().empty());
    EXPECT_TRUE(empty->getAccess().empty());
    EXPECT_TRUE(empty->getHook().empty());
}

/// @brief This test verifies that the API table works as expected.
TEST_F(ApiTest, table) {
    EXPECT_TRUE(apiTable.empty());

    ApiPtr api;
    EXPECT_NO_THROW(api.reset(new Api("foo", "bar", "xyz")));
    ASSERT_TRUE(api);
    apiTable.insert(api);
    EXPECT_EQ(1, apiTable.size());
    ApiPtr got = Api::getApiByName("foo");
    ASSERT_TRUE(got);
    EXPECT_EQ(api->getName(), got->getName());
    EXPECT_EQ(api->getAccess(), got->getAccess());
    EXPECT_EQ(api->getHook(), got->getHook());
    EXPECT_FALSE(Api::getApiByName("bar"));
}

/// @brief This test verifies that API command parsing works as expected.
TEST_F(ApiTest, parse) {
    EXPECT_TRUE(apiTable.empty());

    ElementPtr cfg;
    string expected = "parse null command config";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg = Element::createList();
    expected = "command config is not a map";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg = Element::createMap();
    expected = "'name' is required in command config";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("name", Element::create(1));
    expected = "command name is not a string";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("name", Element::create(string()));
    expected = "command name is empty";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("name", Element::create(string("foo")));
    expected = "'access' is required in command config";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("access", Element::create(true));
    expected = "command access is not a string";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("access", Element::create(string()));
    expected = "command access is empty";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("access", Element::create(string("foo")));
    expected = "command access 'foo' is not 'read' or 'write'";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("access", Element::create(string("read")));
    cfg->set("hook", Element::create(1.23));
    expected = "command hook is not a string";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    cfg->set("hook", Element::create(string()));
    cfg->set("foo", Element::create(string("bar")));
    expected = "command spurious keyword 'foo'";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);

    EXPECT_NO_THROW(Api::parse(cfg, true));
    EXPECT_EQ(1, apiTable.size());
    ApiPtr got = Api::getApiByName("foo");
    ASSERT_TRUE(got);

    cfg->remove("foo");
    expected = "command 'foo' is already defined";
    EXPECT_THROW_MSG(Api::parse(cfg), BadValue, expected);
}

/// @brief This test verifies that fillApiTable works as expected.
TEST_F(ApiTest, fillApiTable) {
    EXPECT_TRUE(apiTable.empty());
    string expected = "fill API table from '/does/not/exist' failed ";
    expected += "with can't open directory '/does/not/exist': ";
    expected += "No such file or directory";
    EXPECT_THROW_MSG(Api::fillApiTable("/does/not/exist"), BadValue, expected);

    string make = string(API_DIR) + "/Makefile.am";
    expected = "fill API table from '";
    expected += make + "' failed with can't open directory '";
    expected += make + "': Not a directory";
    EXPECT_THROW_MSG(Api::fillApiTable(make), BadValue, expected);

    string parent = string(API_DIR) + "/..";
    expected = "can't fill API table from '";
    expected += parent + "': got no command config?";
    EXPECT_THROW_MSG(Api::fillApiTable(parent), BadValue, expected);

    EXPECT_TRUE(apiTable.empty());
    EXPECT_NO_THROW(Api::fillApiTable(string(API_DIR)));
}

} // end of anonymous namespace