management: add CachingPolicy to LocalControlHeader

Breaks: NFD:commit:9cfeecaa2ffad1a1be79aed2321dcc7d042ecc5f
Breaks: ndnSIM:commit:ffe2586cfc466935c0632a5a64384f0fda709086

Change-Id: Idcce2b7ee9be31b55f9ec16c17e915d93974bff4
Refs: #2183
diff --git a/tests/unit-tests/test-data.cpp b/tests/unit-tests/test-data.cpp
index 2493b89..2f8329b 100644
--- a/tests/unit-tests/test-data.cpp
+++ b/tests/unit-tests/test-data.cpp
@@ -120,6 +120,19 @@
   0x0a, 0xb6
 };
 
+const uint8_t DataWithLocalControlHeader[] = {
+  0x50, 0x29, 0x53, 0x02, 0x60, 0x00,
+  0x06, 0x23, 0x07, 0x03, 0x08, 0x01, 0x41, 0x14, 0x04, 0x19, 0x02, 0x27, 0x10, 0x15,
+  0x09, 0x73, 0x6F, 0x6D, 0x65, 0x44, 0x61, 0x74, 0x61, 0x00, 0x16, 0x05, 0x1B, 0x01,
+  0x01, 0x1C, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
+};
+
+const uint8_t DataWithoutLocalControlHeader[] = {
+  0x06, 0x23, 0x07, 0x03, 0x08, 0x01, 0x41, 0x14, 0x04, 0x19, 0x02, 0x27, 0x10, 0x15,
+  0x09, 0x73, 0x6F, 0x6D, 0x65, 0x44, 0x61, 0x74, 0x61, 0x00, 0x16, 0x05, 0x1B, 0x01,
+  0x01, 0x1C, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
+};
+
 BOOST_AUTO_TEST_CASE(DataEqualityChecks)
 {
   using namespace time;
@@ -200,6 +213,114 @@
   BOOST_CHECK_EQUAL(a != b, false);
 }
 
