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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright (C) 2018-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <config.h>

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

#include <asiolink/testutils/timed_signal.h>
#include <cc/data.h>
#include <netconf/netconf_controller.h>
#include <netconf/netconf_process.h>
#include <process/testutils/d_test_stubs.h>
#include <testutils/gtest_utils.h>

using namespace isc::asiolink::test;
using namespace isc::netconf;
using namespace isc::data;
using namespace isc::http;
using namespace isc::process;
using namespace std;

namespace {

/// @brief Valid Netconf Config used in tests.
const char* valid_netconf_config =
    "{"
    "  \"boot-update\": false,"
    "  \"subscribe-changes\": false,"
    "  \"managed-servers\": {"
    "    \"dhcp4\": {"
    "      \"control-socket\": {"
    "        \"socket-type\": \"unix\","
    "        \"socket-name\": \"/first/dhcp4/socket\""
    "      }"
    "    },"
    "    \"dhcp6\": {"
    "      \"control-socket\": {"
    "        \"socket-type\": \"unix\","
    "        \"socket-name\": \"/first/dhcp6/socket\""
    "      }"
    "    }"
    "  }"
    "}";

/// @brief test fixture class for testing NetconfController class.
///
/// This class derives from DControllerTest and wraps NetconfController. Much
/// of the underlying functionality is in the DControllerBase class which
/// has extensive set of unit tests that are independent from Netconf.
class NetconfControllerTest : public DControllerTest {
public:
    /// @brief Constructor.
    NetconfControllerTest()
        : DControllerTest(NetconfController::instance) {
    }

    /// @brief Returns pointer to NetconfProcess instance.
    NetconfProcessPtr getNetconfProcess() {
        return (boost::dynamic_pointer_cast<NetconfProcess>(getProcess()));
    }

    /// @brief Returns pointer to NetconfCfgMgr instance for a process.
    NetconfCfgMgrPtr getNetconfCfgMgr() {
        NetconfCfgMgrPtr p;
        if (getNetconfProcess()) {
            p = getNetconfProcess()->getNetconfCfgMgr();
        }
        return (p);
    }

    /// @brief Returns a pointer to the configuration context.
    NetconfConfigPtr getNetconfConfig() {
        NetconfConfigPtr p;
        if (getNetconfCfgMgr()) {
            p = getNetconfCfgMgr()->getNetconfConfig();
        }
        return (p);
    }
};  // NetconfControllerTest

// Basic Controller instantiation testing.
// Verifies that the controller singleton gets created and that the
// basic derivation from the base class is intact.
TEST_F(NetconfControllerTest, basicInstanceTesting) {<--- syntax error
    // Verify the singleton instance can be fetched and that
    // it has the correct type.
    DControllerBasePtr& controller = DControllerTest::getController();
    ASSERT_TRUE(controller);
    ASSERT_NO_THROW_LOG(boost::dynamic_pointer_cast<NetconfController>(controller));

    // Verify that controller's app name is correct.
    EXPECT_TRUE(checkAppName(NetconfController::netconf_app_name_));

    // Verify that controller's bin name is correct.
    EXPECT_TRUE(checkBinName(NetconfController::netconf_bin_name_));

    // Verify that controller's IOService exists.
    EXPECT_TRUE(checkIOService());

    // Verify that the Process does NOT exist.
    EXPECT_FALSE(checkProcess());
}

// Tests basic command line processing.
// Verifies that:
// 1. Standard command line options are supported.
// 2. Invalid options are detected.
TEST_F(NetconfControllerTest, commandLineArgs) {
    char* argv[] = { const_cast<char*>("progName"),
                     const_cast<char*>("-c"),
                     const_cast<char*>(DControllerTest::CFG_TEST_FILE),
                     const_cast<char*>("-d") };
    int argc = 4;

    // Verify that verbose flag is false initially.
    EXPECT_TRUE(checkVerbose(false));

    // Verify that standard options can be parsed without error.
    EXPECT_NO_THROW_LOG(parseArgs(argc, argv));

    // Verify that verbose flag is true.
    EXPECT_TRUE(checkVerbose(true));

    // Verify configuration file name is correct.
    EXPECT_TRUE(checkConfigFileName(DControllerTest::CFG_TEST_FILE));

    // Verify that an unknown option is detected.
    char* argv2[] = { const_cast<char*>("progName"),
                      const_cast<char*>("-x") };
    argc = 2;
    EXPECT_THROW_MSG(parseArgs(argc, argv2), InvalidUsage, "unsupported option: -x");
}

// Tests application process creation and initialization.
// Verifies that the process can be successfully created and initialized.
TEST_F(NetconfControllerTest, initProcessTesting) {
    ASSERT_NO_THROW_LOG(initProcess());
    EXPECT_TRUE(checkProcess());
}

// Tests launch and normal shutdown (stand alone mode).
// This creates an interval timer to generate a normal shutdown and then
// launches with a valid, stand-alone command line and no simulated errors.
TEST_F(NetconfControllerTest, launchNormalShutdown) {
    // Write valid_netconf_config and then run launch() for 200 ms.
    time_duration elapsed_time;
    runWithConfig(valid_netconf_config, 200, elapsed_time);

    // Give a generous margin to accommodate slower test environs.
    EXPECT_TRUE(elapsed_time.total_milliseconds() >= 100 &&
                elapsed_time.total_milliseconds() <= 500);
}

// Tests that the SIGINT triggers a normal shutdown.
TEST_F(NetconfControllerTest, sigintShutdown) {
    // Setup to raise SIGINT in 1 ms.
    TimedSignal sighup(getIOService(), SIGINT, 1);

    // Write valid_netconf_config and then run launch() for a maximum
    // of 500 ms.
    time_duration elapsed_time;
    runWithConfig(valid_netconf_config, 500, elapsed_time);

    // Signaled shutdown should make our elapsed time much smaller than
    // the maximum run time.  Give generous margin to accommodate slow
    // test environs.
    EXPECT_TRUE(elapsed_time.total_milliseconds() < 300);
}

// Tests that the SIGTERM triggers a normal shutdown.
TEST_F(NetconfControllerTest, sigtermShutdown) {
    // Setup to raise SIGTERM in 1 ms.
    TimedSignal sighup(getIOService(), SIGTERM, 1);

    // Write valid_netconf_config and then run launch() for a maximum
    // of 500 ms.
    time_duration elapsed_time;
    runWithConfig(valid_netconf_config, 500, elapsed_time);

    // Signaled shutdown should make our elapsed time much smaller than
    // the maximum run time.  Give generous margin to accommodate slow
    // test environs.
    EXPECT_TRUE(elapsed_time.total_milliseconds() < 300);
}

}