blob: 954cef2ea56a72abb13a72b62359fcccce356002 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2023, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_TESTS_DAEMON_MGMT_MANAGER_COMMON_FIXTURE_HPP
#define NFD_TESTS_DAEMON_MGMT_MANAGER_COMMON_FIXTURE_HPP
#include "mgmt/manager-base.hpp"
#include "fw/forwarder.hpp"
#include "tests/test-common.hpp"
#include "tests/key-chain-fixture.hpp"
#include "tests/daemon/global-io-fixture.hpp"
#include <ndn-cxx/security/interest-signer.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
namespace nfd::tests {
/**
* \brief A fixture that wraps an InterestSigner.
*/
class InterestSignerFixture : public GlobalIoTimeFixture, public KeyChainFixture
{
protected:
InterestSignerFixture();
/**
* \brief Create a ControlCommand request.
* \param commandName Command name including prefix, such as `/localhost/nfd/fib/add-nexthop`
* \param params Command parameters
* \param format Signed Interest format
* \param identity Signing identity
*/
Interest
makeControlCommandRequest(Name commandName,
const ControlParameters& params = {},
ndn::security::SignedInterestFormat format = ndn::security::SignedInterestFormat::V03,
const Name& identity = DEFAULT_COMMAND_SIGNER_IDENTITY);
protected:
static inline const Name DEFAULT_COMMAND_SIGNER_IDENTITY{"/InterestSignerFixture-identity"};
private:
ndn::security::InterestSigner m_signer{m_keyChain};
};
/**
* @brief A collection of common functions shared by all manager's test fixtures.
*/
class ManagerCommonFixture : public InterestSignerFixture
{
public: // initialize
/**
* @brief Add `/localhost/nfd` as a top prefix to the dispatcher.
*
* Afterwards, advanceClocks() is called to ensure all added filters take effect.
*/
void
setTopPrefix();
public: // test
/**
* @brief Cause management to receive an Interest.
*
* call DummyClientFace::receive to receive Interest and then call advanceClocks to ensure
* the Interest dispatched
*
* @param interest the Interest to receive
*/
void
receiveInterest(const Interest& interest);
public: // verify
static ControlResponse
makeResponse(uint32_t code, const std::string& text, const ControlParameters& parameters);
enum class CheckResponseResult {
OK,
OUT_OF_BOUNDARY,
WRONG_NAME,
WRONG_CONTENT_TYPE,
INVALID_RESPONSE,
WRONG_CODE,
WRONG_TEXT,
WRONG_BODY_SIZE,
WRONG_BODY_VALUE
};
/**
* @brief Check a specified response data with the expected ControlResponse.
*
* @param idx the index of the specified Data in m_responses
* @param expectedDataName the expected name of this Data
* @param expectedResponse the expected ControlResponse
* @param expectedContentType the expected content type of this Data, use -1 to skip this check
*
* @retval OK the response at the specified index can be decoded from the response data,
* and its code, text and response body are all matched with the expected response
* @retval OUT_OF_BOUNDARY the specified index out of boundary
* @retval WRONG_NAME the name of the specified response data does not match
* @retval WRONG_CONTENT_TYPE the content type of the specified response data does not match
* @retval INVALID_RESPONSE the data name matches but it fails in decoding a ControlResponse from
* the content of the specified response data
* @retval WRONG_CODE a valid ControlResponse can be decoded but has a wrong code
* @retval WRONG_TEXT a valid ControlResponse can be decoded but has a wrong text
* @retval WRONG_BODY_SIZE the body size of decoded ControlResponse does not match
* @retval WRONT_BODY_VALUE the body value of decoded ControlResponse does not match
*/
CheckResponseResult
checkResponse(size_t idx,
const Name& expectedName,
const ControlResponse& expectedResponse,
int expectedContentType = -1);
/**
* @brief Concatenate specified response Data into a single block.
*
* @param startIndex the start index in m_responses
* @param nResponses the number of response to concatenate
*
* @return the generated block
*/
Block
concatenateResponses(size_t startIndex = 0, size_t nResponses = 0);
protected:
ndn::DummyClientFace m_face{g_io, m_keyChain, {true, true}};
Dispatcher m_dispatcher{m_face, m_keyChain};
std::vector<Data>& m_responses{m_face.sentData};
};
std::ostream&
operator<<(std::ostream& os, ManagerCommonFixture::CheckResponseResult result);
class ManagerFixtureWithAuthenticator : public ManagerCommonFixture
{
public:
/** \brief Grant m_identityName privilege to sign commands for the management module.
*/
void
setPrivilege(const std::string& privilege);
protected:
FaceTable m_faceTable;
Forwarder m_forwarder{m_faceTable};
shared_ptr<CommandAuthenticator> m_authenticator = CommandAuthenticator::create();
};
class CommandSuccess
{
public:
static ControlResponse
getExpected()
{
return ControlResponse()
.setCode(200)
.setText("OK");
}
};
template<auto CODE>
class CommandFailure
{
public:
static ControlResponse
getExpected()
{
return ControlResponse()
.setCode(CODE);
// error description should not be checked
}
};
} // namespace nfd::tests
#endif // NFD_TESTS_DAEMON_MGMT_MANAGER_COMMON_FIXTURE_HPP