+BOOST_AUTO_TEST_CASE(EncodeWithLocalHeader)
+{
+  Data data("ndn:/A");
+  data.setFreshnessPeriod(time::seconds(10));
+  static const uint8_t someData[] = "someData";
+  data.setContent(someData, sizeof(someData));
+  data.setSignature(SignatureSha256WithRsa());
+  data.setCachingPolicy(nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
+
+  BOOST_CHECK(!data.hasWire());
+
+  Block headerBlock =
+    data.getLocalControlHeader().wireEncode(data, nfd::LocalControlHeader::ENCODE_CACHING_POLICY);
+
+  BOOST_CHECK(data.hasWire());
+  BOOST_CHECK(headerBlock.hasWire());
+
+  BOOST_CHECK_NE(headerBlock.wire(), data.wireEncode().wire());
+  BOOST_CHECK_NE(headerBlock.size(), data.wireEncode().size());
+  BOOST_CHECK_EQUAL(headerBlock.size(), 6);
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(DataWithLocalControlHeader,
+                                DataWithLocalControlHeader + 6,
+                                headerBlock.begin(), headerBlock.end());
+
+  data.setFreshnessPeriod(time::seconds(1000));
+
+  Block updatedHeaderBlock = data.getLocalControlHeader()
+                                 .wireEncode(data, nfd::LocalControlHeader::ENCODE_CACHING_POLICY);
+  BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 6);
+
+  // only length should have changed
+  BOOST_CHECK_EQUAL_COLLECTIONS(updatedHeaderBlock.begin() + 2, updatedHeaderBlock.end(),
+                                headerBlock.begin() + 2,        headerBlock.end());
+
+  // adding IncomingFaceId
+  data.setIncomingFaceId(10);
+  updatedHeaderBlock =
+    data.getLocalControlHeader().wireEncode(data, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID
+                                                  | nfd::LocalControlHeader::ENCODE_CACHING_POLICY);
+  BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 9);
+
+  // masking CachingPolicy
+  updatedHeaderBlock = data.getLocalControlHeader()
+                           .wireEncode(data, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID);
+  BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 5);
+
+  // masking everything
+  BOOST_CHECK_THROW(data.getLocalControlHeader()
+                        .wireEncode(data, nfd::LocalControlHeader::ENCODE_NONE),
+                    nfd::LocalControlHeader::Error);
+}
+
+BOOST_AUTO_TEST_CASE(DecodeWithLocalHeader)
+{
+  Block wireBlock(DataWithLocalControlHeader, sizeof(DataWithLocalControlHeader));
+  const Block& payload = nfd::LocalControlHeader::getPayload(wireBlock);
+  BOOST_REQUIRE_NE(&payload, &wireBlock);
+
+  BOOST_CHECK_EQUAL(payload.type(), static_cast<uint32_t>(tlv::Data));
+  BOOST_CHECK_EQUAL(wireBlock.type(), static_cast<uint32_t>(tlv::nfd::LocalControlHeader));
+
+  Data data(payload);
+  BOOST_CHECK(!data.getLocalControlHeader().hasCachingPolicy());
+  BOOST_CHECK(!data.getLocalControlHeader().hasIncomingFaceId());
+
+  data.getLocalControlHeader().wireDecode(wireBlock);
+
+  BOOST_CHECK_EQUAL(data.getLocalControlHeader()
+                        .wireEncode(data, nfd::LocalControlHeader::ENCODE_CACHING_POLICY).size(),
+                    6);
+
+  BOOST_CHECK(data.getLocalControlHeader().hasCachingPolicy());
+  BOOST_CHECK(!data.getLocalControlHeader().hasIncomingFaceId());
+
+  BOOST_CHECK_THROW(data.getLocalControlHeader()
+                        .wireEncode(data, nfd::LocalControlHeader::ENCODE_NONE),
+                    nfd::LocalControlHeader::Error);
+
+  BOOST_CHECK_THROW(data.getLocalControlHeader()
+                        .wireEncode(data, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID),
+                    nfd::LocalControlHeader::Error);
+
+  BOOST_CHECK_NO_THROW(data.getLocalControlHeader()
+                           .wireEncode(data, nfd::LocalControlHeader::ENCODE_CACHING_POLICY));
+  BOOST_CHECK_NO_THROW(
+    data.getLocalControlHeader().wireEncode(data, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                                  nfd::LocalControlHeader::ENCODE_CACHING_POLICY));
+
+  BOOST_CHECK_NE((void*)data.getLocalControlHeader()
+                            .wireEncode(data, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                              nfd::LocalControlHeader::ENCODE_CACHING_POLICY)
+                            .wire(),
+                 (void*)wireBlock.wire());
+
+  BOOST_CHECK_EQUAL(data.getLocalControlHeader()
+                        .wireEncode(data, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                          nfd::LocalControlHeader::ENCODE_CACHING_POLICY).size(),
+                    6);
+}
+
+BOOST_AUTO_TEST_CASE(DecodeWithoutLocalHeader)
+{
+  Block wireBlock(DataWithoutLocalControlHeader, sizeof(DataWithoutLocalControlHeader));
+  const Block& payload = nfd::LocalControlHeader::getPayload(wireBlock);
+  BOOST_CHECK_EQUAL(&payload, &wireBlock);
+}
+
 class TestDataFixture
 {
 public:
diff --git a/tests/unit-tests/test-face.cpp b/tests/unit-tests/test-face.cpp
index b519d5c..e901e54 100644
--- a/tests/unit-tests/test-face.cpp
+++ b/tests/unit-tests/test-face.cpp
@@ -367,6 +367,7 @@
   Interest i("/Hello/World");
   i.setNextHopFaceId(1000);
   i.setIncomingFaceId(2000);
+  i.getLocalControlHeader().setCachingPolicy(nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
 
   face->expressInterest(i, bind([]{}), bind([]{}));
   advanceClocks(time::milliseconds(10));
@@ -375,6 +376,7 @@
   // only NextHopFaceId is allowed to go out
   BOOST_CHECK(face->sentInterests[0].getLocalControlHeader().hasNextHopFaceId());
   BOOST_CHECK(!face->sentInterests[0].getLocalControlHeader().hasIncomingFaceId());
+  BOOST_CHECK(!face->sentInterests[0].getLocalControlHeader().hasCachingPolicy());
   BOOST_CHECK_EQUAL(face->sentInterests[0].getNextHopFaceId(), 1000);
 }
 
@@ -384,8 +386,11 @@
                           [] (const InterestFilter&, const Interest& i) {
                             BOOST_CHECK(i.getLocalControlHeader().hasNextHopFaceId());
                             BOOST_CHECK(i.getLocalControlHeader().hasIncomingFaceId());
+                            BOOST_CHECK(i.getLocalControlHeader().hasCachingPolicy());
                             BOOST_CHECK_EQUAL(i.getNextHopFaceId(), 1000);
                             BOOST_CHECK_EQUAL(i.getIncomingFaceId(), 2000);
+                            BOOST_CHECK_EQUAL(i.getLocalControlHeader().getCachingPolicy(),
+                                              nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
                           },
                           bind([]{}),
                           bind([] {
@@ -396,6 +401,7 @@
   Interest i("/Hello/World/!");
   i.setNextHopFaceId(1000);
   i.setIncomingFaceId(2000);
+  i.getLocalControlHeader().setCachingPolicy(nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
 
   face->receive(i);
   advanceClocks(time::milliseconds(10));
@@ -405,8 +411,8 @@
 {
   shared_ptr<Data> d = util::makeData("/Bye/World/!");
   d->setIncomingFaceId(2000);
-  d->getLocalControlHeader().setNextHopFaceId(1000); // setNextHopFaceId is intentionally
-                                                     // not exposed directly
+  d->getLocalControlHeader().setNextHopFaceId(1000);
+  d->setCachingPolicy(nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
 
   face->put(*d);
   advanceClocks(time::milliseconds(10));
@@ -414,6 +420,9 @@
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
   BOOST_CHECK(!face->sentDatas[0].getLocalControlHeader().hasNextHopFaceId());
   BOOST_CHECK(!face->sentDatas[0].getLocalControlHeader().hasIncomingFaceId());
+  BOOST_CHECK(face->sentDatas[0].getLocalControlHeader().hasCachingPolicy());
+  BOOST_CHECK_EQUAL(face->sentDatas[0].getCachingPolicy(),
+                    nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
 }
 
 BOOST_AUTO_TEST_CASE(ReceiveDataWithLocalControlHeader)
@@ -422,6 +431,9 @@
                         [&] (const Interest& i, const Data& d) {
                           BOOST_CHECK(d.getLocalControlHeader().hasNextHopFaceId());
                           BOOST_CHECK(d.getLocalControlHeader().hasIncomingFaceId());
+                          BOOST_CHECK(d.getLocalControlHeader().hasCachingPolicy());
+                          BOOST_CHECK_EQUAL(d.getCachingPolicy(),
+                                            nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
                           BOOST_CHECK_EQUAL(d.getIncomingFaceId(), 2000);
                           BOOST_CHECK_EQUAL(d.getLocalControlHeader().getNextHopFaceId(), 1000);
                         },
@@ -433,8 +445,8 @@
 
   shared_ptr<Data> d = util::makeData("/Hello/World/!");
   d->setIncomingFaceId(2000);
-  d->getLocalControlHeader().setNextHopFaceId(1000); // setNextHopFaceId is intentionally
-                                                     // not exposed directly
+  d->getLocalControlHeader().setNextHopFaceId(1000);
+  d->setCachingPolicy(nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
   face->receive(*d);
 
   advanceClocks(time::milliseconds(10), 100);
diff --git a/tests/unit-tests/test-interest.cpp b/tests/unit-tests/test-interest.cpp
index 71d6d29..7151c56 100644
--- a/tests/unit-tests/test-interest.cpp
+++ b/tests/unit-tests/test-interest.cpp
@@ -365,7 +365,10 @@
 
   BOOST_CHECK(!interest.hasWire());
 
-  Block headerBlock = interest.getLocalControlHeader().wireEncode(interest, true, true);
+  Block headerBlock =
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP);
 
   BOOST_CHECK(interest.hasWire());
   BOOST_CHECK(headerBlock.hasWire());
@@ -380,7 +383,10 @@
 
   interest.setNonce(1000);
 
-  Block updatedHeaderBlock = interest.getLocalControlHeader().wireEncode(interest, true, true);
+  Block updatedHeaderBlock =
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP);
   BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 5);
 
   // only length should have changed
@@ -389,30 +395,43 @@
 
   // updating IncomingFaceId that keeps the length
   interest.setIncomingFaceId(100);
-  updatedHeaderBlock = interest.getLocalControlHeader().wireEncode(interest, true, true);
+  updatedHeaderBlock =
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP);
   BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 5);
   BOOST_CHECK_NE(*(updatedHeaderBlock.begin() + 4), *(headerBlock.begin() + 4));
 
   // updating IncomingFaceId that increases the length by 2
   interest.setIncomingFaceId(1000);
-  updatedHeaderBlock = interest.getLocalControlHeader().wireEncode(interest, true, true);
+  updatedHeaderBlock =
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP);
   BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 6);
 
   // adding NextHopId
   interest.setNextHopFaceId(1);
-  updatedHeaderBlock = interest.getLocalControlHeader().wireEncode(interest, true, true);
+  updatedHeaderBlock =
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP);
   BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 9);
 
   // masking IncomingFaceId
