change default FreshnessPeriod to 0 ms

set InterestLifetime to default value when not present

do not encode ChildSelector if at default value

refs #3944

Change-Id: I4a3ebf5512d0d2270798ed212eab7903ba8b8ed0
diff --git a/src/interest.cpp b/src/interest.cpp
index 17a7aa4..80434ab 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -36,14 +36,14 @@
               "Interest::Error must inherit from tlv::Error");
 
 Interest::Interest()
-  : m_interestLifetime(time::milliseconds::min())
+  : m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
   , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
 {
 }
 
 Interest::Interest(const Name& name)
   : m_name(name)
-  , m_interestLifetime(time::milliseconds::min())
+  , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
   , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
 {
 }
@@ -222,6 +222,17 @@
           this->getSelectors() == other.getSelectors());
 }
 
+Interest&
+Interest::setInterestLifetime(time::milliseconds interestLifetime)
+{
+  if (interestLifetime < time::milliseconds::zero()) {
+    BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
+  }
+  m_interestLifetime = interestLifetime;
+  m_wire.reset();
+  return *this;
+}
+
 template<encoding::Tag TAG>
 size_t
 Interest::wireEncode(EncodingImpl<TAG>& encoder) const
@@ -251,23 +262,20 @@
   }
 
   // InterestLifetime
-  if (getInterestLifetime() >= time::milliseconds::zero() &&
-      getInterestLifetime() != DEFAULT_INTEREST_LIFETIME)
-    {
-      totalLength += prependNonNegativeIntegerBlock(encoder,
-                                                    tlv::InterestLifetime,
-                                                    getInterestLifetime().count());
-    }
+  if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
+    totalLength += prependNonNegativeIntegerBlock(encoder,
+                                                  tlv::InterestLifetime,
+                                                  getInterestLifetime().count());
+  }
 
   // Nonce
   getNonce(); // to ensure that Nonce is properly set
   totalLength += encoder.prependBlock(m_nonce);
 
   // Selectors
-  if (hasSelectors())
-    {
-      totalLength += getSelectors().wireEncode(encoder);
-    }
+  if (hasSelectors()) {
+    totalLength += getSelectors().wireEncode(encoder);
+  }
 
   // Name
   totalLength += getName().wireEncode(encoder);
@@ -469,7 +477,7 @@
     os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
     delim = '&';
   }
-  if (interest.getChildSelector() >= 0) {
+  if (interest.getChildSelector() != DEFAULT_CHILD_SELECTOR) {
     os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
     delim = '&';
   }
@@ -477,8 +485,7 @@
     os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
     delim = '&';
   }
-  if (interest.getInterestLifetime() >= time::milliseconds::zero()
-      && interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
+  if (interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
     os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime().count();
     delim = '&';
   }
diff --git a/src/interest.hpp b/src/interest.hpp
index 8d3f29b..e98747e 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -242,13 +242,12 @@
     return m_interestLifetime;
   }
 
+  /**
+   * @brief Set Interest's lifetime
+   * @throw std::invalid_argument specified lifetime is < 0
+   */
   Interest&
-  setInterestLifetime(const time::milliseconds& interestLifetime)
-  {
-    m_interestLifetime = interestLifetime;
-    m_wire.reset();
-    return *this;
-  }
+  setInterestLifetime(time::milliseconds interestLifetime);
 
   /** @brief Check if Nonce set
    */
diff --git a/src/meta-info.cpp b/src/meta-info.cpp
index 0fd6923..41ad0f7 100644
--- a/src/meta-info.cpp
+++ b/src/meta-info.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,7 +34,7 @@
 
 MetaInfo::MetaInfo()
   : m_type(tlv::ContentType_Blob)
-  , m_freshnessPeriod(-1)
+  , m_freshnessPeriod(DEFAULT_FRESHNESS_PERIOD)
 {
 }
 
@@ -52,8 +52,11 @@
 }
 
 MetaInfo&
-MetaInfo::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
+MetaInfo::setFreshnessPeriod(time::milliseconds freshnessPeriod)
 {
+  if (freshnessPeriod < time::milliseconds::zero()) {
+    BOOST_THROW_EXCEPTION(std::invalid_argument("FreshnessPeriod must be >= 0"));
+  }
   m_wire.reset();
   m_freshnessPeriod = freshnessPeriod;
   return *this;
@@ -143,23 +146,20 @@
   }
 
   // FinalBlockId
