blob: 99f5d36391c5f5108e50b00cb59aeb82dbaceb64 [file] [log] [blame]
Junxiao Shi727ed292014-02-19 23:26:45 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
ashiqopud3ae85d2019-02-17 02:29:55 +00002/*
Mark Theeranantachai195b78a2024-02-14 20:54:44 -05003 * Copyright (c) 2014-2024, Regents of the University of California,
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -08004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Junxiao Shi82e7f582014-09-07 15:15:40 -070024 */
Junxiao Shi727ed292014-02-19 23:26:45 -070025
Davide Pesavento97210d52016-10-14 15:45:48 +020026#ifndef NFD_TESTS_DAEMON_FW_STRATEGY_TESTER_HPP
27#define NFD_TESTS_DAEMON_FW_STRATEGY_TESTER_HPP
Junxiao Shi727ed292014-02-19 23:26:45 -070028
Junxiao Shi727ed292014-02-19 23:26:45 -070029#include "fw/strategy.hpp"
Davide Pesavento3dade002019-03-19 11:29:56 -060030
31#include "tests/daemon/limited-io.hpp"
Junxiao Shi727ed292014-02-19 23:26:45 -070032
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040033namespace nfd::tests {
Davide Pesavento14e71f02019-03-28 17:35:25 -040034
35/** \brief Extends strategy S for unit testing.
Junxiao Shi727ed292014-02-19 23:26:45 -070036 *
Davide Pesavento14e71f02019-03-28 17:35:25 -040037 * Actions invoked by S are recorded but not passed to forwarder.
Junxiao Shi890afe92016-12-15 14:34:34 +000038 *
39 * StrategyTester should be registered into the strategy registry prior to use.
40 * \code
41 * // appears in or included by every .cpp MyStrategyTester is used
Davide Pesavento14e71f02019-03-28 17:35:25 -040042 * using MyStrategyTester = StrategyTester<MyStrategy>;
Junxiao Shi890afe92016-12-15 14:34:34 +000043 *
44 * // appears in only one .cpp
45 * NFD_REGISTER_STRATEGY(MyStrategyTester);
46 * \endcode
Junxiao Shi727ed292014-02-19 23:26:45 -070047 */
48template<typename S>
49class StrategyTester : public S
50{
51public:
Davide Pesavento58091582021-03-05 19:02:48 -050052 using S::S;
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070053
Junxiao Shi890afe92016-12-15 14:34:34 +000054 static Name
55 getStrategyName()
56 {
57 Name name = S::getStrategyName();
58 if (!name.empty() && name[-1].isVersion()) {
59 // insert "tester" before version component
60 name::Component versionComp = name[-1];
61 name = name.getPrefix(-1);
62 name.append("tester");
63 name.append(versionComp);
64 }
65 else {
66 name.append("tester");
67 }
68 return name;
69 }
70
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040071 /** \brief Signal emitted after each action.
Junxiao Shi890afe92016-12-15 14:34:34 +000072 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -070073 signal::Signal<StrategyTester<S>> afterAction;
Junxiao Shi727ed292014-02-19 23:26:45 -070074
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040075 /** \brief Execute f and wait for a number of strategy actions.
Junxiao Shi99540072017-01-27 19:57:33 +000076 * \note The actions may occur either during f() invocation or afterwards.
77 * \return whether expected number of actions have occurred
78 */
Davide Pesavento14e71f02019-03-28 17:35:25 -040079 template<typename F>
Junxiao Shi99540072017-01-27 19:57:33 +000080 bool
Davide Pesavento14e71f02019-03-28 17:35:25 -040081 waitForAction(F&& f, LimitedIo& limitedIo, int nExpectedActions = 1)
Junxiao Shi99540072017-01-27 19:57:33 +000082 {
83 int nActions = 0;
84
85 signal::ScopedConnection conn = afterAction.connect([&] {
86 limitedIo.afterOp();
87 ++nActions;
88 });
89
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040090 std::invoke(std::forward<F>(f));
Junxiao Shi99540072017-01-27 19:57:33 +000091
92 if (nActions < nExpectedActions) {
Alexander Afanasyev4400e422021-02-17 11:17:33 -050093 // If strategy doesn't forward anything (e.g., decides not to forward an Interest), the number
Davide Pesavento58091582021-03-05 19:02:48 -050094 // of expected actions should be 0; otherwise the test will get stuck.
Davide Pesavento14e71f02019-03-28 17:35:25 -040095 return limitedIo.run(nExpectedActions - nActions, LimitedIo::UNLIMITED_TIME) == LimitedIo::EXCEED_OPS;
Junxiao Shi99540072017-01-27 19:57:33 +000096 }
97 return nActions == nExpectedActions;
98 }
99
Junxiao Shi727ed292014-02-19 23:26:45 -0700100protected:
Eric Newberry2377ada2020-09-28 22:40:14 -0700101 pit::OutRecord*
Mark Theeranantachai195b78a2024-02-14 20:54:44 -0500102 sendInterest(const Interest& interest, Face& egress, const shared_ptr<pit::Entry>& pitEntry) override
Junxiao Shib9420cf2016-08-13 04:38:52 +0000103 {
Teng Liangebc20f62020-06-23 16:55:20 -0700104 sendInterestHistory.push_back({pitEntry->getInterest(), egress.getId(), interest});
Eric Newberry2377ada2020-09-28 22:40:14 -0700105 auto it = pitEntry->insertOrUpdateOutRecord(egress, interest);
106 BOOST_ASSERT(it != pitEntry->out_end());
Junxiao Shib9420cf2016-08-13 04:38:52 +0000107 afterAction();
Eric Newberry2377ada2020-09-28 22:40:14 -0700108 return &*it;
Junxiao Shib9420cf2016-08-13 04:38:52 +0000109 }
Junxiao Shi727ed292014-02-19 23:26:45 -0700110
Junxiao Shi890afe92016-12-15 14:34:34 +0000111 void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000112 rejectPendingInterest(const shared_ptr<pit::Entry>& pitEntry) override
113 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000114 rejectPendingInterestHistory.push_back({pitEntry->getInterest()});
Junxiao Shib9420cf2016-08-13 04:38:52 +0000115 afterAction();
116 }
Junxiao Shi727ed292014-02-19 23:26:45 -0700117
Eric Newberry2377ada2020-09-28 22:40:14 -0700118 bool
Mark Theeranantachai195b78a2024-02-14 20:54:44 -0500119 sendNack(const lp::NackHeader& header, Face& egress, const shared_ptr<pit::Entry>& pitEntry) override
Junxiao Shib9420cf2016-08-13 04:38:52 +0000120 {
Teng Liangebc20f62020-06-23 16:55:20 -0700121 sendNackHistory.push_back({pitEntry->getInterest(), egress.getId(), header});
Davide Pesavento4d2e7882024-02-15 23:00:21 -0500122 auto it = pitEntry->getInRecord(egress);
123 if (it != pitEntry->in_end()) {
124 pitEntry->deleteInRecord(it);
125 }
Junxiao Shib9420cf2016-08-13 04:38:52 +0000126 afterAction();
Eric Newberry2377ada2020-09-28 22:40:14 -0700127 return true;
Junxiao Shib9420cf2016-08-13 04:38:52 +0000128 }
Junxiao Shi727ed292014-02-19 23:26:45 -0700129
Mark Theeranantachai195b78a2024-02-14 20:54:44 -0500130 bool
131 sendNack(const lp::Nack& nack, Face& egress) override
132 {
133 sendNackHistory.push_back({nack.getInterest(), egress.getId(), nack.getHeader()});
134 afterAction();
135 return true;
136 }
137
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700138public:
139 struct SendInterestArgs
140 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000141 Interest pitInterest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700142 FaceId outFaceId;
Junxiao Shic5f651f2016-11-17 22:58:12 +0000143 Interest interest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700144 };
145 std::vector<SendInterestArgs> sendInterestHistory;
146
147 struct RejectPendingInterestArgs
148 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000149 Interest pitInterest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700150 };
151 std::vector<RejectPendingInterestArgs> rejectPendingInterestHistory;
152
153 struct SendNackArgs
154 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000155 Interest pitInterest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700156 FaceId outFaceId;
157 lp::NackHeader header;
158 };
159 std::vector<SendNackArgs> sendNackHistory;
Junxiao Shi727ed292014-02-19 23:26:45 -0700160};
161
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400162} // namespace nfd::tests
Junxiao Shi727ed292014-02-19 23:26:45 -0700163
Davide Pesavento97210d52016-10-14 15:45:48 +0200164#endif // NFD_TESTS_DAEMON_FW_STRATEGY_TESTER_HPP