-  updatedHeaderBlock = interest.getLocalControlHeader().wireEncode(interest, false, true);
+  updatedHeaderBlock = interest.getLocalControlHeader()
+                               .wireEncode(interest, nfd::LocalControlHeader::ENCODE_NEXT_HOP);
   BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 5);
 
   // masking NextHopId
-  updatedHeaderBlock = interest.getLocalControlHeader().wireEncode(interest, true, false);
+  updatedHeaderBlock =
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID);
   BOOST_CHECK_EQUAL(updatedHeaderBlock.size(), 6);
 
   // masking everything
-  BOOST_CHECK_THROW(interest.getLocalControlHeader().wireEncode(interest, false, false),
+  BOOST_CHECK_THROW(interest.getLocalControlHeader()
+                            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_NONE),
                     nfd::LocalControlHeader::Error);
 }
 
@@ -432,24 +451,42 @@
 
   BOOST_REQUIRE_NO_THROW(interest.getLocalControlHeader().wireDecode(wireBlock));
 
-  BOOST_CHECK_EQUAL(interest.getLocalControlHeader().wireEncode(interest, true, true).size(), 5);
+  BOOST_CHECK_EQUAL(
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP).size(),
+    5);
 
   BOOST_CHECK_EQUAL(interest.getIncomingFaceId(), 10);
   BOOST_CHECK(!interest.getLocalControlHeader().hasNextHopFaceId());
 
