| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /* |
| * Copyright (c) 2014-2017, Regents of the University of California. |
| * |
| * This file is part of NDN repo-ng (Next generation of NDN repository). |
| * See AUTHORS.md for complete list of repo-ng authors and contributors. |
| * |
| * repo-ng is free software: you can redistribute it and/or modify it under the terms |
| * of the GNU General Public License as published by the Free Software Foundation, |
| * either version 3 of the License, or (at your option) any later version. |
| * |
| * repo-ng 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 General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along with |
| * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include "handles/watch-handle.hpp" |
| #include "storage/sqlite-storage.hpp" |
| |
| #include "command-fixture.hpp" |
| #include "../repo-storage-fixture.hpp" |
| #include "../dataset-fixtures.hpp" |
| |
| #include <ndn-cxx/util/random.hpp> |
| |
| #include <boost/mpl/vector.hpp> |
| #include <boost/test/unit_test.hpp> |
| |
| namespace repo { |
| namespace tests { |
| |
| using ndn::time::milliseconds; |
| using ndn::time::seconds; |
| using ndn::EventId; |
| |
| // All the test cases in this test suite should be run at once. |
| BOOST_AUTO_TEST_SUITE(TestBasicCommandWatchDelete) |
| |
| const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6}; |
| |
| template<class Dataset> |
| class Fixture : public CommandFixture, public RepoStorageFixture, public Dataset |
| { |
| public: |
| Fixture() |
| : watchHandle(repoFace, *handle, keyChain, scheduler, validator) |
| , watchFace(repoFace.getIoService()) |
| { |
| Name cmdPrefix("/repo/command"); |
| repoFace.registerPrefix(cmdPrefix, nullptr, |
| [] (const Name& cmdPrefix, const std::string& reason) { |
| BOOST_FAIL("Command prefix registration error: " << reason); |
| }); |
| watchHandle.listen(cmdPrefix); |
| } |
| |
| void |
| scheduleWatchEvent(); |
| |
| void |
| onWatchInterest(const Interest& interest); |
| |
| void |
| onRegisterFailed(const std::string& reason); |
| |
| void |
| delayedInterest(); |
| |
| void |
| onWatchData(const Interest& interest, const Data& data); |
| |
| void |
| onWatchStopData(const Interest& interest, const Data& data); |
| |
| void |
| onWatchTimeout(const Interest& interest); |
| |
| void |
| sendWatchStartInterest(const Interest& interest); |
| |
| void |
| sendWatchStopInterest(const Interest& interest); |
| |
| void |
| checkWatchOk(const Interest& interest); |
| |
| public: |
| WatchHandle watchHandle; |
| Face watchFace; |
| std::map<Name, EventId> watchEvents; |
| }; |
| |
| template<class T> void |
| Fixture<T>::onWatchInterest(const Interest& interest) |
| { |
| auto data = make_shared<Data>(Name(interest.getName()) |
| .appendNumber(ndn::random::generateWord64() + 100)); |
| data->setContent(content, sizeof(content)); |
| data->setFreshnessPeriod(milliseconds(0)); |
| keyChain.sign(*data); |
| watchFace.put(*data); |
| |
| // schedule an event 50ms later to check whether watch is Ok |
| scheduler.scheduleEvent(milliseconds(10000), |
| bind(&Fixture<T>::checkWatchOk, this, |
| Interest(data->getName()))); |
| } |
| |
| |
| template<class T> void |
| Fixture<T>::onRegisterFailed(const std::string& reason) |
| { |
| BOOST_ERROR("ERROR: Failed to register prefix in local hub's daemon" + reason); |
| } |
| |
| template<class T> void |
| Fixture<T>::delayedInterest() |
| { |
| BOOST_ERROR("Fetching interest does not come. It may be satisfied in CS or something is wrong"); |
| } |
| |
| template<class T> void |
| Fixture<T>::onWatchData(const Interest& interest, const Data& data) |
| { |
| RepoCommandResponse response; |
| response.wireDecode(data.getContent().blockFromValue()); |
| |
| int statusCode = response.getStatusCode(); |
| BOOST_CHECK_EQUAL(statusCode, 100); |
| } |
| |
| template<class T> void |
| Fixture<T>::onWatchStopData(const Interest& interest, const Data& data) |
| { |
| RepoCommandResponse response; |
| response.wireDecode(data.getContent().blockFromValue()); |
| |
| int statusCode = response.getStatusCode(); |
| BOOST_CHECK_EQUAL(statusCode, 101); |
| } |
| |
| template<class T> void |
| Fixture<T>::onWatchTimeout(const Interest& interest) |
| { |
| BOOST_ERROR("Watch command timeout"); |
| } |
| |
| template<class T> void |
| Fixture<T>::sendWatchStartInterest(const Interest& watchInterest) |
| { |
| watchFace.expressInterest(watchInterest, |
| bind(&Fixture<T>::onWatchData, this, _1, _2), |
| bind(&Fixture<T>::onWatchTimeout, this, _1), // Nack |
| bind(&Fixture<T>::onWatchTimeout, this, _1)); |
| } |
| |
| template<class T> void |
| Fixture<T>::sendWatchStopInterest(const Interest& watchInterest) |
| { |
| watchFace.expressInterest(watchInterest, |
| bind(&Fixture<T>::onWatchStopData, this, _1, _2), |
| bind(&Fixture<T>::onWatchTimeout, this, _1), // Nack |
| bind(&Fixture<T>::onWatchTimeout, this, _1)); |
| } |
| |
| template<class T> void |
| Fixture<T>::checkWatchOk(const Interest& interest) |
| { |
| BOOST_TEST_MESSAGE(interest); |
| shared_ptr<Data> data = handle->readData(interest); |
| if (data) { |
| int rc = memcmp(data->getContent().value(), content, sizeof(content)); |
| BOOST_CHECK_EQUAL(rc, 0); |
| } |
| else { |
| std::cerr<<"Check Watch Failed"<<std::endl; |
| } |
| } |
| |
| template<class T> void |
| Fixture<T>::scheduleWatchEvent() |
| { |
| Name watchCommandName("/repo/command/watch/start"); |
| RepoCommandParameter watchParameter; |
| watchParameter.setName(Name("/a/b")); |
| watchParameter.setMaxInterestNum(10); |
| watchParameter.setInterestLifetime(milliseconds(50000)); |
| watchParameter.setWatchTimeout(milliseconds(1000000000)); |
| watchCommandName.append(watchParameter.wireEncode()); |
| Interest watchInterest(watchCommandName); |
| keyChain.sign(watchInterest); |
| //schedule a job to express watchInterest |
| scheduler.scheduleEvent(milliseconds(1000), |
| bind(&Fixture<T>::sendWatchStartInterest, this, watchInterest)); |
| |
| Name watchStopName("/repo/command/watch/stop"); |
| RepoCommandParameter watchStopParameter; |
| watchStopName.append(watchStopParameter.wireEncode()); |
| Interest watchStopInterest(watchStopName); |
| keyChain.sign(watchStopInterest); |
| |
| // scheduler.scheduleEvent(milliseconds(10000), |
| // bind(&Fixture<T>::sendWatchStopInterest, this, watchStopInterest)); |
| //The delayEvent will be canceled in onWatchInterest |
| watchFace.setInterestFilter(watchParameter.getName(), |
| bind(&Fixture<T>::onWatchInterest, this, _2), |
| ndn::RegisterPrefixSuccessCallback(), |
| bind(&Fixture<T>::onRegisterFailed, this, _2)); |
| } |
| |
| typedef boost::mpl::vector< BasicDataset > Dataset; |
| |
| BOOST_FIXTURE_TEST_CASE_TEMPLATE(WatchDelete, T, Dataset, Fixture<T>) |
| { |
| // schedule events |
| this->scheduler.scheduleEvent(seconds(0), |
| bind(&Fixture<T>::scheduleWatchEvent, this)); |
| |
| this->repoFace.processEvents(seconds(500)); |
| } |
| |
| BOOST_AUTO_TEST_SUITE_END() |
| |
| } // namespace tests |
| } // namespace repo |