blob: 99d5a2096cf4f072476ac1239d02a770ca395cb6 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi909ffef2017-07-07 22:12:27 +00002/*
Davide Pesavento0f830802018-01-16 23:58:58 -05003 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyev20d2c582014-01-26 15:32:51 -080020 */
21
Alexander Afanasyeve6c65e22015-01-28 19:56:03 -080022#define BOOST_TEST_MODULE ndn-cxx Integrated Tests (Face)
Davide Pesavento7e780642018-11-24 15:51:34 -050023#include "tests/boost-test.hpp"
Alexander Afanasyeve6c65e22015-01-28 19:56:03 -080024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "ndn-cxx/face.hpp"
26#include "ndn-cxx/transport/tcp-transport.hpp"
27#include "ndn-cxx/transport/unix-transport.hpp"
28#include "ndn-cxx/util/scheduler.hpp"
Alexander Afanasyev20d2c582014-01-26 15:32:51 -080029
Davide Pesavento7e780642018-11-24 15:51:34 -050030#include "tests/identity-management-fixture.hpp"
31#include "tests/make-interest-data.hpp"
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070032
Junxiao Shicf9c6bb2016-07-27 02:18:19 +000033#include <stdio.h>
Alexander Afanasyeva54d5a62017-02-11 19:01:34 -080034#include <condition_variable>
Davide Pesavento7e780642018-11-24 15:51:34 -050035#include <mutex>
36#include <thread>
37
Junxiao Shi2bea5c42017-08-14 20:10:32 +000038#include <boost/mpl/vector.hpp>
Junxiao Shicf9c6bb2016-07-27 02:18:19 +000039
Alexander Afanasyev0abb2da2014-01-30 18:07:57 -080040namespace ndn {
Alexander Afanasyev5fc795f2014-10-20 23:06:56 -040041namespace tests {
Alexander Afanasyev20d2c582014-01-26 15:32:51 -080042
Junxiao Shi2bea5c42017-08-14 20:10:32 +000043static Name
44makeVeryLongName(Name prefix = Name())
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070045{
Eric Newberry06690612016-12-27 12:50:15 -070046 for (size_t i = 0; i <= MAX_NDN_PACKET_SIZE / 10; i++) {
Junxiao Shi2bea5c42017-08-14 20:10:32 +000047 prefix.append("0123456789");
48 }
49 return prefix;
50}
51
52static std::string
53executeCommand(const std::string& cmd)
54{
55 std::string output;
56 char buf[256];
57 FILE* pipe = popen(cmd.data(), "r");
58 BOOST_REQUIRE_MESSAGE(pipe != nullptr, "cannot execute '" << cmd << "'");
59 while (fgets(buf, sizeof(buf), pipe) != nullptr) {
60 output += buf;
61 }
62 pclose(pipe);
63 return output;
64}
65
66template<typename TransportType>
67class FaceFixture : public IdentityManagementFixture
68{
69protected:
70 FaceFixture()
71 : face(TransportType::create(""), m_keyChain)
72 , sched(face.getIoService())
73 {
Eric Newberry06690612016-12-27 12:50:15 -070074 }
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -070075
Junxiao Shi2bea5c42017-08-14 20:10:32 +000076 /** \brief Send an Interest from a secondary face
77 * \param delay scheduling delay before sending Interest
78 * \param interest the Interest
79 * \param[out] outcome the response, initially '?', 'D' for Data, 'N' for Nack, 'T' for timeout
80 * \return scheduled event id
81 */
82 EventId
83 sendInterest(time::nanoseconds delay, const Interest& interest, char& outcome)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070084 {
Junxiao Shi2bea5c42017-08-14 20:10:32 +000085 if (face2 == nullptr) {
86 face2 = make_unique<Face>(TransportType::create(""), face.getIoService(), m_keyChain);
87 }
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070088
Junxiao Shi2bea5c42017-08-14 20:10:32 +000089 outcome = '?';
90 return sched.scheduleEvent(delay, [this, interest, &outcome] {
91 face2->expressInterest(interest,
92 [&] (const Interest&, const Data&) { outcome = 'D'; },
93 [&] (const Interest&, const lp::Nack&) { outcome = 'N'; },
94 [&] (const Interest&) { outcome = 'T'; });
95 });
96 }
97
98 EventId
99 sendInterest(time::nanoseconds delay, const Interest& interest)
100 {
101 static char ignoredOutcome;
102 return sendInterest(delay, interest, ignoredOutcome);
103 }
104
105 /** \brief Stop io_service after a delay
106 * \return scheduled event id
107 */
108 EventId
109 terminateAfter(time::nanoseconds delay)
110 {
111 return sched.scheduleEvent(delay, [this] { face.getIoService().stop(); });
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700112 }
Junxiao Shicf9c6bb2016-07-27 02:18:19 +0000113
114protected:
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000115 Face face;
116 Scheduler sched;
117
118 unique_ptr<Face> face2;
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700119};
120
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000121using Transports = boost::mpl::vector<UnixTransport, TcpTransport>;
122
123BOOST_FIXTURE_TEST_SUITE(TestFace, FaceFixture<UnixTransport>)
124
125BOOST_AUTO_TEST_SUITE(Consumer)
126
127BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExpressInterestData, TransportType, Transports, FaceFixture<TransportType>)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700128{
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000129 int nData = 0;
Junxiao Shib55e5d32018-07-18 13:32:00 -0600130 this->face.expressInterest(*makeInterest("/", true),
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000131 [&] (const Interest&, const Data&) { ++nData; },
132 [] (const Interest&, const lp::Nack&) { BOOST_ERROR("unexpected Nack"); },
133 [] (const Interest&) { BOOST_ERROR("unexpected timeout"); });
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700134
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000135 this->face.processEvents();
136 BOOST_CHECK_EQUAL(nData, 1);
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700137}
Alexander Afanasyev90164962014-03-06 08:29:59 +0000138
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000139BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExpressInterestNack, TransportType, Transports, FaceFixture<TransportType>)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700140{
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000141 int nNacks = 0;
Junxiao Shib55e5d32018-07-18 13:32:00 -0600142 this->face.expressInterest(*makeInterest("/localhost/non-existent-should-nack"),
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000143 [] (const Interest&, const Data&) { BOOST_ERROR("unexpected Data"); },
144 [&] (const Interest&, const lp::Nack&) { ++nNacks; },
145 [] (const Interest&) { BOOST_ERROR("unexpected timeout"); });
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700146
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000147 this->face.processEvents();
148 BOOST_CHECK_EQUAL(nNacks, 1);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700149}
150
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000151BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExpressInterestTimeout, TransportType, Transports, FaceFixture<TransportType>)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700152{
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000153 // add route toward null face so Interest would timeout instead of getting Nacked
154 executeCommand("nfdc route add /localhost/non-existent-should-timeout null://");
155 std::this_thread::sleep_for(std::chrono::milliseconds(200)); // wait for FIB update to take effect
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700156
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000157 int nTimeouts = 0;
Junxiao Shib55e5d32018-07-18 13:32:00 -0600158 this->face.expressInterest(*makeInterest("/localhost/non-existent-should-timeout", false, 1_s),
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000159 [] (const Interest&, const Data&) { BOOST_ERROR("unexpected Data"); },
160 [] (const Interest&, const lp::Nack&) { BOOST_ERROR("unexpected Nack"); },
161 [&] (const Interest&) { ++nTimeouts; });
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700162
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000163 this->face.processEvents();
164 BOOST_CHECK_EQUAL(nTimeouts, 1);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700165}
166
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000167BOOST_FIXTURE_TEST_CASE_TEMPLATE(OversizedInterest, TransportType, Transports, FaceFixture<TransportType>)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700168{
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000169 BOOST_CHECK_THROW(do {
Junxiao Shib55e5d32018-07-18 13:32:00 -0600170 this->face.expressInterest(*makeInterest(makeVeryLongName()), nullptr, nullptr, nullptr);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000171 this->face.processEvents();
172 } while (false), Face::OversizedPacketError);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700173}
Alexander Afanasyev5fc795f2014-10-20 23:06:56 -0400174
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000175BOOST_AUTO_TEST_SUITE_END() // Consumer
176
177BOOST_AUTO_TEST_SUITE(Producer)
178
179BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegisterUnregisterPrefix, TransportType, Transports, FaceFixture<TransportType>)
180{
Davide Pesavento0f830802018-01-16 23:58:58 -0500181 this->terminateAfter(4_s);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000182
183 int nRegSuccess = 0, nUnregSuccess = 0;
184 auto id = this->face.registerPrefix("/Hello/World",
185 [&] (const Name&) { ++nRegSuccess; },
186 [] (const Name&, const std::string& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
187
Davide Pesavento0f830802018-01-16 23:58:58 -0500188 this->sched.scheduleEvent(1_s, [&nRegSuccess] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000189 BOOST_CHECK_EQUAL(nRegSuccess, 1);
190 std::string output = executeCommand("nfdc route list | grep /Hello/World");
191 BOOST_CHECK(!output.empty());
192 });
193
Davide Pesavento0f830802018-01-16 23:58:58 -0500194 this->sched.scheduleEvent(2_s, [this, id, &nUnregSuccess] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000195 this->face.unregisterPrefix(id,
196 [&] { ++nUnregSuccess; },
197 [] (const std::string& msg) { BOOST_ERROR("unexpected unregister prefix failure: " << msg); });
198 });
199
Davide Pesavento0f830802018-01-16 23:58:58 -0500200 this->sched.scheduleEvent(3_s, [&nUnregSuccess] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000201 BOOST_CHECK_EQUAL(nUnregSuccess, 1);
202
203 // Boost.Test would fail if a child process exits with non-zero. http://stackoverflow.com/q/5325202
204 std::string output = executeCommand("nfdc route list | grep /Hello/World || true");
205 BOOST_CHECK(output.empty());
206 });
207
208 this->face.processEvents();
209}
210
211BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegularFilter, TransportType, Transports, FaceFixture<TransportType>)
212{
Davide Pesavento0f830802018-01-16 23:58:58 -0500213 this->terminateAfter(2_s);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000214
215 int nInterests1 = 0, nRegSuccess1 = 0, nRegSuccess2 = 0;
216 this->face.setInterestFilter("/Hello/World",
217 [&] (const InterestFilter&, const Interest&) { ++nInterests1; },
218 [&] (const Name&) { ++nRegSuccess1; },
219 [] (const Name&, const std::string& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
220 this->face.setInterestFilter("/Los/Angeles/Lakers",
221 [&] (const InterestFilter&, const Interest&) { BOOST_ERROR("unexpected Interest"); },
222 [&] (const Name&) { ++nRegSuccess2; },
223 [] (const Name&, const std::string& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
224
Davide Pesavento0f830802018-01-16 23:58:58 -0500225 this->sched.scheduleEvent(500_ms, [] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000226 std::string output = executeCommand("nfdc route list | grep /Hello/World");
227 BOOST_CHECK(!output.empty());
228 });
229
230 char interestOutcome;
Junxiao Shib55e5d32018-07-18 13:32:00 -0600231 this->sendInterest(1_s, *makeInterest("/Hello/World/regular", false, 50_ms), interestOutcome);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000232
233 this->face.processEvents();
234 BOOST_CHECK_EQUAL(interestOutcome, 'T');
235 BOOST_CHECK_EQUAL(nInterests1, 1);
236 BOOST_CHECK_EQUAL(nRegSuccess1, 1);
237 BOOST_CHECK_EQUAL(nRegSuccess2, 1);
238}
239
240BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegexFilter, TransportType, Transports, FaceFixture<TransportType>)
241{
Davide Pesavento0f830802018-01-16 23:58:58 -0500242 this->terminateAfter(2_s);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000243
244 int nRegSuccess = 0;
245 std::set<Name> receivedInterests;
246 this->face.setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
247 [&] (const InterestFilter&, const Interest& interest) { receivedInterests.insert(interest.getName()); },
248 [&] (const Name&) { ++nRegSuccess; },
249 [] (const Name&, const std::string& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
250
Davide Pesavento0f830802018-01-16 23:58:58 -0500251 this->sched.scheduleEvent(700_ms, [] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000252 std::string output = executeCommand("nfdc route list | grep /Hello/World");
253 BOOST_CHECK(!output.empty());
254 });
255
Junxiao Shib55e5d32018-07-18 13:32:00 -0600256 this->sendInterest(200_ms, *makeInterest("/Hello/World/a", false, 50_ms));
257 this->sendInterest(300_ms, *makeInterest("/Hello/World/a/b", false, 50_ms));
258 this->sendInterest(400_ms, *makeInterest("/Hello/World/a/b/c", false, 50_ms));
259 this->sendInterest(500_ms, *makeInterest("/Hello/World/a/b/d", false, 50_ms));
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000260
261 this->face.processEvents();
262 BOOST_CHECK_EQUAL(nRegSuccess, 1);
263 std::set<Name> expectedInterests{"/Hello/World/a/b", "/Hello/World/a/b/c"};
264 BOOST_CHECK_EQUAL_COLLECTIONS(receivedInterests.begin(), receivedInterests.end(),
265 expectedInterests.begin(), expectedInterests.end());
266}
267
268BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegexFilterNoRegister, TransportType, Transports, FaceFixture<TransportType>)
269{
Davide Pesavento0f830802018-01-16 23:58:58 -0500270 this->terminateAfter(2_s);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000271
272 // no Interest shall arrive because prefix isn't registered in forwarder
273 this->face.setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
274 [&] (const InterestFilter&, const Interest& interest) { BOOST_ERROR("unexpected Interest"); });
275
Davide Pesavento0f830802018-01-16 23:58:58 -0500276 this->sched.scheduleEvent(700_ms, [] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000277 // Boost.Test would fail if a child process exits with non-zero. http://stackoverflow.com/q/5325202
278 std::string output = executeCommand("nfdc route list | grep /Hello/World || true");
279 BOOST_CHECK(output.empty());
280 });
281
Junxiao Shib55e5d32018-07-18 13:32:00 -0600282 this->sendInterest(200_ms, *makeInterest("/Hello/World/a", false, 50_ms));
283 this->sendInterest(300_ms, *makeInterest("/Hello/World/a/b", false, 50_ms));
284 this->sendInterest(400_ms, *makeInterest("/Hello/World/a/b/c", false, 50_ms));
285 this->sendInterest(500_ms, *makeInterest("/Hello/World/a/b/d", false, 50_ms));
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000286
287 this->face.processEvents();
288}
289
290BOOST_FIXTURE_TEST_CASE_TEMPLATE(PutDataNack, TransportType, Transports, FaceFixture<TransportType>)
291{
Davide Pesavento0f830802018-01-16 23:58:58 -0500292 this->terminateAfter(2_s);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000293
294 this->face.setInterestFilter("/Hello/World",
295 [&] (const InterestFilter&, const Interest& interest) {
296 if (interest.getName().at(2) == name::Component("nack")) {
297 this->face.put(makeNack(interest, lp::NackReason::NO_ROUTE));
298 }
299 else {
300 this->face.put(*makeData(interest.getName()));
301 }
302 },
303 nullptr,
304 [] (const Name&, const std::string& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
305
306 char outcome1, outcome2;
Junxiao Shib55e5d32018-07-18 13:32:00 -0600307 this->sendInterest(700_ms, *makeInterest("/Hello/World/data", false, 50_ms), outcome1);
308 this->sendInterest(800_ms, *makeInterest("/Hello/World/nack", false, 50_ms), outcome2);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000309
310 this->face.processEvents();
311 BOOST_CHECK_EQUAL(outcome1, 'D');
312 BOOST_CHECK_EQUAL(outcome2, 'N');
313}
314
315BOOST_FIXTURE_TEST_CASE_TEMPLATE(OversizedData, TransportType, Transports, FaceFixture<TransportType>)
316{
Davide Pesavento0f830802018-01-16 23:58:58 -0500317 this->terminateAfter(2_s);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000318
319 this->face.setInterestFilter("/Hello/World",
320 [&] (const InterestFilter&, const Interest& interest) {
321 this->face.put(*makeData(makeVeryLongName(interest.getName())));
322 },
323 nullptr,
324 [] (const Name&, const std::string& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
325
Junxiao Shib55e5d32018-07-18 13:32:00 -0600326 this->sendInterest(1_s, *makeInterest("/Hello/World/oversized", true, 50_ms));
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000327
328 BOOST_CHECK_THROW(this->face.processEvents(), Face::OversizedPacketError);
329}
330
331BOOST_AUTO_TEST_SUITE_END() // Producer
332
333BOOST_AUTO_TEST_SUITE(IoRoutine)
334
Alexander Afanasyevfba1ac62015-08-26 15:19:13 -0700335BOOST_AUTO_TEST_CASE(ShutdownWhileSendInProgress) // Bug #3136
336{
Junxiao Shib55e5d32018-07-18 13:32:00 -0600337 this->face.expressInterest(*makeInterest("/Hello/World"), nullptr, nullptr, nullptr);
Davide Pesavento0f830802018-01-16 23:58:58 -0500338 this->face.processEvents(1_s);
Alexander Afanasyevfba1ac62015-08-26 15:19:13 -0700339
Junxiao Shib55e5d32018-07-18 13:32:00 -0600340 this->face.expressInterest(*makeInterest("/Bye/World/1"), nullptr, nullptr, nullptr);
341 this->face.expressInterest(*makeInterest("/Bye/World/2"), nullptr, nullptr, nullptr);
342 this->face.expressInterest(*makeInterest("/Bye/World/3"), nullptr, nullptr, nullptr);
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000343 this->face.shutdown();
Alexander Afanasyevfba1ac62015-08-26 15:19:13 -0700344
Davide Pesavento0f830802018-01-16 23:58:58 -0500345 this->face.processEvents(1_s); // should not segfault
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000346 BOOST_CHECK(true);
Alexander Afanasyevfba1ac62015-08-26 15:19:13 -0700347}
348
Alexander Afanasyeve508f142015-09-01 15:14:45 -0700349BOOST_AUTO_TEST_CASE(LargeDelayBetweenFaceConstructorAndProcessEvents) // Bug #2742
350{
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000351 std::this_thread::sleep_for(std::chrono::seconds(5)); // simulate setup workload
Davide Pesavento0f830802018-01-16 23:58:58 -0500352 this->face.processEvents(1_s); // should not throw
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000353 BOOST_CHECK(true);
Alexander Afanasyeve508f142015-09-01 15:14:45 -0700354}
355
Alexander Afanasyeva54d5a62017-02-11 19:01:34 -0800356BOOST_AUTO_TEST_CASE(ProcessEventsBlocksForeverWhenNothingScheduled) // Bug #3957
357{
Alexander Afanasyeva54d5a62017-02-11 19:01:34 -0800358 std::mutex m;
359 std::condition_variable cv;
360 bool processEventsFinished = false;
361
362 std::thread faceThread([&] {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000363 this->face.processEvents();
Alexander Afanasyeva54d5a62017-02-11 19:01:34 -0800364
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000365 processEventsFinished = true;
366 std::lock_guard<std::mutex> lk(m);
367 cv.notify_one();
368 });
Alexander Afanasyeva54d5a62017-02-11 19:01:34 -0800369
370 {
371 std::unique_lock<std::mutex> lk(m);
372 cv.wait_for(lk, std::chrono::seconds(5), [&] { return processEventsFinished; });
373 }
374
375 BOOST_CHECK_EQUAL(processEventsFinished, true);
376 if (!processEventsFinished) {
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000377 this->face.shutdown();
Alexander Afanasyeva54d5a62017-02-11 19:01:34 -0800378 }
379 faceThread.join();
380}
381
Junxiao Shi2bea5c42017-08-14 20:10:32 +0000382BOOST_AUTO_TEST_SUITE_END() // IoRoutine
383
384BOOST_AUTO_TEST_SUITE_END() // TestFace
Alexander Afanasyev0abb2da2014-01-30 18:07:57 -0800385
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -0700386} // namespace tests
Alexander Afanasyev0abb2da2014-01-30 18:07:57 -0800387} // namespace ndn