-  if (!m_finalBlockId.empty())
-    {
-      totalLength += prependNestedBlock(encoder, tlv::FinalBlockId, m_finalBlockId);
-    }
+  if (!m_finalBlockId.empty()) {
+    totalLength += prependNestedBlock(encoder, tlv::FinalBlockId, m_finalBlockId);
+  }
 
   // FreshnessPeriod
-  if (m_freshnessPeriod >= time::milliseconds::zero())
-    {
-      totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
-                                                    m_freshnessPeriod.count());
-    }
+  if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD) {
+    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
+                                                  m_freshnessPeriod.count());
+  }
 
   // ContentType
-  if (m_type != tlv::ContentType_Blob)
-    {
-      totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ContentType, m_type);
-    }
+  if (m_type != tlv::ContentType_Blob) {
+    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ContentType, m_type);
+  }
 
   totalLength += encoder.prependVarNumber(totalLength);
   totalLength += encoder.prependVarNumber(tlv::MetaInfo);
@@ -218,7 +218,7 @@
     ++val;
   }
   else {
-    m_freshnessPeriod = time::milliseconds::min();
+    m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD;
   }
 
   // FinalBlockId
@@ -248,7 +248,7 @@
   os << "ContentType: " << info.getType();
 
   // FreshnessPeriod
