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
// Copyright (C) 2013-2021 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/.

#ifndef COMMON_HOOKS_TEST_CLASS_H
#define COMMON_HOOKS_TEST_CLASS_H

#include <hooks/callout_handle.h>
#include <hooks/callout_manager.h>
#include <hooks/server_hooks.h>
#include <hooks/tests/marker_file.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

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

/// @brief Common hooks test class
///
/// This class is a shared parent of the test fixture class in the tests of the
/// higher-level hooks classes (LibraryManager, LibraryManagerCollection and
/// HooksManager).  It
///
/// - sets the ServerHooks object with three hooks and stores their
///   indexes.
/// - executes the callouts (which are assumed to perform a calculation)
///   and checks the results.

class HooksCommonTestClass {
public:
    /// @brief Constructor
    HooksCommonTestClass() {

        // Set up the server hooks.  ServerHooks is a singleton, so we reset it
        // between each test.
        isc::hooks::ServerHooks& hooks =
            isc::hooks::ServerHooks::getServerHooks();
        hooks.reset();
        hookpt_one_index_ = hooks.registerHook("hookpt_one");
        hookpt_two_index_ = hooks.registerHook("hookpt_two");
        hookpt_three_index_ = hooks.registerHook("hookpt_three");
    }

    /// @brief Call callouts test
    ///
    /// All of the loaded libraries for which callouts are called register four
    /// callouts: a context_create callout and three callouts that are attached
    /// to hooks hookpt_one, hookpt_two and hookpt_three.  These four callouts,
    /// executed in sequence, perform a series of calculations. Data is passed
    /// between callouts in the argument list, in a variable named "result".
    ///
    /// context_create initializes the calculation by setting a seed
    /// value, called r0 here.  This value is dependent on the library being
    /// loaded.  Prior to that, the argument "result" is initialized to -1,
    /// the purpose being to avoid exceptions when running this test with no
    /// libraries loaded.
    ///
    /// Callout hookpt_one is passed a value d1 and performs a simple arithmetic
    /// operation on it and r0 yielding a result r1.  Hence we can say that
    /// @f[ r1 = hookpt_one(r0, d1) @f]
    ///
    /// Callout hookpt_two is passed a value d2 and performs another simple
    /// arithmetic operation on it and d2, yielding r2, i.e.
    /// @f[ r2 = hookpt_two(d1, d2) @f]
    ///
    /// hookpt_three does a similar operation giving
    /// @f[ r3 = hookpt_three(r2, d3) @f].
    ///
    /// The details of the operations hookpt_one, hookpt_two and hookpt_three
    /// depend on the library, so the results obtained not only depend on
    /// the data, but also on the library loaded.  This method is passed both
    /// data and expected results.  It executes the three callouts in sequence,
    /// checking the intermediate and final results.  Only if the expected
    /// library has been loaded correctly and the callouts in it registered
    /// correctly will be the results be as expected.
    ///
    /// It is assumed that callout_manager_ has been set up appropriately.
    ///
    /// @note The CalloutHandle used in the calls is declared locally here.
    ///       The advantage of this (apart from scope reduction) is that on
    ///       exit, it is destroyed.  This removes any references to memory
    ///       allocated by loaded libraries while they are still loaded.
    ///
    /// @param manager CalloutManager to use for the test
    /// @param r0...r3, d1..d3 Data (dN) and expected results (rN) - both
    ///        intermediate and final.  The arguments are ordered so that they
    ///        appear in the argument list in the order they are used.
    void executeCallCallouts(
            const boost::shared_ptr<isc::hooks::CalloutManager>& manager,
            int r0, int d1, int r1, int d2, int r2, int d3, int r3) {
        static const char* COMMON_TEXT = " callout returned the wrong value";
        static const char* RESULT = "result";

        int result;

        // Set up a callout handle for the calls.
        isc::hooks::CalloutHandle handle(manager);

        // Initialize the argument RESULT.  This simplifies testing by
        // eliminating the generation of an exception when we try the unload
        // test.  In that case, RESULT is unchanged.
        handle.setArgument(RESULT, -1);

        // Seed the calculation.
        manager->callCallouts(isc::hooks::ServerHooks::CONTEXT_CREATE, handle);
        handle.getArgument(RESULT, result);
        EXPECT_EQ(r0, result) << "context_create" << COMMON_TEXT;

        // Perform the first calculation.
        handle.setArgument("data_1", d1);
        manager->callCallouts(hookpt_one_index_, handle);
        handle.getArgument(RESULT, result);
        EXPECT_EQ(r1, result) << "hookpt_one" << COMMON_TEXT;

        // ... the second ...
        handle.setArgument("data_2", d2);
        manager->callCallouts(hookpt_two_index_, handle);
        handle.getArgument(RESULT, result);
        EXPECT_EQ(r2, result) << "hookpt_two" << COMMON_TEXT;

        // ... and the third.
        handle.setArgument("data_3", d3);
        manager->callCallouts(hookpt_three_index_, handle);
        handle.getArgument(RESULT, result);
        EXPECT_EQ(r3, result) << "hookpt_three" << COMMON_TEXT;
    }

    /// @brief Call command handlers test.
    ///
    /// This test is similar to @c executeCallCallouts but it uses
    /// @ref CalloutManager::callCommandHandlers to execute the command
    /// handlers for the following commands: 'command-one' and 'command-two'.
    ///
    /// @param manager CalloutManager to use for the test
    /// @param r1..r2, d1..d2 Data (dN) and expected results (rN).
    void executeCallCommandHandlers(
             const boost::shared_ptr<isc::hooks::CalloutManager>& manager,
             int d1, int r1, int d2, int r2) {
        static const char* COMMON_TEXT = " command handler returned the wrong value";
        static const char* RESULT = "result";

        int result;

        // Set up a callout handle for the calls.
        isc::hooks::CalloutHandle handle(manager);

        // Initialize the argument RESULT.  This simplifies testing by
        // eliminating the generation of an exception when we try the unload
        // test.  In that case, RESULT is unchanged.
        handle.setArgument(RESULT, -1);

        // Perform the first calculation: it should assign the data to the
        // result.
        handle.setArgument("data_1", d1);
        manager->callCommandHandlers("command-one", handle);
        handle.getArgument(RESULT, result);
        EXPECT_EQ(r1, result) << "command-one" << COMMON_TEXT;

        // Perform the second calculation: it should multiply the data by 10
        // and return in the result.
        handle.setArgument("data_2", d2);
        manager->callCommandHandlers("command-two", handle);
        handle.getArgument(RESULT, result);
        EXPECT_EQ(r2, result) << "command-two" << COMMON_TEXT;
    }


    /// Hook indexes.  These are are made public for ease of reference.
    int hookpt_one_index_;
    int hookpt_two_index_;
    int hookpt_three_index_;
};

#endif // COMMON_HOOKS_TEST_CLASS_H