blob: 6b1cd203d8f4a40c0775b2613cf84ba416b4f9be [file] [log] [blame]
Junxiao Shi38f4ce92016-08-04 10:01:52 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento87fc0f82018-04-11 23:43:51 -04002/*
Davide Pesavento3dade002019-03-19 11:29:56 -06003 * Copyright (c) 2014-2019, Regents of the University of California,
Junxiao Shi38f4ce92016-08-04 10:01:52 +00004 * 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.
10 *
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/>.
24 */
25
Junxiao Shi331ade72016-08-19 14:07:19 +000026#include "nfdc/status-report.hpp"
Junxiao Shi38f4ce92016-08-04 10:01:52 +000027
Junxiao Shi1f481fa2017-01-26 15:14:43 +000028#include "status-fixture.hpp"
Junxiao Shi38f4ce92016-08-04 10:01:52 +000029
30namespace nfd {
31namespace tools {
Junxiao Shi331ade72016-08-19 14:07:19 +000032namespace nfdc {
Junxiao Shi38f4ce92016-08-04 10:01:52 +000033namespace tests {
34
35const std::string STATUS_XML = stripXmlSpaces(R"XML(
36 <?xml version="1.0"?>
37 <nfdStatus xmlns="ndn:/localhost/nfd/status/1">
38 <module1/>
39 <module2/>
40 </nfdStatus>
41)XML");
42
43const std::string STATUS_TEXT = std::string(R"TEXT(
44module1
45module2
46)TEXT").substr(1);
47
48class DummyModule : public Module
49{
50public:
Davide Pesavento3dade002019-03-19 11:29:56 -060051 DummyModule(const std::string& moduleName, boost::asio::io_service& io)
Junxiao Shi38f4ce92016-08-04 10:01:52 +000052 : m_moduleName(moduleName)
Davide Pesavento3dade002019-03-19 11:29:56 -060053 , m_scheduler(io)
Junxiao Shi38f4ce92016-08-04 10:01:52 +000054 , m_res(0)
55 , m_delay(time::milliseconds(1))
56 {
57 }
58
59 /** \brief cause fetchStatus to succeed or fail
60 * \param res zero to succeed, non-zero to fail with specific code
61 * \param delay duration from fetchStatus invocation to succeed or fail; must be positive
62 */
63 void
64 setResult(uint32_t res, time::nanoseconds delay)
65 {
66 BOOST_ASSERT(delay > time::nanoseconds::zero());
67 m_res = res;
68 m_delay = delay;
69 }
70
Davide Pesavento87fc0f82018-04-11 23:43:51 -040071 void
Davide Pesavento3dade002019-03-19 11:29:56 -060072 fetchStatus(Controller&,
Davide Pesavento87fc0f82018-04-11 23:43:51 -040073 const std::function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +000074 const Controller::DatasetFailCallback& onFailure,
Davide Pesavento3dade002019-03-19 11:29:56 -060075 const CommandOptions&) final
Junxiao Shi38f4ce92016-08-04 10:01:52 +000076 {
77 ++nFetchStatusCalls;
Davide Pesavento3dade002019-03-19 11:29:56 -060078 m_scheduler.schedule(m_delay, [=] {
Junxiao Shi38f4ce92016-08-04 10:01:52 +000079 if (m_res == 0) {
80 onSuccess();
81 }
82 else {
83 onFailure(m_res, m_moduleName + " fails with code " + to_string(m_res));
84 }
85 });
86 }
87
Davide Pesavento87fc0f82018-04-11 23:43:51 -040088 void
89 formatStatusXml(std::ostream& os) const final
Junxiao Shi38f4ce92016-08-04 10:01:52 +000090 {
91 os << '<' << m_moduleName << "/>";
92 }
93
Davide Pesavento87fc0f82018-04-11 23:43:51 -040094 void
95 formatStatusText(std::ostream& os) const final
Junxiao Shi38f4ce92016-08-04 10:01:52 +000096 {
97 os << m_moduleName << '\n';
98 }
99
100public:
101 int nFetchStatusCalls = 0;
102
103private:
104 std::string m_moduleName;
Davide Pesavento3dade002019-03-19 11:29:56 -0600105 Scheduler m_scheduler;
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000106 uint32_t m_res;
107 time::nanoseconds m_delay;
108};
109
110class StatusReportTester : public StatusReport
111{
112private:
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400113 void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000114 processEvents(Face&) override
115 {
116 processEventsFunc();
117 }
118
119public:
120 std::function<void()> processEventsFunc;
121};
122
Davide Pesavento1d12d2f2019-03-22 12:44:14 -0400123class StatusReportModulesFixture : public UnitTestTimeFixture, public KeyChainFixture
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000124{
125protected:
126 StatusReportModulesFixture()
127 : face(g_io, m_keyChain)
128 , controller(face, m_keyChain, validator)
129 , res(0)
130 {
131 }
132
133 DummyModule&
134 addModule(const std::string& moduleName)
135 {
Davide Pesavento3dade002019-03-19 11:29:56 -0600136 report.sections.push_back(make_unique<DummyModule>(moduleName, g_io));
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000137 return static_cast<DummyModule&>(*report.sections.back());
138 }
139
140 void
141 collect(time::nanoseconds tick, size_t nTicks)
142 {
143 report.processEventsFunc = [=] {
144 this->advanceClocks(tick, nTicks);
145 };
146 res = report.collect(face, m_keyChain, validator, CommandOptions());
147
148 if (res == 0) {
149 statusXml.str("");
150 report.formatXml(statusXml);
151 statusText.str("");
152 report.formatText(statusText);
153 }
154 }
155
156protected:
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000157 ndn::util::DummyClientFace face;
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000158 ValidatorNull validator;
159 Controller controller;
160 StatusReportTester report;
161
162 uint32_t res;
163 output_test_stream statusXml;
164 output_test_stream statusText;
165};
166
167
Junxiao Shi331ade72016-08-19 14:07:19 +0000168BOOST_AUTO_TEST_SUITE(Nfdc)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000169BOOST_FIXTURE_TEST_SUITE(TestStatusReport, StatusReportModulesFixture)
170
171BOOST_AUTO_TEST_CASE(Normal)
172{
173 DummyModule& m1 = addModule("module1");
174 m1.setResult(0, time::milliseconds(10));
175 DummyModule& m2 = addModule("module2");
176 m2.setResult(0, time::milliseconds(20));
177
178 this->collect(time::milliseconds(5), 6);
179
180 BOOST_CHECK_EQUAL(m1.nFetchStatusCalls, 1);
181 BOOST_CHECK_EQUAL(m2.nFetchStatusCalls, 1);
182
183 BOOST_CHECK_EQUAL(res, 0);
184 BOOST_CHECK(statusXml.is_equal(STATUS_XML));
185 BOOST_CHECK(statusText.is_equal(STATUS_TEXT));
186}
187
188BOOST_AUTO_TEST_CASE(Reorder)
189{
190 DummyModule& m1 = addModule("module1");
191 m1.setResult(0, time::milliseconds(20));
192 DummyModule& m2 = addModule("module2");
193 m2.setResult(0, time::milliseconds(10)); // module2 completes earlier than module1
194
195 this->collect(time::milliseconds(5), 6);
196
197 BOOST_CHECK_EQUAL(res, 0);
198 BOOST_CHECK(statusXml.is_equal(STATUS_XML)); // output is still in order
199 BOOST_CHECK(statusText.is_equal(STATUS_TEXT));
200}
201
202BOOST_AUTO_TEST_CASE(Error)
203{
204 DummyModule& m1 = addModule("module1");
205 m1.setResult(0, time::milliseconds(20));
206 DummyModule& m2 = addModule("module2");
207 m2.setResult(500, time::milliseconds(10));
208
209 this->collect(time::milliseconds(5), 6);
210
211 BOOST_CHECK_EQUAL(res, 1000500);
212}
213
Junxiao Shi8c39bf02016-08-28 23:54:13 +0000214BOOST_AUTO_TEST_SUITE_END() // TestStatusReport
Junxiao Shi331ade72016-08-19 14:07:19 +0000215BOOST_AUTO_TEST_SUITE_END() // Nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000216
217} // namespace tests
Junxiao Shi331ade72016-08-19 14:07:19 +0000218} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000219} // namespace tools
220} // namespace nfd