-  if (info.getFreshnessPeriod() >= time::milliseconds::zero()) {
+  if (info.getFreshnessPeriod() > time::milliseconds::zero()) {
     os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
   }
 
diff --git a/src/meta-info.hpp b/src/meta-info.hpp
index 798acd1..bec2275 100644
--- a/src/meta-info.hpp
+++ b/src/meta-info.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,6 +31,8 @@
 
 namespace ndn {
 
+const time::milliseconds DEFAULT_FRESHNESS_PERIOD = time::milliseconds::zero();
+
 /**
  * An MetaInfo holds the meta info which is signed inside the data packet.
  *
@@ -97,8 +99,11 @@
   const time::milliseconds&
   getFreshnessPeriod() const;
 
+  /** @brief set FreshnessPeriod
+   *  @throw std::invalid_argument specified FreshnessPeriod is < 0
+   */
   MetaInfo&
-  setFreshnessPeriod(const time::milliseconds& freshnessPeriod);
+  setFreshnessPeriod(time::milliseconds freshnessPeriod);
 
   const name::Component&
   getFinalBlockId() const;
diff --git a/src/selectors.cpp b/src/selectors.cpp
index 7b46b1e..dc741a3 100644
--- a/src/selectors.cpp
+++ b/src/selectors.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -35,7 +35,7 @@
 Selectors::Selectors()
   : m_minSuffixComponents(-1)
   , m_maxSuffixComponents(-1)
-  , m_childSelector(-1)
+  , m_childSelector(DEFAULT_CHILD_SELECTOR)
   , m_mustBeFresh(false)
 {
 }
@@ -78,7 +78,7 @@
   }
 
   // ChildSelector
-  if (getChildSelector() >= 0) {
+  if (getChildSelector() != DEFAULT_CHILD_SELECTOR) {
     totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ChildSelector, getChildSelector());
   }
 
@@ -171,6 +171,9 @@
   if (val != m_wire.elements_end()) {
     m_childSelector = readNonNegativeInteger(*val);
   }
+  else {
+    m_childSelector = DEFAULT_CHILD_SELECTOR;
+  }
 
   // MustBeFresh
   val = m_wire.find(tlv::MustBeFresh);
@@ -214,6 +217,9 @@
 Selectors&
 Selectors::setChildSelector(int childSelector)
 {
+  if (childSelector != 0 && childSelector != 1) {
+    BOOST_THROW_EXCEPTION(std::invalid_argument("ChildSelector must be 0 or 1"));
+  }
   m_childSelector = childSelector;
   m_wire.reset();
   return *this;
diff --git a/src/selectors.hpp b/src/selectors.hpp
index 9a1d8a4..960947f 100644
--- a/src/selectors.hpp
+++ b/src/selectors.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -28,6 +28,8 @@
 
 namespace ndn {
 
+const int DEFAULT_CHILD_SELECTOR = 0;
+
 /**
  * @brief Abstraction implementing Interest selectors
  */
@@ -117,6 +119,10 @@
     return m_childSelector;
   }
 
+  /**
+   * @brief set ChildSelector
+   * @throw std::invalid_argument ChildSelector not 0 or 1
+   */
   Selectors&
   setChildSelector(int childSelector);
 
diff --git a/tests/unit-tests/interest.t.cpp b/tests/unit-tests/interest.t.cpp
index aee782f..3e31438 100644
--- a/tests/unit-tests/interest.t.cpp
+++ b/tests/unit-tests/interest.t.cpp
@@ -543,6 +543,114 @@
           0x01
 };
 
+BOOST_AUTO_TEST_CASE(DefaultValues)
+{
+  Interest i;
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  BOOST_CHECK(!i.hasSelectedDelegation());
+}
+
+BOOST_AUTO_TEST_CASE(EncodeChildSelector)
+{
+  Interest i;
+  i.setName("/local/ndn/prefix");
+  i.setNonce(1);
+  BOOST_CHECK_EQUAL(i.getChildSelector(), 0);
+  BOOST_CHECK_THROW(i.setChildSelector(-1), std::invalid_argument);
+  BOOST_CHECK_THROW(i.setChildSelector(2), std::invalid_argument);
+  BOOST_CHECK_NO_THROW(i.setChildSelector(1));
+  BOOST_CHECK_EQUAL(i.getChildSelector(), 1);
+  BOOST_CHECK_NO_THROW(i.setChildSelector(0));
+  BOOST_CHECK_EQUAL(i.getChildSelector(), 0);
+
+  const uint8_t expectedDefault[] = {
+    0x05, 0x1e, // MetaInfo
+          0x07, 0x14, // Name
+                0x08, 0x5, // NameComponent
+                      0x6c, 0x6f, 0x63, 0x61, 0x6c,
+                0x08, 0x3, // NameComponent
+                      0x6e, 0x64, 0x6e,
+                0x08, 0x6, // NameComponent
+                      0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+          0x09, 0x00, // Selectors
+          0x0a, 0x04, // Nonce
+                0x01, 0x00, 0x00, 0x00, // 1
+  };
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(i.wireEncode().begin(), i.wireEncode().end(),
+                                expectedDefault, expectedDefault + sizeof(expectedDefault));
+
+  const uint8_t expected1[] = {
+    0x05, 0x21, // MetaInfo
+          0x07, 0x14, // Name
+                0x08, 0x5, // NameComponent
+                      0x6c, 0x6f, 0x63, 0x61, 0x6c,
+                0x08, 0x3, // NameComponent
+                      0x6e, 0x64, 0x6e,
+                0x08, 0x6, // NameComponent
+                      0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+          0x09, 0x03, // Selectors
+                0x11, 0x01, // ChildSelector
+                      0x01, // 1
+          0x0a, 0x04, // Nonce
+                0x01, 0x00, 0x00, 0x00, // 1
+  };
+
+  i.setChildSelector(1);
+  BOOST_CHECK_EQUAL_COLLECTIONS(i.wireEncode().begin(), i.wireEncode().end(),
+                                expected1, expected1 + sizeof(expected1));
+}
+
+BOOST_AUTO_TEST_CASE(EncodeInterestLifetime)
+{
+  Interest i;
+  i.setName("/local/ndn/prefix");
+  i.setNonce(1);
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  BOOST_CHECK_THROW(i.setInterestLifetime(time::milliseconds(-1)), std::invalid_argument);
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  BOOST_CHECK_NO_THROW(i.setInterestLifetime(time::milliseconds(1)));
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds(1));
+  BOOST_CHECK_NO_THROW(i.setInterestLifetime(DEFAULT_INTEREST_LIFETIME));
+
+  const uint8_t expectedDefault[] = {
+    0x05, 0x1e, // MetaInfo
+          0x07, 0x14, // Name
+                0x08, 0x5, // NameComponent
+                      0x6c, 0x6f, 0x63, 0x61, 0x6c,
+                0x08, 0x3, // NameComponent
+                      0x6e, 0x64, 0x6e,
+                0x08, 0x6, // NameComponent
+                      0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+          0x09, 0x00, // Selectors
+          0x0a, 0x04, // Nonce
+                0x01, 0x00, 0x00, 0x00, // 1
+  };
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(i.wireEncode().begin(), i.wireEncode().end(),
+                                expectedDefault, expectedDefault + sizeof(expectedDefault));
+
+  const uint8_t expected1000ms[] = {
+    0x05, 0x22, // MetaInfo
+          0x07, 0x14, // Name
+                0x08, 0x5, // NameComponent
+                      0x6c, 0x6f, 0x63, 0x61, 0x6c,
+                0x08, 0x3, // NameComponent
+                      0x6e, 0x64, 0x6e,
+                0x08, 0x6, // NameComponent
+                      0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+          0x09, 0x00, // Selectors
+          0x0a, 0x04, // Nonce
+                0x01, 0x00, 0x00, 0x00, // 1
+          0x0c, 0x02, // InterestLifetime
+                0x03, 0xe8
+  };
+
+  BOOST_CHECK_NO_THROW(i.setInterestLifetime(time::milliseconds(1000)));
+  BOOST_CHECK_EQUAL_COLLECTIONS(i.wireEncode().begin(), i.wireEncode().end(),
+                                expected1000ms, expected1000ms + sizeof(expected1000ms));
+}
+
 BOOST_AUTO_TEST_CASE(InterestEqualityChecks)
 {
   // Interest ::= INTEREST-TYPE TLV-LENGTH
@@ -959,7 +1067,7 @@
   i.setNonce(1);
 
   BOOST_CHECK_EQUAL(i.hasWire(), false);
-  const Block &wire = i.wireEncode();
+  const Block& wire = i.wireEncode();
   BOOST_CHECK_EQUAL(i.hasWire(), true);
 
   BOOST_CHECK_EQUAL_COLLECTIONS(Interest1, Interest1 + sizeof(Interest1),
diff --git a/tests/unit-tests/meta-info.t.cpp b/tests/unit-tests/meta-info.t.cpp
index ad83119..51412c5 100644
--- a/tests/unit-tests/meta-info.t.cpp
+++ b/tests/unit-tests/meta-info.t.cpp
@@ -193,6 +193,56 @@
   BOOST_CHECK_THROW(info.addAppMetaInfo(makeNonNegativeIntegerBlock(253, 1000)), MetaInfo::Error);
 }
 
+BOOST_AUTO_TEST_CASE(EncodeDecodeFreshnessPeriod)
+{
+  const uint8_t expectedDefault[] = {
+    0x14, 0x00, // MetaInfo
+  };
+
+  const uint8_t expected1000ms[] = {
+    0x14, 0x04, // MetaInfo
+          0x19, 0x02, // FreshnessPeriod
+                0x03, 0xe8 // 1000ms
+  };
+
+  MetaInfo info;
+  BOOST_CHECK_EQUAL_COLLECTIONS(info.wireEncode().begin(), info.wireEncode().end(),
+                                expectedDefault, expectedDefault + sizeof(expectedDefault));
+
+  info.setFreshnessPeriod(time::milliseconds::zero());
+  BOOST_CHECK_EQUAL_COLLECTIONS(info.wireEncode().begin(), info.wireEncode().end(),
+                                expectedDefault, expectedDefault + sizeof(expectedDefault));
+
+  info.setFreshnessPeriod(time::milliseconds(1000));
+  BOOST_CHECK_EQUAL_COLLECTIONS(info.wireEncode().begin(), info.wireEncode().end(),
+                                expected1000ms, expected1000ms + sizeof(expected1000ms));
+
+  const uint8_t inputDefault[] = {
+    0x14, 0x03, // MetaInfo
+          0x19, 0x01, // FreshnessPeriod
+                0x00  // 0ms
+  };
+
+  const uint8_t input2000ms[] = {
+    0x14, 0x04, // MetaInfo
+          0x19, 0x02, // FreshnessPeriod
+                0x07, 0xd0 // 2000ms
+  };
+
+  Block inputDefaultBlock(inputDefault, sizeof(inputDefault));
+  BOOST_CHECK_NO_THROW(info.wireDecode(inputDefaultBlock));
+  BOOST_CHECK_EQUAL(info.getFreshnessPeriod(), time::milliseconds::zero());
+
+  Block input2000msBlock(input2000ms, sizeof(input2000ms));
+  BOOST_CHECK_NO_THROW(info.wireDecode(input2000msBlock));
+  BOOST_CHECK_EQUAL(info.getFreshnessPeriod(), time::milliseconds(2000));
+
+  BOOST_CHECK_NO_THROW(info.setFreshnessPeriod(time::milliseconds(10000)));
+  BOOST_CHECK_EQUAL(info.getFreshnessPeriod(), time::milliseconds(10000));
+  BOOST_CHECK_THROW(info.setFreshnessPeriod(time::milliseconds(-1)), std::invalid_argument);
+  BOOST_CHECK_EQUAL(info.getFreshnessPeriod(), time::milliseconds(10000));
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestMetaInfo
 
 } // namespace tests