mgmt+tools: rework FacePersistency handling in faces/create and faces/update
1. enable changing persistency in faces/update command
2. reject faces/create request if the face already exists
3. nfdc changes to support the above
Change-Id: I659906da846608a42a768f08fb110ceee1a947a7
refs: #3232
diff --git a/tests/daemon/mgmt/face-manager-update-face.t.cpp b/tests/daemon/mgmt/face-manager-update-face.t.cpp
index df1f97f..6757622 100644
--- a/tests/daemon/mgmt/face-manager-update-face.t.cpp
+++ b/tests/daemon/mgmt/face-manager-update-face.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -23,10 +23,15 @@
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "mgmt/face-manager.hpp"
+#include "face/generic-link-service.hpp"
#include "face-manager-command-fixture.hpp"
#include "nfd-manager-common-fixture.hpp"
+
#include <ndn-cxx/lp/tags.hpp>
+#include <thread>
+
namespace nfd {
namespace tests {
@@ -56,36 +61,54 @@
params.setFacePersistency(persistency);
params.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, enableLocalFields);
+ createFace(params);
+ }
+
+ void
+ createFace(const ControlParameters& createParams,
+ bool isForOnDemandFace = false)
+ {
Name commandName("/localhost/nfd/faces/create");
- commandName.append(params.wireEncode());
+ commandName.append(createParams.wireEncode());
auto command = makeInterest(commandName);
m_keyChain.sign(*command);
+ // if this creation if for on-demand face then create it on node2
+ FaceManagerCommandNode& target = isForOnDemandFace ? this->node2 : this->node1;
+
bool hasCallbackFired = false;
- signal::ScopedConnection connection = this->node1.face.onSendData.connect(
- [this, command, &hasCallbackFired] (const Data& response) {
+ signal::ScopedConnection connection = target.face.onSendData.connect(
+ [&, command, isForOnDemandFace, this] (const Data& response) {
if (!command->getName().isPrefixOf(response.getName())) {
return;
}
ControlResponse create(response.getContent().blockFromValue());
BOOST_REQUIRE_EQUAL(create.getCode(), 200);
+ BOOST_REQUIRE(create.getBody().hasWire());
- if (create.getBody().hasWire()) {
- ControlParameters faceParams(create.getBody());
- BOOST_REQUIRE(faceParams.hasFaceId());
- this->faceId = faceParams.getFaceId();
- }
- else {
- BOOST_FAIL("Face creation failed");
- }
+ ControlParameters faceParams(create.getBody());
+ BOOST_REQUIRE(faceParams.hasFaceId());
+ this->faceId = faceParams.getFaceId();
hasCallbackFired = true;
+
+ if (isForOnDemandFace) {
+ auto face = target.faceTable.get(static_cast<FaceId>(this->faceId));
+
+ // to force creation of on-demand face
+ face->sendInterest(*make_shared<Interest>("/hello/world"));
+ }
});
- this->node1.face.receive(*command);
+ target.face.receive(*command);
this->advanceClocks(time::milliseconds(1), 5);
+ if (isForOnDemandFace) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100)); // allow wallclock time for socket IO
+ this->advanceClocks(time::milliseconds(1), 5); // let node1 accept Interest and create on-demand face
+ }
+
BOOST_REQUIRE(hasCallbackFired);
}
@@ -176,29 +199,63 @@
});
}
-// TODO #3232: Expected failure until FacePersistency updating implemented
-BOOST_AUTO_TEST_CASE(UpdatePersistency)
+template<bool CAN_CHANGE_PERSISTENCY>
+class UpdatePersistencyDummyTransport : public face::Transport
{
- createFace();
+public:
+ UpdatePersistencyDummyTransport()
+ {
+ this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
+ }
- ControlParameters requestParams;
- requestParams.setFaceId(faceId);
- requestParams.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
+protected:
+ bool
+ canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const override
+ {
+ return CAN_CHANGE_PERSISTENCY;
+ }
- updateFace(requestParams, false, [] (const ControlResponse& actual) {
- ControlResponse expected(409, "Invalid fields specified");
- BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
- BOOST_TEST_MESSAGE(actual.getText());
+ void
+ doClose() override
+ {
+ }
- if (actual.getBody().hasWire()) {
- ControlParameters actualParams(actual.getBody());
+private:
+ void
+ doSend(face::Transport::Packet&& packet) override
+ {
+ }
+};
- BOOST_REQUIRE(actualParams.hasFacePersistency());
- BOOST_CHECK_EQUAL(actualParams.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
- }
- else {
- BOOST_ERROR("Response does not contain ControlParameters");
- }
+namespace mpl = boost::mpl;
+
+using UpdatePersistencyTests =
+ mpl::vector<mpl::pair<UpdatePersistencyDummyTransport<true>, CommandSuccess>,
+ mpl::pair<UpdatePersistencyDummyTransport<false>, CommandFailure<409>>>;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(UpdatePersistency, T, UpdatePersistencyTests, FaceManagerUpdateFixture)
+{
+ using TransportType = typename T::first;
+ using ResultType = typename T::second;
+
+ auto face = make_shared<face::Face>(make_unique<face::GenericLinkService>(),
+ make_unique<TransportType>());
+ this->node1.faceTable.add(face);
+
+ auto parameters = ControlParameters()
+ .setFaceId(face->getId())
+ .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
+
+ updateFace(parameters, false, [] (const ControlResponse& actual) {
+ BOOST_TEST_MESSAGE(actual.getText());
+ BOOST_CHECK_EQUAL(actual.getCode(), ResultType::getExpected().getCode());
+
+ // the response for either 200 or 409 will have a content body
+ BOOST_REQUIRE(actual.getBody().hasWire());
+
+ ControlParameters resp;
+ resp.wireDecode(actual.getBody());
+ BOOST_CHECK_EQUAL(resp.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
});
}
@@ -413,8 +470,6 @@
}
};
-namespace mpl = boost::mpl;
-
typedef mpl::vector<mpl::pair<TcpLocalFieldsEnable, CommandSuccess>,
mpl::pair<TcpLocalFieldsDisable, CommandSuccess>,
mpl::pair<UdpLocalFieldsEnable, CommandFailure<409>>,