blob: f2ac93d22611c203680c4e42a8eee161df2a679a [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/*
3 * Copyright (c) 2014-2019, 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
33namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080034namespace fw {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070035namespace tests {
Junxiao Shi727ed292014-02-19 23:26:45 -070036
Junxiao Shi5e5e4452015-09-24 16:56:52 -070037/** \brief extends strategy S for unit testing
Junxiao Shi727ed292014-02-19 23:26:45 -070038 *
39 * Actions invoked by S are recorded but not passed to forwarder
Junxiao Shi890afe92016-12-15 14:34:34 +000040 *
41 * StrategyTester should be registered into the strategy registry prior to use.
42 * \code
43 * // appears in or included by every .cpp MyStrategyTester is used
44 * typedef StrategyTester<MyStrategy> MyStrategyTester;
45 *
46 * // appears in only one .cpp
47 * NFD_REGISTER_STRATEGY(MyStrategyTester);
48 * \endcode
Junxiao Shi727ed292014-02-19 23:26:45 -070049 */
50template<typename S>
51class StrategyTester : public S
52{
53public:
54 explicit
Junxiao Shi890afe92016-12-15 14:34:34 +000055 StrategyTester(Forwarder& forwarder, const Name& name = getStrategyName())
56 : S(forwarder, name)
Junxiao Shi727ed292014-02-19 23:26:45 -070057 {
58 }
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070059
Junxiao Shi890afe92016-12-15 14:34:34 +000060 static Name
61 getStrategyName()
62 {
63 Name name = S::getStrategyName();
64 if (!name.empty() && name[-1].isVersion()) {
65 // insert "tester" before version component
66 name::Component versionComp = name[-1];
67 name = name.getPrefix(-1);
68 name.append("tester");
69 name.append(versionComp);
70 }
71 else {
72 name.append("tester");
73 }
74 return name;
75 }
76
77 /** \brief signal emitted after each Action
78 */
Junxiao Shi5e5e4452015-09-24 16:56:52 -070079 signal::Signal<StrategyTester<S>> afterAction;
Junxiao Shi727ed292014-02-19 23:26:45 -070080
Junxiao Shi99540072017-01-27 19:57:33 +000081 /** \brief execute f and wait for a number of strategy actions
82 * \note The actions may occur either during f() invocation or afterwards.
83 * \return whether expected number of actions have occurred
84 */
85 bool
86 waitForAction(const std::function<void()>& f,
87 nfd::tests::LimitedIo& limitedIo, int nExpectedActions = 1)
88 {
89 int nActions = 0;
90
91 signal::ScopedConnection conn = afterAction.connect([&] {
92 limitedIo.afterOp();
93 ++nActions;
94 });
95
96 f();
97
98 if (nActions < nExpectedActions) {
99 // A correctly implemented strategy is required to invoke reject pending Interest action if it
100 // decides to not forward an Interest. If a test case is stuck in the call below, check that
101 // rejectPendingInterest is invoked under proper condition.
102 return limitedIo.run(nExpectedActions - nActions, nfd::tests::LimitedIo::UNLIMITED_TIME) ==
103 nfd::tests::LimitedIo::EXCEED_OPS;
104 }
105 return nActions == nExpectedActions;
106 }
107
Junxiao Shi727ed292014-02-19 23:26:45 -0700108protected:
Junxiao Shi890afe92016-12-15 14:34:34 +0000109 void
ashiqopuc7079482019-02-20 05:34:37 +0000110 sendInterest(const shared_ptr<pit::Entry>& pitEntry, const FaceEndpoint& egress,
Junxiao Shic5f651f2016-11-17 22:58:12 +0000111 const Interest& interest) override
Junxiao Shib9420cf2016-08-13 04:38:52 +0000112 {
ashiqopuc7079482019-02-20 05:34:37 +0000113 sendInterestHistory.push_back({pitEntry->getInterest(), egress.face.getId(), interest});
114 pitEntry->insertOrUpdateOutRecord(egress.face, egress.endpoint, interest);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000115 afterAction();
116 }
Junxiao Shi727ed292014-02-19 23:26:45 -0700117
Junxiao Shi890afe92016-12-15 14:34:34 +0000118 void
Junxiao Shib9420cf2016-08-13 04:38:52 +0000119 rejectPendingInterest(const shared_ptr<pit::Entry>& pitEntry) override
120 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000121 rejectPendingInterestHistory.push_back({pitEntry->getInterest()});
Junxiao Shib9420cf2016-08-13 04:38:52 +0000122 afterAction();
123 }
Junxiao Shi727ed292014-02-19 23:26:45 -0700124
Junxiao Shi890afe92016-12-15 14:34:34 +0000125 void
ashiqopuc7079482019-02-20 05:34:37 +0000126 sendNack(const shared_ptr<pit::Entry>& pitEntry, const FaceEndpoint& egress,
Junxiao Shib9420cf2016-08-13 04:38:52 +0000127 const lp::NackHeader& header) override
128 {
ashiqopuc7079482019-02-20 05:34:37 +0000129 sendNackHistory.push_back({pitEntry->getInterest(), egress.face.getId(), header});
130 pitEntry->deleteInRecord(egress.face, egress.endpoint);
Junxiao Shib9420cf2016-08-13 04:38:52 +0000131 afterAction();
132 }
Junxiao Shi727ed292014-02-19 23:26:45 -0700133
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700134public:
135 struct SendInterestArgs
136 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000137 Interest pitInterest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700138 FaceId outFaceId;
Junxiao Shic5f651f2016-11-17 22:58:12 +0000139 Interest interest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700140 };
141 std::vector<SendInterestArgs> sendInterestHistory;
142
143 struct RejectPendingInterestArgs
144 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000145 Interest pitInterest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700146 };
147 std::vector<RejectPendingInterestArgs> rejectPendingInterestHistory;
148
149 struct SendNackArgs
150 {
Junxiao Shi8ff0a862016-08-13 04:50:50 +0000151 Interest pitInterest;
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700152 FaceId outFaceId;
153 lp::NackHeader header;
154 };
155 std::vector<SendNackArgs> sendNackHistory;
Junxiao Shi727ed292014-02-19 23:26:45 -0700156};
157
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700158} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800159} // namespace fw
Junxiao Shi727ed292014-02-19 23:26:45 -0700160} // namespace nfd
161
Davide Pesavento97210d52016-10-14 15:45:48 +0200162#endif // NFD_TESTS_DAEMON_FW_STRATEGY_TESTER_HPP