interest: improve setApplicationParameters() behavior

Refs: #4658
Change-Id: Iecc476613d81b2958198a222717e9b5b522d72e2
diff --git a/docs/doxygen.conf.in b/docs/doxygen.conf.in
index e7a7315..fd5237b 100644
--- a/docs/doxygen.conf.in
+++ b/docs/doxygen.conf.in
@@ -2058,10 +2058,10 @@
                          NDN_LOG_MEMBER_DECL_SPECIALIZED(x)= \
                          NDN_LOG_MEMBER_INIT(x,y)= \
                          NDN_LOG_MEMBER_INIT_SPECIALIZED(x,y)= \
-                         PUBLIC_WITH_TESTS_ELSE_PROTECTED=protected \
-                         PUBLIC_WITH_TESTS_ELSE_PRIVATE=private \
-                         PROTECTED_WITH_TESTS_ELSE_PRIVATE=private \
-                         VIRTUAL_WITH_TESTS=
+                         NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PROTECTED=protected \
+                         NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE=private \
+                         NDN_CXX_PROTECTED_WITH_TESTS_ELSE_PRIVATE=private \
+                         NDN_CXX_VIRTUAL_WITH_TESTS=
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
 # tag can be used to specify a list of macro names that should be expanded. The
diff --git a/ndn-cxx/interest.cpp b/ndn-cxx/interest.cpp
index 6ac6f4f..38858ca 100644
--- a/ndn-cxx/interest.cpp
+++ b/ndn-cxx/interest.cpp
@@ -598,7 +598,10 @@
 Interest&
 Interest::setApplicationParameters(const Block& parameters)
 {
-  if (parameters.type() == tlv::ApplicationParameters) {
+  if (parameters.empty()) {
+    m_parameters = Block(tlv::ApplicationParameters);
+  }
+  else if (parameters.type() == tlv::ApplicationParameters) {
     m_parameters = parameters;
   }
   else {
@@ -611,6 +614,9 @@
 Interest&
 Interest::setApplicationParameters(const uint8_t* buffer, size_t bufferSize)
 {
+  if (buffer == nullptr && bufferSize != 0) {
+    NDN_THROW(std::invalid_argument("ApplicationParameters buffer cannot be nullptr"));
+  }
   m_parameters = makeBinaryBlock(tlv::ApplicationParameters, buffer, bufferSize);
   m_wire.reset();
   return *this;
@@ -619,6 +625,9 @@
 Interest&
 Interest::setApplicationParameters(ConstBufferPtr buffer)
 {
+  if (buffer == nullptr) {
+    NDN_THROW(std::invalid_argument("ApplicationParameters buffer cannot be nullptr"));
+  }
   m_parameters = Block(tlv::ApplicationParameters, std::move(buffer));
   m_wire.reset();
   return *this;
diff --git a/ndn-cxx/interest.hpp b/ndn-cxx/interest.hpp
index cb27a73..9f16aff 100644
--- a/ndn-cxx/interest.hpp
+++ b/ndn-cxx/interest.hpp
@@ -301,10 +301,11 @@
 
   /** @brief Set ApplicationParameters from a Block
    *
-   *  If the block's TLV-TYPE is ApplicationParameters, it will be used directly as
-   *  this Interest's ApplicationParameters element.
-   *  If the block's TLV-TYPE is not ApplicationParameters, it will be nested into
-   *  an ApplicationParameters element.
+   *  If the block is default-constructed, this will set a zero-length
+   *  ApplicationParameters element.
+   *  Else, if the block's TLV-TYPE is ApplicationParameters, it will be
+   *  used directly as this Interest's ApplicationParameters element.
+   *  Else, the block will be nested into an ApplicationParameters element.
    *  @return a reference to this Interest
    */
   Interest&
@@ -321,7 +322,7 @@
 
   /** @brief Set ApplicationParameters from a wire buffer
    *
-   *  @param buffer buffer containing the parameters
+   *  @param buffer buffer containing the parameters, must not be nullptr
    *  @return a reference to this Interest
    */
   Interest&
diff --git a/tests/unit/interest.t.cpp b/tests/unit/interest.t.cpp
index 53215d5..4523d07 100644
--- a/tests/unit/interest.t.cpp
+++ b/tests/unit/interest.t.cpp
@@ -590,14 +590,27 @@
   i.unsetApplicationParameters();
   BOOST_CHECK(!i.hasApplicationParameters());
 
-  i.setApplicationParameters("2401C0"_block); // Block overload
+  // Block overload
+  i.setApplicationParameters(Block{});
+  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2400"_block);
+  i.setApplicationParameters("2401C0"_block);
   BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2401C0"_block);
-  i.setApplicationParameters(PARAMETERS1, sizeof(PARAMETERS1)); // raw buffer overload
-  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2401C1"_block);
-  i.setApplicationParameters(make_shared<Buffer>(PARAMETERS2, sizeof(PARAMETERS2))); // ConstBufferPtr overload
-  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2401C2"_block);
-  i.setApplicationParameters("8001C1"_block); // Block of non-ApplicationParameters type
+  i.setApplicationParameters("8001C1"_block);
   BOOST_CHECK_EQUAL(i.getApplicationParameters(), "24038001C1"_block);
+
+  // raw buffer+size overload
+  i.setApplicationParameters(PARAMETERS1, sizeof(PARAMETERS1));
+  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2401C1"_block);
+  i.setApplicationParameters(nullptr, 0);
+  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2400"_block);
+  BOOST_CHECK_THROW(i.setApplicationParameters(nullptr, 42), std::invalid_argument);
+
+  // ConstBufferPtr overload
+  i.setApplicationParameters(make_shared<Buffer>(PARAMETERS2, sizeof(PARAMETERS2)));
+  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2401C2"_block);
+  i.setApplicationParameters(make_shared<Buffer>());
+  BOOST_CHECK_EQUAL(i.getApplicationParameters(), "2400"_block);
+  BOOST_CHECK_THROW(i.setApplicationParameters(nullptr), std::invalid_argument);
 }
 
 // ---- operators ----