tests: sync common testing infrastructure with ndn-cxx

Also upgrade waf to version 2.0.21

Change-Id: Ibfd3386772d48df287b6be73e6d778d3661abe86
This commit is contained in:
Davide Pesavento committed 2020-11-25 14:50:41 -05:00
1 parent 8ab7572247
commit f91d1dfe15
12 files changed
+271 -166

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013-2020 Regents of the University of California
* The University of Memphis
*
* This file is part of PSync.
*
* PSync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* PSync 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tests/clock-fixture.hpp"
namespace ndn {
namespace tests {
ClockFixture::ClockFixture()
: m_steadyClock(make_shared<time::UnitTestSteadyClock>())
, m_systemClock(make_shared<time::UnitTestSystemClock>())
{
time::setCustomClocks(m_steadyClock, m_systemClock);
}
ClockFixture::~ClockFixture()
{
time::setCustomClocks(nullptr, nullptr);
}
void
ClockFixture::advanceClocks(time::nanoseconds tick, time::nanoseconds total)
{
BOOST_ASSERT(tick > time::nanoseconds::zero());
BOOST_ASSERT(total >= time::nanoseconds::zero());
while (total > time::nanoseconds::zero()) {
auto t = std::min(tick, total);
m_steadyClock->advance(t);
m_systemClock->advance(t);
total -= t;
afterTick();
}
}
} // namespace tests
} // namespace ndn
+83
View File
@@ -0,0 +1,83 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013-2020 Regents of the University of California
* The University of Memphis
*
* This file is part of PSync.
*
* PSync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* PSync 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PSYNC_TESTS_CLOCK_FIXTURE_HPP
#define PSYNC_TESTS_CLOCK_FIXTURE_HPP
#include <ndn-cxx/util/time-unit-test-clock.hpp>
namespace ndn {
namespace tests {
/** \brief A test fixture that overrides steady clock and system clock.
*/
class ClockFixture
{
public:
virtual
~ClockFixture();
/** \brief Advance steady and system clocks.
*
* Clocks are advanced in increments of \p tick for \p nTicks ticks.
* afterTick() is called after each tick.
*
* Exceptions thrown during I/O events are propagated to the caller.
* Clock advancement will stop in the event of an exception.
*/
void
advanceClocks(time::nanoseconds tick, size_t nTicks = 1)
{
advanceClocks(tick, tick * nTicks);
}
/** \brief Advance steady and system clocks.
*
* Clocks are advanced in increments of \p tick for \p total time.
* The last increment might be shorter than \p tick.
* afterTick() is called after each tick.
*
* Exceptions thrown during I/O events are propagated to the caller.
* Clock advancement will stop in the event of an exception.
*/
void
advanceClocks(time::nanoseconds tick, time::nanoseconds total);
protected:
ClockFixture();
private:
/** \brief Called by advanceClocks() after each clock advancement (tick).
*
* The base class implementation is a no-op.
*/
virtual void
afterTick()
{
}
protected:
shared_ptr<time::UnitTestSteadyClock> m_steadyClock;
shared_ptr<time::UnitTestSystemClock> m_systemClock;
};
} // namespace tests
} // namespace ndn
#endif // PSYNC_TESTS_CLOCK_FIXTURE_HPP
+53
View File
@@ -0,0 +1,53 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2013-2020 Regents of the University of California
* The University of Memphis
*
* This file is part of PSync.
*
* PSync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* PSync 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PSYNC_TESTS_IO_FIXTURE_HPP
#define PSYNC_TESTS_IO_FIXTURE_HPP
#include "tests/clock-fixture.hpp"
#include <boost/asio/io_service.hpp>
namespace ndn {
namespace tests {
class IoFixture : public ClockFixture
{
private:
void
afterTick() final
{
if (m_io.stopped()) {
#if BOOST_VERSION >= 106600
m_io.restart();
#else
m_io.reset();
#endif
}
m_io.poll();
}
protected:
boost::asio::io_service m_io;
};
} // namespace tests
} // namespace ndn
#endif // PSYNC_TESTS_IO_FIXTURE_HPP
+5 -7
View File
@@ -20,7 +20,7 @@
#include "PSync/consumer.hpp"
#include "tests/boost-test.hpp"
#include "tests/unit-test-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
@@ -55,15 +55,13 @@ BOOST_AUTO_TEST_CASE(AddSubscription)
BOOST_CHECK(!consumer.addSubscription(subscription, 0));
}
BOOST_FIXTURE_TEST_CASE(ConstantTimeoutForFirstSegment, tests::UnitTestTimeFixture)
BOOST_FIXTURE_TEST_CASE(ConstantTimeoutForFirstSegment, tests::IoFixture)
{
util::DummyClientFace face(io, {true, true});
util::DummyClientFace face(m_io, {true, true});
Consumer consumer(Name("/psync"), face,
[] (const auto&) {},
[] (const auto&) {},
40, 0.001,
ndn::time::milliseconds(4000),
ndn::time::milliseconds(4000));
40, 0.001, 4_s, 4_s);
consumer.sendHelloInterest();
advanceClocks(4_s);
@@ -71,7 +69,7 @@ BOOST_FIXTURE_TEST_CASE(ConstantTimeoutForFirstSegment, tests::UnitTestTimeFixtu
face.sentInterests.clear();
consumer.stop();
consumer.m_iblt = ndn::Name("test");
consumer.m_iblt = Name("test");
consumer.sendSyncInterest();
advanceClocks(3999_ms);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
+12 -13
View File
@@ -20,7 +20,7 @@
#include "PSync/full-producer.hpp"
#include "tests/boost-test.hpp"
#include "tests/unit-test-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
@@ -35,7 +35,7 @@ BOOST_AUTO_TEST_SUITE(TestFullProducer)
BOOST_AUTO_TEST_CASE(Constructor)
{
util::DummyClientFace face({true, true});
BOOST_REQUIRE_NO_THROW(FullProducer(40, face, Name("/psync"), Name("/testUser"), nullptr));
BOOST_CHECK_NO_THROW(FullProducer(40, face, Name("/psync"), Name("/testUser"), nullptr));
}
BOOST_AUTO_TEST_CASE(OnInterest)
@@ -51,17 +51,17 @@ BOOST_AUTO_TEST_CASE(OnInterest)
BOOST_REQUIRE_NO_THROW(node.onSyncInterest(syncPrefix, Interest(syncInterestName)));
}
BOOST_FIXTURE_TEST_CASE(ConstantTimeoutForFirstSegment, tests::UnitTestTimeFixture)
BOOST_FIXTURE_TEST_CASE(ConstantTimeoutForFirstSegment, tests::IoFixture)
{
Name syncPrefix("/psync"), userNode("/testUser");
util::DummyClientFace face(io, {true, true});
util::DummyClientFace face(m_io, {true, true});
FullProducer node(40, face, syncPrefix, userNode, nullptr, ndn::time::milliseconds(8000));
advanceClocks(ndn::time::milliseconds(10));
FullProducer node(40, face, syncPrefix, userNode, nullptr, 8_s);
advanceClocks(10_ms);
face.sentInterests.clear();
// full sync sends the next one in interest lifetime / 2 +- jitter
advanceClocks(ndn::time::milliseconds(6000));
advanceClocks(6_s);
BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
}
@@ -72,17 +72,16 @@ BOOST_AUTO_TEST_CASE(OnSyncDataDecodeFailure)
FullProducer node(40, face, syncPrefix, userNode, nullptr);
ndn::Name syncInterestName(syncPrefix);
Name syncInterestName(syncPrefix);
node.m_iblt.appendToName(syncInterestName);
ndn::Interest syncInterest(syncInterestName);
Interest syncInterest(syncInterestName);
auto badCompress = std::make_shared<const ndn::Buffer>(5);
BOOST_REQUIRE_NO_THROW(node.onSyncData(syncInterest, badCompress));
auto badCompress = std::make_shared<const Buffer>(5);
BOOST_CHECK_NO_THROW(node.onSyncData(syncInterest, badCompress));
const uint8_t test[] = {'t', 'e', 's', 't'};
auto goodCompressBadBlock = compress(node.m_contentCompression, &test[0], sizeof(test));
BOOST_REQUIRE_NO_THROW(node.onSyncData(syncInterest, goodCompressBadBlock));
BOOST_CHECK_NO_THROW(node.onSyncData(syncInterest, goodCompressBadBlock));
}
BOOST_AUTO_TEST_SUITE_END()
+4 -3
View File
@@ -22,7 +22,7 @@
#include "PSync/detail/state.hpp"
#include "tests/boost-test.hpp"
#include "tests/unit-test-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
@@ -31,14 +31,15 @@ namespace psync {
using namespace ndn;
class FullSyncFixture : public tests::UnitTestTimeFixture
class FullSyncFixture : public tests::IoFixture
{
protected:
void
addNode(int id)
{
BOOST_ASSERT(id >= 0 && id <= 3);
faces[id] = std::make_shared<util::DummyClientFace>(io, util::DummyClientFace::Options{true, true});
faces[id] = std::make_shared<util::DummyClientFace>(m_io, util::DummyClientFace::Options{true, true});
userPrefixes[id] = Name("userPrefix" + to_string(id));
nodes[id] = make_shared<FullProducer>(40, *faces[id], syncPrefix, userPrefixes[id],
[] (const auto&) {});
+13 -13
View File
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_SUITE(TestPartialProducer)
BOOST_AUTO_TEST_CASE(Constructor)
{
util::DummyClientFace face({true, true});
BOOST_REQUIRE_NO_THROW(PartialProducer(40, face, Name("/psync"), Name("/testUser")));
BOOST_CHECK_NO_THROW(PartialProducer(40, face, Name("/psync"), Name("/testUser")));
}
BOOST_AUTO_TEST_CASE(RegisterPrefix)
@@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(RegisterPrefix)
util::DummyClientFace face({true, true});
PartialProducer producer(40, face, syncPrefix, userNode);
face.processEvents(time::milliseconds(-1));
face.processEvents(-1_ms);
BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 1);
auto interest = face.sentInterests.front();
@@ -88,24 +88,24 @@ BOOST_AUTO_TEST_CASE(SameSyncInterest)
producer.m_iblt.appendToName(syncInterestName);
Interest syncInterest(syncInterestName);
syncInterest.setInterestLifetime(time::milliseconds(1000));
syncInterest.setInterestLifetime(1_s);
syncInterest.setNonce(1);
BOOST_REQUIRE_NO_THROW(producer.onSyncInterest(syncInterestPrefix, syncInterest));
face.processEvents(time::milliseconds(10));
BOOST_CHECK_NO_THROW(producer.onSyncInterest(syncInterestPrefix, syncInterest));
face.processEvents(10_ms);
BOOST_CHECK_EQUAL(producer.m_pendingEntries.size(), 1);
face.processEvents(time::milliseconds(500));
face.processEvents(500_ms);
// Same interest again - size of pending interest should remain same, but expirationEvent should change
syncInterest.setNonce(2);
BOOST_REQUIRE_NO_THROW(producer.onSyncInterest(syncInterestPrefix, syncInterest));
face.processEvents(time::milliseconds(10));
BOOST_CHECK_NO_THROW(producer.onSyncInterest(syncInterestPrefix, syncInterest));
face.processEvents(10_ms);
BOOST_CHECK_EQUAL(producer.m_pendingEntries.size(), 1);
face.processEvents(time::milliseconds(500));
face.processEvents(500_ms);
BOOST_CHECK_EQUAL(producer.m_pendingEntries.size(), 1);
face.processEvents(time::milliseconds(500));
face.processEvents(500_ms);
BOOST_CHECK_EQUAL(producer.m_pendingEntries.size(), 0);
}
@@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(OnSyncInterest)
Name syncInterestName(syncPrefix);
syncInterestName.append("sync");
producer.m_iblt.appendToName(syncInterestName);
BOOST_REQUIRE_NO_THROW(producer.onSyncInterest(syncInterestName, Interest(syncInterestName)));
BOOST_CHECK_NO_THROW(producer.onSyncInterest(syncInterestName, Interest(syncInterestName)));
// Sync interest with malicious bloom filter
syncInterestName = syncPrefix;
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(OnSyncInterest)
syncInterestName.appendNumber(1); // false positive probability * 1000 of bloom filter
syncInterestName.append("fake-name");
producer.m_iblt.appendToName(syncInterestName);
BOOST_REQUIRE_NO_THROW(producer.onSyncInterest(syncInterestName, Interest(syncInterestName)));
BOOST_CHECK_NO_THROW(producer.onSyncInterest(syncInterestName, Interest(syncInterestName)));
// Sync interest with malicious IBF
syncInterestName = syncPrefix;
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(OnSyncInterest)
BloomFilter bf(20, 0.001);
bf.appendToName(syncInterestName);
syncInterestName.append("fake-name");
BOOST_REQUIRE_NO_THROW(producer.onSyncInterest(syncInterestName, Interest(syncInterestName)));
BOOST_CHECK_NO_THROW(producer.onSyncInterest(syncInterestName, Interest(syncInterestName)));
}
BOOST_AUTO_TEST_SUITE_END()
+18 -23
View File
@@ -21,7 +21,7 @@
#include "PSync/consumer.hpp"
#include "tests/boost-test.hpp"
#include "tests/unit-test-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
@@ -30,23 +30,18 @@ namespace psync {
using namespace ndn;
class PartialSyncFixture : public tests::UnitTestTimeFixture
class PartialSyncFixture : public tests::IoFixture
{
public:
PartialSyncFixture()
: face(io, {true, true})
, syncPrefix("psync")
, userPrefix("testUser-0")
, numHelloDataRcvd(0)
, numSyncDataRcvd(0)
{
producer = make_shared<PartialProducer>(40, face, syncPrefix, userPrefix);
addUserNodes("testUser", 10);
}
~PartialSyncFixture()
~PartialSyncFixture() override
{
for (auto consumer : consumers) {
for (const auto& consumer : consumers) {
if (consumer) {
consumer->stop();
}
@@ -56,15 +51,15 @@ public:
void
addConsumer(int id, const std::vector<std::string>& subscribeTo, bool linkToProducer = true)
{
consumerFaces[id] = std::make_shared<util::DummyClientFace>(io, util::DummyClientFace::Options{true, true});
consumerFaces[id] =
std::make_shared<util::DummyClientFace>(m_io, util::DummyClientFace::Options{true, true});
if (linkToProducer) {
face.linkTo(*consumerFaces[id]);
}
consumers[id] = std::make_shared<Consumer>(syncPrefix, *consumerFaces[id],
[&, id] (const auto& availableSubs)
{
[&, id] (const auto& availableSubs) {
numHelloDataRcvd++;
BOOST_CHECK(checkSubList(availableSubs));
@@ -136,17 +131,17 @@ public:
producer->updateSeqNo(prefix, seq);
}
util::DummyClientFace face;
Name syncPrefix;
Name userPrefix;
util::DummyClientFace face{m_io, {true, true}};
Name syncPrefix{"psync"};
Name userPrefix{"testUser-0"};
shared_ptr<PartialProducer> producer;
std::map <ndn::Name, uint64_t> oldSeqMap;
std::map<Name, uint64_t> oldSeqMap;
shared_ptr<Consumer> consumers[3];
shared_ptr<util::DummyClientFace> consumerFaces[3];
int numHelloDataRcvd;
int numSyncDataRcvd;
int numHelloDataRcvd = 0;
int numSyncDataRcvd = 0;
};
BOOST_FIXTURE_TEST_SUITE(TestPartialSync, PartialSyncFixture)
@@ -293,7 +288,7 @@ BOOST_AUTO_TEST_CASE(ReplicatedProducer)
// Link to first producer goes down
face.unlink();
util::DummyClientFace face2(io, {true, true});
util::DummyClientFace face2(m_io, {true, true});
PartialProducer replicatedProducer(40, face2, syncPrefix, userPrefix);
for (int i = 1; i < 10; i++) {
replicatedProducer.addUserNode("testUser-" + to_string(i));
@@ -331,7 +326,7 @@ BOOST_AUTO_TEST_CASE(ApplicationNack)
oldSeqMap = producer->m_prefixes;
for (int i = 0; i < 50; i++) {
ndn::Name prefix("testUser-" + to_string(i));
Name prefix("testUser-" + to_string(i));
producer->updateSeqNo(prefix, producer->getSeqNo(prefix).value() + 1);
}
// Next sync interest should trigger the nack
@@ -343,7 +338,7 @@ BOOST_AUTO_TEST_CASE(ApplicationNack)
bool nackRcvd = false;
for (const auto& data : face.sentData) {
if (data.getContentType() == ndn::tlv::ContentType_Nack) {
if (data.getContentType() == tlv::ContentType_Nack) {
nackRcvd = true;
break;
}
@@ -384,7 +379,7 @@ BOOST_AUTO_TEST_CASE(SegmentedHello)
BOOST_AUTO_TEST_CASE(SegmentedSync)
{
ndn::Name longNameToExceedDataSize;
Name longNameToExceedDataSize;
for (int i = 0; i < 100; i++) {
longNameToExceedDataSize.append("test-" + std::to_string(i));
}
@@ -401,7 +396,7 @@ BOOST_AUTO_TEST_CASE(SegmentedSync)
BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
// To be used later to simulate sending delayed segmented interest
ndn::Name syncInterestName(consumers[0]->m_syncInterestPrefix);
Name syncInterestName(consumers[0]->m_syncInterestPrefix);
consumers[0]->m_bloomFilter.appendToName(syncInterestName);
syncInterestName.append(consumers[0]->m_iblt);
syncInterestName.appendVersion();
+4 -4
View File
@@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(Basic)
BOOST_CHECK_EQUAL(prefix.getPrefix(-1), userNode);
producerBase.removeUserNode(userNode);
BOOST_CHECK(producerBase.getSeqNo(userNode.toUri()) == ndn::nullopt);
BOOST_CHECK(producerBase.getSeqNo(userNode.toUri()) == nullopt);
BOOST_CHECK(producerBase.m_biMap.right.find(prefixWithSeq) == producerBase.m_biMap.right.end());
BOOST_CHECK(producerBase.m_biMap.left.find(hash) == producerBase.m_biMap.left.end());
@@ -72,12 +72,12 @@ BOOST_AUTO_TEST_CASE(ApplicationNack)
ProducerBase producerBase(40, face, Name("/psync"), Name("/testUser"));
BOOST_CHECK_EQUAL(face.sentData.size(), 0);
producerBase.m_syncReplyFreshness = time::milliseconds(1000);
producerBase.m_syncReplyFreshness = 1_s;
producerBase.sendApplicationNack(Name("test"));
face.processEvents(time::milliseconds(10));
face.processEvents(10_ms);
BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
BOOST_CHECK_EQUAL(face.sentData.front().getContentType(), ndn::tlv::ContentType_Nack);
BOOST_CHECK_EQUAL(face.sentData.front().getContentType(), tlv::ContentType_Nack);
}
BOOST_AUTO_TEST_SUITE_END()
+17 -28
View File
@@ -21,7 +21,7 @@
#include "PSync/detail/state.hpp"
#include "tests/boost-test.hpp"
#include "tests/unit-test-time-fixture.hpp"
#include "tests/io-fixture.hpp"
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/interest.hpp>
@@ -33,29 +33,24 @@ namespace psync {
using namespace ndn;
class SegmentPublisherFixture : public tests::UnitTestTimeFixture
class SegmentPublisherFixture : public tests::IoFixture
{
public:
SegmentPublisherFixture()
: face(io, util::DummyClientFace::Options{true, true})
: face(m_io, util::DummyClientFace::Options{true, true})
, publisher(face, keyChain)
, freshness(1000)
, numComplete(0)
, numRepliesFromStore(0)
{
face.setInterestFilter(InterestFilter("/hello/world"),
bind(&SegmentPublisherFixture::onInterest, this, _1, _2),
[] (const ndn::Name& prefix, const std::string& msg) {
BOOST_CHECK(false);
});
advanceClocks(ndn::time::milliseconds(10));
[] (auto&&...) { BOOST_CHECK(false); });
advanceClocks(10_ms);
for (int i = 0; i < 1000; ++i) {
state.addContent(Name("/test").appendNumber(i));
}
}
~SegmentPublisherFixture()
~SegmentPublisherFixture() override
{
fetcher->stop();
}
@@ -63,11 +58,11 @@ public:
void
expressInterest(const Interest& interest)
{
fetcher = util::SegmentFetcher::start(face, interest, ndn::security::getAcceptAllValidator());
fetcher = util::SegmentFetcher::start(face, interest, security::getAcceptAllValidator());
fetcher->onComplete.connect([this] (auto&&...) { numComplete++; });
fetcher->onError.connect([] (auto&&...) { BOOST_CHECK(false); });
advanceClocks(ndn::time::milliseconds(10));
advanceClocks(10_ms);
}
void
@@ -92,11 +87,11 @@ public:
SegmentPublisher publisher;
shared_ptr<util::SegmentFetcher> fetcher;
Name dataName;
time::milliseconds freshness;
time::milliseconds freshness = 1_s;
State state;
int numComplete;
int numRepliesFromStore;
int numComplete = 0;
int numRepliesFromStore = 0;
};
BOOST_FIXTURE_TEST_SUITE(TestSegmentPublisher, SegmentPublisherFixture)
@@ -116,7 +111,7 @@ BOOST_AUTO_TEST_CASE(Basic)
BOOST_CHECK_EQUAL(numComplete, 2);
BOOST_CHECK_EQUAL(numRepliesFromStore, 3);
advanceClocks(ndn::time::milliseconds(freshness));
advanceClocks(time::milliseconds(freshness));
BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);
numRepliesFromStore = 0;
@@ -126,16 +121,10 @@ BOOST_AUTO_TEST_CASE(Basic)
numRepliesFromStore = 0;
face.expressInterest(Interest("/hello/world/").setCanBePrefix(true),
[this] (const Interest& interest, const Data& data) {
numComplete++;
},
[] (const Interest& interest, const lp::Nack& nack) {
BOOST_CHECK(false);
},
[] (const Interest& interest) {
BOOST_CHECK(false);
});
advanceClocks(ndn::time::milliseconds(10));
[this] (auto&&...) { this->numComplete++; },
[] (auto&&...) { BOOST_CHECK(false); },
[] (auto&&...) { BOOST_CHECK(false); });
advanceClocks(10_ms);
BOOST_CHECK_EQUAL(numComplete, 4);
BOOST_CHECK_EQUAL(numRepliesFromStore, 1);
}
@@ -152,7 +141,7 @@ BOOST_AUTO_TEST_CASE(LargerDataName)
BOOST_CHECK_EQUAL(numRepliesFromStore, 2);
BOOST_CHECK_EQUAL(publisher.m_ims.size(), 3);
advanceClocks(ndn::time::milliseconds(freshness));
advanceClocks(time::milliseconds(freshness));
BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);
}
-67
View File
@@ -1,67 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2012-2020 University of California, Los Angeles
* The University of Memphis
*
* This file is part of PSync.
*
* PSync is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* PSync 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDN_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
#define NDN_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
#include <ndn-cxx/util/time-unit-test-clock.hpp>
#include <boost/asio.hpp>
namespace ndn {
namespace tests {
class UnitTestTimeFixture
{
public:
UnitTestTimeFixture()
: steadyClock(make_shared<time::UnitTestSteadyClock>())
, systemClock(make_shared<time::UnitTestSystemClock>())
{
time::setCustomClocks(steadyClock, systemClock);
}
~UnitTestTimeFixture()
{
time::setCustomClocks(nullptr, nullptr);
}
void
advanceClocks(const time::nanoseconds& tick, size_t nTicks = 1)
{
for (size_t i = 0; i < nTicks; ++i) {
steadyClock->advance(tick);
systemClock->advance(tick);
if (io.stopped())
io.reset();
io.poll();
}
}
public:
shared_ptr<time::UnitTestSteadyClock> steadyClock;
shared_ptr<time::UnitTestSystemClock> systemClock;
boost::asio::io_service io;
};
} // namespace tests
} // namespace ndn
#endif // NDN_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
Vendored
+8 -8
View File
@@ -32,13 +32,13 @@ POSSIBILITY OF SUCH DAMAGE.
import os, sys, inspect
VERSION="2.0.19"
REVISION="1f3c580272b15a03d2566843c5fe872a"
GIT="61ee22b598cf80e260beb64e475966f58b304d0d"
VERSION="2.0.21"
REVISION="16cd196b0fc7b4eebe195ce20396f3d1"
GIT="86eea788e3210f6681a827cda931089da04e06c1"
INSTALL=''
C1='#6'
C2='#.'
C3='#%'
C1='#2'
C2='#/'
C3='#-'
cwd = os.getcwd()
join = os.path.join
@@ -168,6 +168,6 @@ if __name__ == '__main__':
Scripting.waf_entry_point(cwd, VERSION, wafdir)
#==>
#BZh91AY&SY9 ½´\¥ÿÿÿ³DPÿÿÿÿÿÿÿÿÿÿÿm (¬#%0�0e€(b÷/mЀ#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%öÞúzómmkîÖZžÞæ—²U#.´[iÚ¾î�õ¹±µ–ú:¥'kd‹î7{ÛïoºµÛ¶ÖµK“¹]Øvµ'ÛßO¾ö¸gv÷s½÷¶N)#.Q+Ù½íp·µÞ�]/{mš»<{guÒ‹@Ýó{§«�vo;¾ø;ŸvÎiîáÉî44lºï{ß|ûëËßÚU9íõÝŸÝšî·¯y½÷½x#%#%@(}ìh#%` ï²€=â�wfí˜:4§[aÓ¹½ y©³A¦€‡¸ê»´ö4=¦öìd+Ö¨ª)ífš0#6 *”¢”{ƒ’�Q$#%#6#%YJ�zÚV½ƒ%çÍíîæ}»�j½êºa’ïjÚØá3TTf˦Iv×]s}6óu7¾÷z:#.ÎxûÝW_=³ÛzÖ­åZ;Û»ÍÝÛ}Þsy¾¯³»ß{¸ûížÖîiÉÔ÷Ëzõ¶§rç>^æû}ñ¾íóÛa zúz{x¹-ì�z̀ݳ­Ö²4÷³¼ÛÞ÷fÞÏs¬ô`u¡ÒãF°Û"’EE7w¼#%(J*’OCÀ#%lîè•=÷n{Ywº¹½»ÐdÜ öï>}Ü[vÇGÐ`>†ÛEmk®¥ÑMã�W`×LæyÛãÚ^u½#%}�÷aŽît;o¶û}|{mçO—vpòǼ΀Šo·*WµíƘܶ2>öí®®òÏŸwÖõ»]´î;ºjîí9QÚt×·Zt“ž>÷»Ü®¨ÜÙu÷‡ß|}í­«×ܬ‰&ÞíN«îq\îû½:¾Ã.ñŽ^ÙéyaC§¶Ó¶Û›—³®÷Ð¥&nCzî¤|öilöͶíÝîвë[¸˜÷»³Ûºû5ÖkoX«èqØ—nöÐl­îõÞÞ/`{´žó½wÌ>ï†Ðê¥PJªPTT´jB¹7uÐv�&i¶v­Üèº]vú‰Ý›:kÛkÔØëUUܘ{x÷š)º¼»HЃºÚɯfw€#%7ZI#%#%;Ü^êåÉÎó²û3ÊF-Ÿm½ÜözÔíÝ™Üì_U.us[›¶ õv]]ó¸|˜Hû†,ÍqÑ»ÝÁæñ{c;úŒçvåJº{+¹éÔ²õ§l÷+ªWg¡»`úùÛÙ;{n#î²Ç]÷}çww»{»»xîvÛ#.¾Øú½mÝEfù‡"sž¼ï¯¼ùÚÀ°ËlÐú$/g¬íÑ”x<ïÜë°VØ6EÇ‘µÞ®ÚGxO{×>öø½ïwÞ´#%À*×Û;Fªµíí7¶;g�<�ÂÀëu´oSk´Ý­ëÓ­mï 9.ó’®Ú×ݬ» ݾçwÅówwtåvë¥Þç:#.[.ëwc Ó‚àéÕhÁ”gu“½Þ^ïŸnØu¼�ÓÐŒ…/=ÝÚ4#%•c�¹éî½Mö{ÜàìJ…U )½{xW»´×`ï{®ñÝÊäÅÖÃV¶•U[}÷IzovƒuÇH*Ší·u­$ëIÒÖªîúãÞncÚ[ÓµŽÛ× &Æ»»}öøø‡½óí·³acÜ| ìÁ“G»îñÌͼÜ&:·»}½í6µî�Ðíç;ï¹ßvÛRÀîï·Ÿw}-âò�ó[ãnh€ &€#%&€ £CBa0š#.#%‰ä™PÏTz†Ðš#%õ§’{SÔõA) B @†@©©á$zzI☠é4#%#%#%#%#%#%#%‚D!  M5TÿMŠoU<ÔôzTý(òÔõ)é¨mG¨#%#%Ñ£@#%#%'ªRD!4dÐODõ$ÙOFž¡£õM#.€ò@#.Sj#%#%#%#%#%#%$!#%&@bh&M#%M#.4SÓiˆŒ4 ¢ #%h#%#%#%I¨ˆ L˜#Až€&Œ¦�=&”õmêˆ{SIé” h#%d4#%È#%—ÿÓ?£Uirê\ÕQWwk¹úµZvhʃ>5Zu!LA³ ,L•Q*"€)æ°Pcõ§óü Zü“•5OùÓ¦¸ üæJt¦î£Ä‘8•WoT"¢]^SÌÆ´_3ý†os2ì ÀlDs‚4;m»qE6­›®ñ‘ÎÊ­´ÚMí˜ÖØ`Vd…â]jíâ—˜•5o‚# åñ÷UŒI7wD¼áÌKUå¦/žÝ~«oÔB�äE"ªSº»U¦ÖÖ5k3khÈ‹ €7#%H*-E Õ:¥”$HŠ&� ˆ" HåP° !ß#%hŠ–‚¡#%ª$@d PÉ@mªfL…’ŒÍCLÓd@M$Rj6Ñ35–25)F”Sm&‰š$ÐJ2Zš�Q°h[Fi,ši¢Z!#.F)iM€F¥� #.1eM£DRl–�¨Š–ZSMh�ˆYi#.š ƒ(ÌÌcRF£Qµ&ƒJl†BjcI@˜hÒËHÆR›F¦›"[M¶³U´i˜’ÆfLÈM& ²m¦ÛM6�5%)-5±–¦Û3fZL“1‘f´ÄÑd¢‚™l‰B!Qf‘´R`4TH!`ؤ©„f•Jb0lB ‘X�hdFIR&B4±ClÍ ’&)BF�RÊËf$@ÒYŠY5“ccE�#6‘d†K) -)¦ ±%&EDš2hhɉIF‘(�$@VAM�Eˆ¢fRÒ¦`›É ؉1M Í‚ab6¤Ø–V‹$”›‚$´”PRD•’%¤Q0Ea�ÆIL# ”&RJME™±£XHÒjH’b iM�$"H²[bË2ŠFÌ’‰²™3bdE(Í‘˜&U4Ä�‹)A³Q`,�i¦†Æ"5+%’6(”R"šIˆ&¤a³L�cI¡ &¤–Q”Ôi3HÚ("šh¢kP,&YA¤²2‹%&DÐM2‘*4f6”)1¨6ÄÊA! "“1�F4,�Ë ŠÙ&TÌÕ˜£l¥±(‰™#.H¦!HŒØÐ¡YM$QF¤É&ÉØÆJšF¦h±b2’™˜²2³i„¬D`ˆ¢JM52i™!Œ¢)#.š1Sb‹5*R’š)#.‘“2)´…HÅ(ÊHR"‹E$˜’M)´i5DŠFÀ˜Œh&Ti¦DÚ#.ƒ,„Òe‹DÈY‘¦ÉJb”D!f™ k6lmd°$4–Ld5EPZ XR$Ècc1 Â2ƒRXÔY¤J&ŒE©M(Z˜hI™IŠ$2ɲ#)‚E,Ñ¥1„5„²e"$4M¶¦¶´`™BjfŒ¦F&”RLȈ­¥6À¥š,Å&‘”%–TÙ¢-L¬-”bC؈RˆšD#HJm~Ãk¢¦©aˆÍ¢ŒlVƶ*6L¥4ÔR¤š44´…¨ØFÉ5Y†¡¦c(ÉS*H¶D‰™¦[%´Q‰IKQµ…£&˜D±5˜±acR#6e¥™2eI´*Ò4TÙB+dË"©TÒT›63š¶,Y­“L¬‰S,¦ÖJ²ÙJSL�l�’‘µ)¬±%¤2RÔZ ªŒ!¨Õ£%AEVMd£jŠÅEH”kDÑ$m‹hÅŠÔl2ѵ�€´™0°U@i€”R £F2™&•¦±Æ�¦&±‹d‹i Õª–µ–* ”ÍKY4IR1!M¤lY"¶¥Y¶1Jm*–R¦YaZšDF¶•K"e5MM¶„”Êk,Xl²k+,…lÓ  ¨ÒD…�bÃ4˜‰!´…-£T%¢†KQY&š6LšJ,ˆ&ËŠl¤#."+,‚E1”ÌJ”lÓ4 AE¢Ó$&Fm6“F6ÆÈS¦™cE%bHÌÔ#!4LÔQ¢JdR�–P5BTÀ4˜Ó J™²Bj-#636£)F̤’Œ�£!HbÊkÃi4F5&Éa $YP…-4) Äš4Y”©””²•˜d¬aš,‘± jE¨Õ5£4ECF¥)6b¥�fQj4  2ÆA¦&Ä•%I”1Ršcd�¤Ía)ME`Û0Ù¤²lf“E�˜‰CJ2Zfµ‘hTÍ2–H’l£0D2hªih�¬Òl”Ä,LDÒRBAh´[ Q¨ÔQŠÆ-–ÃI†’M#6L�ŒRˆ#b��-f›C2ˆ6*2%,¤©‘Ñ´k£TI¢„Ë5EŠ$Ôš£PdðŒj”¡kA¥4Ë!E$ЦIh‚5Eˆ±JÛ"¥F±¤ÁdÑÌ¡jQHfJ$©±(‰•j#V#.2,Y*6Œ)‹4¢Ù2V-­&)+)¶D¶M�¡¢T’™R¢Âƒccd£dÑ&#¶H�ÔRLÁ¬ÉƒA#6�)³6&"𯍩•“Y‘¤)¤šŠ¢Š&›RV-”’ÆÉˆ£F‚4˜2JÔˆÑie£he¨’Ñjб”£i5² …Q¶5%)ЙÈ̌ƚ‘�LÙ&kDlU%‹hÔ•,«&´LÚ�1lj £cc$UE2©¥XÚ6��¶1mI˜ÊQ f²±-F+iQµ´©QJV”f*šB (4X"J�&ØÖ,Ê’+I[M²“+F�bbÑI�E[l¶¬R&T*&$¢1PÀ"CF�Ši&ÔÃ%XÛØ´Í[F5¬´•42ÖÊY6ÔÔÛ!mI¦¬ME26’QA°ÖjMI™²Êˆ B¢LI&RLˆÈÄd"Ù-¢Ñ‚±“þn··ýÔ¥C)þB51jÄÿTqôe+(a(Æh”‡÷!þ§ ûbåÕ LÿL$hÒlùNzí¿Îó±½9¿‹øºô·¦SUIPª?ë[ŒlÈŸÎÿ·ÖYLâsÈ †ßùë;�L(0\:8À¥‰pÁI äˆd˜*ƒ‰Ãß±¢rý*¤çÿœ3ÿ³ôZÑÿÊI(R×+ˆ½”g™,$b/­Í0ÿ-‹npz%ZM‡¼íõâ8ßwB¹ÁŒ¨d~Ë Õ‹NØœ“ÆZþ,3cRR(l“ŠrrXˆþúݳf¤áV…cÈÌ`I¥Û"lÆLhƒcôzç““G]“¼î�˜Þ¹w§¥^¥ã\³�Ë/âuçåu™Í\‚LŠëP¦"W‹4LªvcK™@¥JAF&Ä“M‚ê×bÈ‹Ò3ˆ(êñç]¨eñnY½74h6 m `Ù—(c2@sªªzoþÝ(‘ 7p‡ Êc#6Gv…)†ì,`¼rÂü®R[ŒR}ßÒëdzçgsÅéšÐN×VÄQL0¦Ð¤Y;ùd«Ïô8$ÚÍÏ£˜ØÐØžj¤Ï(%?·râƒþ°Ãµ “ºÀ¡…†JÅxžß÷k¶Œ¶cÂx-›2KËw%€•¬C°UyáyÜ–íÞw^QŽr車esn–CQW6éçqllO²ëå5¼Z4EA¯»ºŸ?_ÆW‹ò-ȦWÅȶÆåÈIºÕø¼u‘¨Û?Go*„Èyùæ|m<™b#4L9cuPEX°ž«©#.¹t@#6A�!´ä#ñÆ#.¯)ÎãÂHˆÃz”^+›Ý\Ѩ8šë•ÞwcrŽ•Ë™(Ë®é$s™5öø‘ZA„�ÿhÿŒJrÈ.YÚlCÙ’,0!M ðÛtÉÈe«#6ýR�­‹ÁÃ79ô,ýפ�¾ìÉþ˜FtÃÏxV¬@Gô¡€dž%lþ «p’—<kìÄ9 c£ðÐÃ|¶Ç™“#tE]H P0îT[æÈ؃Ù_#¨½—zírH È¦wâÔŠŽÍW†7mxþVYê? )Ärvj³oQžwE¦m„e#.¿ÂdÔ‚™ç™×¶b²àþN!ïe §&¢”øuû/ÑÏKà`ö§nínœšùT)"*�¤#6d9 #c*w&é�ƒbÛ†ÉðfR6zš®:'ï�.àûì¥k,YL#6N�*}±ÆyÞ>ÇãŠ�UË"õÖ�“UO«pi)8ª—â”+ñ §Ó¬,‰±Èj[þv¼‹lQôÇôa™1Kèë¯Ç×FÌ÷¿SªÄ7Ím‰Z½&#6”*‰£NŒ¼Pâ-#6¬AË@‰�*•{iX<ÙZøW÷»(Éðâ»EEE¼nY5ÆÕ͵þ—ìw’�>ÇS6½•ß‹«¦öøÿM‡fhŠF¨%2+zmýW!†�ŒbSQIðîÜ®÷uVé(i%"�÷@Xš'+¬¥&D§)J²‹šå¢¶/]öï^¯"R¬•k¹bÑ_·-×»±öõÆ*Š|ý{ü=o÷îèë˜ØÔl›|ÏÀÞ1¨4–üŽ�‹> õÝŒ>¬žýóL—ÖȲ"4£�~"U�ä¨ræPaŒLÖ¶jϹ$Â![ÙùzÛ²†F²lWßî«âøùÑÊW=ì¼4D‰Áa«l—AHÒPŤ'Ò'mBµ§…C×Gƒ¶éE2„R]U¥"»wÕ¬�ü*ÔðХ߲œœ²ôî²Á‹¨ÀS�E#6lÃQ MZH"JuœëJ» *”Ó#6I¢L²íãe—¥Â„S²ŠŸ$+� bLine truncated
#BZh91AY&SYTÛ¶ñ^îÿÿÿ°dPÿÿÿÿÿÿÿÿÿÿÿm ¨Â,#-40�E0m b¼÷) #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-¥÷Ó\ÊV¾æ»Yc½Û½Úl¥Cf–ÎÜ´ºûwY¬Û¬w¶U:fÖÉÖ»zt¾­{vÚÖ%Ñܬš�<Ÿ|ûäÂolÙÝ·G»dÅ!ª;nìó½p¼›×»^ƒïa»<zÞ÷C¤ô:íõÛÚN&Y®mïCs‡]××q‰îg°½ì÷½÷Ûï¾Wo|m¶4Þo¯£Àocš½Ý;øà#-#-#-#-A7¸#->4=hà÷f€yà#/›»y€=µnÒw;Ðtô{¾ööµ°i #-i“Ó»]—^Š:º#-íÐØl…z4Uö°Q€P()T¥È2ª‚ŠÐ#/uèzz€UèuÀé£Ï¾íz÷»‰Øí]ŸuEnñÛÍÕ©3#/RTm‹L’í­ÍÍôö�®_wÞ^·»ØûîŽö¼öí´�mìó¹çxúÉí¾ûzó{;vÏnºûìÉlÛy5<ûž“íñßYêmËÇxíïpò€ èó²´#2AUR�{6›Ù¤ë]µÝ›µ™v={¼nï9Ö:Ô�´<¯yÈöìÌÔˆ¤§o9L§­#-Q‰DP=Øg¡Ð½ÁÑOGo;¼g¼Ôö·½�Jªû�w¼Ï™—³"Š#-õ¥¦)kk_]K§Û;ã�W{�ïiæ}öö;ÁèV÷·µào}nw²·�Ãèi[Üð}ã¦}×sÔöãÝ�#-ºÓïgÓÛv©�p2_föº»ËO¾ß[Ç]\]Ë´ÕÍÒï®=§»W×7�$ç—Ü÷/nv¾ïuìç¼;½>ó«ì¥#/vt¦œîm>Úõ]>Ì9|'s|šÞ,({k’î¹ÏmÛãà ×»*Ïvêfùîîún½ŽÙ±÷�¾Î^Û;›C–ÕK}Ý%ë�÷d{»Ýdòœwpç+µÓy#-Ý9^ózï˜}Þ#/:ÎRŠ(#2ìÊB.…˜Ùr‚¶ZÖÛggCêÜ®—BAï¹›±:UÃcÛBW]²¼¼{e"ÝvöÔƒ»æuÝ�#-#-mìë´€‹Ðöósr;¼ívZªKW¶l¾Ýæiîkbn»ÜÙnQêæäTôévÁO³:ù8ön�½515ÇDBÞ²“¼^ìyîú}íïq¸ø +™Jó[ž�Aí›Ö�§:¤žG¤›{+¡Ï¶â>ë}‡r[ºu½Ã½î^Õçm¬Wۃã»��zvL§�ÙÎǦ–›j[[(z/wéÞÞL£>¼{àíºè5k ¢qòίCU™Â÷žûß}µ>sì@UïjáUG9J[×y�{º8îõ\î.0©Úfì*Í7׃٫6½·m�}µ—a½ï}ÏwŸU»�ÒTËJ½ÎtiwXÒîšô÷Zí‡4ð\º ƒt8éÇ{¼»¾µ¶¾o iè °ú+é˜=À#-9W“Wn¬û¬v{€:¢�¶¥Ú×{Þ »­Û#-ì^Úqo+¶çwWLX½·­ë{¤lغÜ»¤¨¡Œ­m¦ÙÖ•Ùm— õÆ}Ï»ÇvÜ}¥½1{Xì÷zͪæ¾ûxø‡½ó¾ë\ÀžÇÏFôÇlC&NëîñÛÍÁ¡mqïsîï-½Þ÷¼ó¸ôÖ^ù÷;/²µ�ÝݸÖókíï­¯“àkSå_,ᦈ#-€#-&€#CA0 ¡¡0‰äBO#/¨ÈQ z@òGµ4Ÿª M@�#-š¥<&1&FÑOÒFÒPÈF™#-#-#-#-#-#- &A2a4§â‰?#2›ÒŸéSñ=Q=OQ£j=zž“@Ð4#-#-#-#-OT¤ˆA4ôÊ1)æ£ÑGêƒF'êž�P#-#/šƒÔ4M#-#-#-#-D#-M#-€&™4ÔÍ551‰¦ ¡3I�š@#-#-#-€$ÔD ˆ4h�4Õ3 )õQè�({I¨ÓOSÔ#-h#- #->_ÿIþ�U¥sùñʵ;µÛöª´ó4™¨3ãU§bB˜“Td` ˆ*%@@|–" Qú/Óø¨ý?¨»ýTøØ xƒ50èµ+,S¾šSTboéêê`‰þ£_#ývos2ì ÀkWdD$ AÔÔ] ÔDd‘ÊÞd¾*ꉗŽqs…OˆW4]Z¬aâí•FQ1‰Ãâ1wŒ(˜‹˜¸Ça†ñåøúˆVâ#2‘V#2F @¨€‘EF1E$E@A@n#-�TZŠ”å,¬‰"Asha@0Š�#ŒQBÀ$Dl@„×çUºm¯-kim©Wt[н¦ÔU­Uo}¶µµLÉ�²Q™¨išlˆ £ŠJ�´LÍB%Œ€MJQ¥ÛI°¢f�2M£%©¨Õ…´f’ɤˆÑ-†£‰´¦‚@#/£RƆ˜²¦Ñ¢)6KE¨Š–ZSKh�ˆYi#/š ƒ(ÌÌcRF£Qj “A¥6C¡51¤ L4Ye¤c)M£SM‘-¦ÛYjÚ4ÌIc3&d&ˆ“Y6Óm¦›@š’�”–šØËSm™²–“$ÌE@dY­14Y( ¦E"FЈTY¤m˜#/X6)*a¥DAR˜Œ„($D– Z’FÔ‰��,DÛ3C$‰ŠP‘†d²²Á™‰4–F"–MdØØÑb‰…H²C%”„�Ji‚lII‘FQ&ŒšL˜�T”iˆÒH�ScD‘b(™”´‚)˜&ƲC6"LSC3`˜X�i6%•„"À‰%&Æ¢"KIE$IQ "Q ŠEP`& d”Â0™Be$¤ÔY›5„�&¤‰&!–”ÙB$‹%±&,³(¤lÉ(›)‘±6&DRŒÙ‚eSLI²”†ÍE€²A¦šˆÔ¬–HØ¢QHLŠi& š�†Í2�&! &¤–Q”Ôi3HÚ("šh¢kP,&YA¤²2‹%&DÐM2‘*4f6”)1¨6ÄÊA! "“1�F4,�Ë ŠÙ&TÌÕ˜£l¥±(‰™#/H¦!HŒØÐ¡YM$QF¤É&ÉØÆJšF¦h±b2’™˜²2³i„¬D`ˆ¢JM52i™!Œ¢)#/š"¦ÅjT¥%4R#&2dSi#2,‘ŠQ”�¤E*ŠI1$šShÒj4‰4ÆÀ˜Œh&Ti¦DÚ#/ƒ,„Òe‹DÈY‘¦ÉJb”D!f™ k6lmd°$4–Ld5EPZ XR$Ècc1 Â2ƒRXÔY¤J&ŒE©M(Z˜hI™IŠ$2ɲ#)‚E,Ñ¥1„5„²e"$4J­5µ£ÊS4e214¢’fDEh5)¶,Ñf)4Œ¡,²¦Íjeal£Sb!J"i�!)µüV×D%MR"ÛEØ­ŠØ¨Ù2”ÓQJ’hÐÒÒ£a$ÔmdF†™Œ£$l¦T‘lˆ33L¶Kh£’–£j) FM0ššÌX°±©2ÒÌ™2¤Ú#2�•i*l¡²e‘TªY*aM›ŒÍ[,ˆ­“L¬‰S,¦ÖJ²ÙJSL‹l�’‘µ)¬±%¤2RÔZ ªŒHj5hÉPQU“Y(Ú¢±QR%Ñ4DÉbÄZ1bµ ´mc`-&L(ÁU¦QH&�ÈZdšV–Ä[6˜šÆ-’,m¢ Z©kYb¡�™LÔµ“D•#4ÚFÅ’+jU›c¦Ò©e*e–©¤DkiT²&RÔÔѱ hIL¦²Å†Ë&²²ÈVË1BAC*4‘!cDX°Í&"Dˆm„Æ!KhÕ @„¨¡’ÔVI¦�“&’‹" ²Å"›)FÈŠË ‘Le3…%4ÍQh´É ‘›M¤Å�±²Â)¦@Ä…ÑIE†˜’2j ‰#/�ƒ &j(Ñ%2)F‚Ë(¡*` �Li„¥LÙ!5Œ„FfÔe(Ù”’Q�4d) YKb"˜m&ˆÆ¤Ù,"‚ÉXBŒ–Š †bM,ÊTÊJYJÌ2V0‚ÍH؆5"Ôj�šÑš"¡£R”›#/1RÆÙ”–£@‘�“ LdblIRT™BŠ”Ó$…&k Jj+Ù†Í%“c4š,lÄM4£%¦FÕ‘hTÍ2–H’l£0D2hªih�¬Òl”Ä,LDÒRBAh´[ Q¨ÔQŠÆ-–ÃI†’M#2L�ŒRˆ#b��-f›C2ˆ6*2FÉK)*dE´mƨÕh¡2ÍQAb‚ 5&¨Ô0Ä,#¥(mch4¦™d(£D‘TÉ-F¨±#)[dT¢¨Ö4˜",š"™”-J) ÉD•6%2­DjÁ¢¦E‹%FÑ…1f”[&Jŵ¤Å%e6Ȗɱ´4J’S ÊTX@�lll”lš$Äb6ÉŠI˜ Õ™0h!Q¥6fÄÄSXÕ2²k24…4“QAQDÓjJŲ’XÙ1h �& ’µ"4ZYhÚj$´Z¢¬e(ÚMlˆ!Tm�IEŠE4&E23#1¦¤F%#/LÙ&kDlU%‹hÔ•,«&´LÚ�1lj £cc$UE2©¥XÚ6��¶1mI˜ÊQ f²±-F+iQµ´©QJV”f*šB (4X"J�&ØÖ,Ê’+I[M²“+F�bbÑI�F­¶[V)*Q¨`!£FÅ4“jaŒ“mbÛ™«hƵ–’¦†ZÙK&Úš›d-©4Õ‰£(¢#FFÒJ(6ÍI©™›,¨Š*$Ä’e$ÈŒŒFB6Éme¶EÿƒÄÿ} èš?ÁXf³ô#?Ï£¥†ØJ0åÛ•üÅò9ì¿“�wÅ[›û<½*#/MŸ4ç®Ûüï;Ó›ø?ƒ¯Kze7q˨ÿ]òeŇõÏôüK�Õ‡~…rÿ©Zà#2dAE ‡G±.)$‘#/·¹‰ÃåÚÑ9þJ¤³ýAŸüÿZ?é$”)k•Ä^ÊpVP±ˆ¾§4ÃýkÜàóJ´›i×çˆã}�#2ç2¡‘úXwf¬ZvÄä�ò×õ0ÕJ"†É8¡·'%ˆƒüµ»fÍI­ D##1�$v—l‰³1¢#/�Í¢:>MvNóºBczåÞž•z—�rÎw,¿�ן�Ög5r 6#2…1š¼Y¢eS³\Ê*S I’$b„Þíº P®‘€‰�h”…ãλPËâܲ3znhÐl‚ÁS‹ &*�­î\r¿ö,°þ wp̦0Q`¤whR˜nÂÆ nX_wµÊKb1ŠOËü=xö|íÜñzf´µÕ±S )´)NþY*Ì�Á&Ön|9���&ÄóU&xA(ñý›—(?àv¡brwBØ0¡ÂiX¯Ûþjí£-˜ðžË@æÌ’òÝÉA %kìQáyÜ–íÞw^QŽr車esn–CQW6éçqllGÀ£q„¶A`¢€«uP<hø!kë[‘L¯‹‘m�Ë�þëWçxë#Q¶~|("!ãã˜Añ´òeˆŒÑ0å�ÕAbÂz®¤4råÑ#-)i#/§!7Ž0mxNwDFÔ£¼W7º¹£Pq5×+¼îÆå+—2Q—]ÒHç2>kíòIa�?ìê’œ² –A¶›öB$ÆÑ�#2hg†ØË��ËV,öQJ>´š~ÆŒi[v—_'³2<PD¯õQIº4Áj°T?І�>¼J6:jÀ\$¥‘7£þRÁ½8&V¾Û%AÆgØ¢…2Ia ;•ù²6 öWÄÈê/eÞË\’(3)¡øµ"¢…+ö¼~û,ò>ü)Äruj³oQ�ß#/wE¦m„e#/¿ÂdÔ‚™ç™×¶b²àþN ø2�S“QJ|:ý—èç¥ð0{S·v·NM|ª² âÕÊßDlònß}|—·»´Kn'¹™HÙäÕqÑ?l wÛe+Zie0):4¨ôRÄGçxûŽ*uW,MùqY„�¿µ21¤Úy"¾ÖP¯¼&ŸGXYc�Ô·ü¬=Y4Ø£ƒÇó�a™1Kèë¯Öë£f{ß›«Èæ¶Ä­^ˆ�ŒJDѧF^(q…V å DÇ•J½´¬l­|+ûÝ”euâ»EEE¼nY5ÆÕÌ�ÿ‡ì«X>#/ ¡^41Xý¾?ÉaÙš"‘ª L‚#2Å^›EÈa„EF1‰ME'ûr»ÝÕ[¦á¤”ŠwÝbhœ®²”™œ¥*�5ËEl^»íÞ½^D ¥Y*×rÅ¢¿¥–ëÝØûzãE ¾~½þ·Š{÷tuÌlj6M¾gÝoÔK}n�,ø/»æÆ,žÝóL—Í‘dDiGÜD«ë�åÌ Â#™­lÕŸrI„B>¶£éD•V"Â#"‡Z 6vº’W=ü¼ôë,±®h×Áão:¹9tÇ!8¶‘;jå­<(šº<·J)”"’ê­)Ù¥®úµ‘¿¦­O#/#2]ü+)ÉË/N뼦5„Ô_5×Eñká+ÅðrÓ£áxLC%¡GîŠ4whŒ[bÓV¾ÖYz\(E;(©òB¸ñ°¶*ŠÄêÃÍ–±ä�¥ÑÒŠœ�£Â©æLine truncated
#<==
#-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEEivIt5aBoIuNHTzxwSbTGfAUneqoFAl3aW3cACgkQSbTGfAUn\neqruqA//Y9oJ46ZR8W7YB/e45bfrYxGbN7NnkvkwSPNziObYur+n1QpQEOaPTn/U\n5kFtPWHXRJzaG/A9poKn7pl1Xd7Edcu1aalfoEazZbuD37VOxIp9lnrefCAeICqj\nGv0SD96Zac91CbA+b20Q4xnqxKMi3LSI4NPjfFGy62FkSk3MS4p6Rdp0/WAKwwNj\nw7WEjQCNmLb37z+FGSzXg28aljYeteBZEthsVmGJ5QqVwMBwgj2+y5FOTzFfxmqB\nrWgjFYS0l85kgYRZv9yzdNmFs5SScwafwpT8Xmdr49tFn/+0LxXyRxX+rdODgrpV\nY4EOiQz0fd6mMMnaTDXlLSXls3JyVYmbTjeNL/9gcHmnStzJ851CJQfyQg7A+JoC\nc7nz0HbiFyTgB+PUZr1OhGj3A7287o8XQ0tqR3oa7jXIOX0OynrGplMQKr++0jE1\nBgKzjLoE9CTbjkQfICLG+aUy3S1ZyDk/BcO+5+Ytbru+qXuDsIgAdVosMfNSv9jJ\nXvOINsbRMekdejYMZv8fIkn5OEjCFHVhNpobEsCb768bjB3p7alQGECBvjHCm6dy\nXZPzl9cBMWIXcBjPTS+GZj+PIXGcu76pbsx6HBHWf+uJ+4xgOsUCVu//0AV09jvA\n0MjtLWwQ8mdRH6Wt4hsp4HKtSvQrhmljf2OnuYBgaFmcdJkN1zI=\n=C0oT\n-----END PGP SIGNATURE-----\n
#-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEECzlystnjLqtCPS4PIr4MYv+/pUgFAl+oTtQACgkQIr4MYv+/\npUhzmhAAqNeBRQuz2Z2EvWjxH/EARVKUe499ZPLsiJpl79NX3r0LWeLjf1kNAdxi\n7pR36XY8RdRwQaqNQiJ7UWzKRYXGCix71gaDyq/Qk6eZko6ts3DdicG8m12i7abi\navAtSgKzwE7o4rMqKG3iZe4AXxhCtijjIZY8Kli22XNCpY0YqUjXSNYPlhsZBWrK\nkKSmfcYxqHGrH6AKGwEJV/GbLIivYCQi6KWFfJwSOcid+479EXBuMiK8piVl6uhs\nvWGI/FcbR7cWA46Mkw7JGqJcdoyX9r8fHXrkbdIrojvQ1b4YdALZvgG6jzENCD8s\nk1KPQw+nLcC5Bax9aNO8QEn2O7vkQ5OAq19RV7ezaup2ptwe2XLuolkD3TAXr+jz\njDp0Ktc24IuVmArOyz6KZXQSIxKN3vZ8NJfdRD112/HBO/gxuZCdRQgD4c8WX9EV\nCbgrgxy02pKQdvTva/ffNgFBDOY7esRhrLLzH8lIo/556aAx6NIUy8ekAXTaFfKL\n+UenHhsYzuemapaTMhbBjqzAeiczB/fhWRr9NUajQ2x3+NDJ52/V40/fnZvYbkRx\nmvw28wCXslOh2kxQM7GgLfke8rmHN9Kek6SwHJx7RQ5OnCMKPHAo2Vb/VMx01qX4\nWeNIX9df34mD+Zy+iqJ5neXERGARPAIPeb3xYhCemgyRdWEUwvc=\n=/5DR\n-----END PGP SIGNATURE-----\n