-  BOOST_CHECK_THROW(interest.getLocalControlHeader().wireEncode(interest, false, false),
+  BOOST_CHECK_THROW(interest.getLocalControlHeader()
+                            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_NONE),
                     nfd::LocalControlHeader::Error);
 
-  BOOST_CHECK_THROW(interest.getLocalControlHeader().wireEncode(interest, false, true),
+  BOOST_CHECK_THROW(interest.getLocalControlHeader()
+                            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_NEXT_HOP),
                     nfd::LocalControlHeader::Error);
 
-  BOOST_CHECK_NO_THROW(interest.getLocalControlHeader().wireEncode(interest, true, false));
-  BOOST_CHECK_NO_THROW(interest.getLocalControlHeader().wireEncode(interest, true, true));
+  BOOST_CHECK_NO_THROW(
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID));
+  BOOST_CHECK_NO_THROW(
+    interest.getLocalControlHeader()
+            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP));
 
-  BOOST_CHECK_NE((void*)interest.getLocalControlHeader().wireEncode(interest, true, true).wire(),
-                 (void*)wireBlock.wire());
+  BOOST_CHECK_NE(
+    (void*)interest.getLocalControlHeader()
+                   .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                         nfd::LocalControlHeader::ENCODE_NEXT_HOP)
+                   .wire(),
+    (void*)wireBlock.wire());
 
-  BOOST_CHECK_EQUAL(interest.getLocalControlHeader().wireEncode(interest, true, true).size(), 5);
+  BOOST_CHECK_EQUAL(interest.getLocalControlHeader()
+                            .wireEncode(interest, nfd::LocalControlHeader::ENCODE_INCOMING_FACE_ID |
+                                                  nfd::LocalControlHeader::ENCODE_NEXT_HOP).size(),
+                    5);
 }
 
 BOOST_AUTO_TEST_CASE(DecodeWithoutLocalHeader)