encoding: treat TLV-TYPE zero as invalid

 * Use tlv::Invalid to indicate an invalid Block, instead of
   UINT32_MAX (which is a valid type), thus fixing bug #4726
 * Introduce Block::isValid as a replacement for Block::empty
   and soft-deprecate the latter
 * Improve test coverage of Block and tlv::readType

Refs: #4726, #4895
Change-Id: I1cd3336fcbfe83555f3111738da67041dfae64f3
diff --git a/tests/unit/encoding/tlv.t.cpp b/tests/unit/encoding/tlv.t.cpp
index 8c73267..1810f01 100644
--- a/tests/unit/encoding/tlv.t.cpp
+++ b/tests/unit/encoding/tlv.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -112,6 +112,7 @@
 }
 
 static const uint8_t BUFFER[] = {
+  0x00, // == 0
   0x01, // == 1
   0xfc, // == 252
   0xfd, 0x00, 0xfd, // == 253
@@ -121,10 +122,12 @@
 
 BOOST_AUTO_TEST_CASE(SizeOf)
 {
+  BOOST_CHECK_EQUAL(sizeOfVarNumber(0), 1);
   BOOST_CHECK_EQUAL(sizeOfVarNumber(1), 1);
   BOOST_CHECK_EQUAL(sizeOfVarNumber(252), 1);
   BOOST_CHECK_EQUAL(sizeOfVarNumber(253), 3);
   BOOST_CHECK_EQUAL(sizeOfVarNumber(65536), 5);
+  BOOST_CHECK_EQUAL(sizeOfVarNumber(4294967295), 5);
   BOOST_CHECK_EQUAL(sizeOfVarNumber(4294967296), 9);
 }
 
@@ -132,6 +135,7 @@
 {
   std::ostringstream os;
 
+  writeVarNumber(os, 0);
   writeVarNumber(os, 1);
   writeVarNumber(os, 252);
   writeVarNumber(os, 253);
@@ -139,7 +143,7 @@
   writeVarNumber(os, 4294967296);
 
   std::string buffer = os.str();
-  const uint8_t* actual = reinterpret_cast<const uint8_t*>(buffer.c_str());
+  const uint8_t* actual = reinterpret_cast<const uint8_t*>(buffer.data());
 
   BOOST_CHECK_EQUAL(buffer.size(), sizeof(BUFFER));
   BOOST_CHECK_EQUAL_COLLECTIONS(BUFFER, BUFFER + sizeof(BUFFER),
@@ -155,60 +159,65 @@
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 1, value), true);
   begin = BUFFER;
   BOOST_CHECK_NO_THROW(readVarNumber(begin, begin + 1));
-  BOOST_CHECK_EQUAL(value, 1);
+  BOOST_CHECK_EQUAL(value, 0);
 
   begin = BUFFER + 1;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 1, value), true);
   begin = BUFFER + 1;
   BOOST_CHECK_NO_THROW(readVarNumber(begin, begin + 1));
+  BOOST_CHECK_EQUAL(value, 1);
+
+  begin = BUFFER + 2;
+  BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 1, value), true);
+  begin = BUFFER + 2;
+  BOOST_CHECK_NO_THROW(readVarNumber(begin, begin + 1));
   BOOST_CHECK_EQUAL(value, 252);
 
-  begin = BUFFER + 2;
+  begin = BUFFER + 3;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 1, value), false);
-  begin = BUFFER + 2;
+  begin = BUFFER + 3;
   BOOST_CHECK_THROW(readVarNumber(begin, begin + 1), Error);
 
-  begin = BUFFER + 2;
+  begin = BUFFER + 3;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 2, value), false);
-  begin = BUFFER + 2;
+  begin = BUFFER + 3;
   BOOST_CHECK_THROW(readVarNumber(begin, begin + 2), Error);
 
-  begin = BUFFER + 2;
+  begin = BUFFER + 3;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 3, value), true);
-  begin = BUFFER + 2;
+  begin = BUFFER + 3;
   BOOST_CHECK_NO_THROW(readVarNumber(begin, begin + 3));
   BOOST_CHECK_EQUAL(value, 253);
 
-
-  begin = BUFFER + 5;
+  begin = BUFFER + 6;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 1, value), false);
-  begin = BUFFER + 5;
+  begin = BUFFER + 6;
   BOOST_CHECK_THROW(readVarNumber(begin, begin + 1), Error);
 
-  begin = BUFFER + 5;
+  begin = BUFFER + 6;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 4, value), false);
-  begin = BUFFER + 5;
+  begin = BUFFER + 6;
   BOOST_CHECK_THROW(readVarNumber(begin, begin + 4), Error);
 
-  begin = BUFFER + 5;
+  begin = BUFFER + 6;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 5, value), true);
-  begin = BUFFER + 5;
+  begin = BUFFER + 6;
   BOOST_CHECK_NO_THROW(readVarNumber(begin, begin + 5));
   BOOST_CHECK_EQUAL(value, 65536);
 
-  begin = BUFFER + 10;
+  begin = BUFFER + 11;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 1, value), false);
-  begin = BUFFER + 10;
+  begin = BUFFER + 11;
   BOOST_CHECK_THROW(readVarNumber(begin, begin + 1), Error);
 
-  begin = BUFFER + 10;
+  begin = BUFFER + 11;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 8, value), false);
-  begin = BUFFER + 10;
+  begin = BUFFER + 11;
   BOOST_CHECK_THROW(readVarNumber(begin, begin + 8), Error);
 
-  begin = BUFFER + 10;
+  begin = BUFFER + 11;
   BOOST_CHECK_EQUAL(readVarNumber(begin, begin + 9, value), true);
-  begin = BUFFER + 10;
+  begin = BUFFER + 11;
   BOOST_CHECK_NO_THROW(readVarNumber(begin, begin + 9));
   BOOST_CHECK_EQUAL(value, 4294967296);
 }
@@ -217,6 +226,7 @@
 {
   StreamIterator end; // end of stream
   uint64_t value;
+
   {
     ArrayStream stream(reinterpret_cast<const char*>(BUFFER), 1);
     StreamIterator begin(stream);
@@ -226,118 +236,130 @@
     ArrayStream stream(reinterpret_cast<const char*>(BUFFER), 1);
     StreamIterator begin(stream);
     BOOST_CHECK_NO_THROW(readVarNumber(begin, end));
+    BOOST_CHECK_EQUAL(value, 0);
+  }
+
+  {
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 1, 1);
+    StreamIterator begin(stream);
+    BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), true);
+  }
+  {
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 1, 1);
+    StreamIterator begin(stream);
+    BOOST_CHECK_NO_THROW(readVarNumber(begin, end));
     BOOST_CHECK_EQUAL(value, 1);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 1, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), true);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 1, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_NO_THROW(readVarNumber(begin, end));
     BOOST_CHECK_EQUAL(value, 252);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 3, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), false);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 3, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_THROW(readVarNumber(begin, end), Error);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 2);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 3, 2);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), false);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 2);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 3, 2);
     StreamIterator begin(stream);
     BOOST_CHECK_THROW(readVarNumber(begin, end), Error);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 3);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 3, 3);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), true);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 2, 3);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 3, 3);
     StreamIterator begin(stream);
     BOOST_CHECK_NO_THROW(readVarNumber(begin, end));
     BOOST_CHECK_EQUAL(value, 253);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 5, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 6, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), false);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 5, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 6, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_THROW(readVarNumber(begin, end), Error);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 5, 4);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 6, 4);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), false);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 5, 4);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 6, 4);
     StreamIterator begin(stream);
     BOOST_CHECK_THROW(readVarNumber(begin, end), Error);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 5, 5);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 6, 5);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), true);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 5, 5);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 6, 5);
     StreamIterator begin(stream);
     BOOST_CHECK_NO_THROW(readVarNumber(begin, end));
     BOOST_CHECK_EQUAL(value, 65536);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 10, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 11, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), false);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 10, 1);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 11, 1);
     StreamIterator begin(stream);
     BOOST_CHECK_THROW(readVarNumber(begin, end), Error);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 10, 8);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 11, 8);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), false);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 10, 8);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 11, 8);
     StreamIterator begin(stream);
     BOOST_CHECK_THROW(readVarNumber(begin, end), Error);
   }
 
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 10, 9);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 11, 9);
     StreamIterator begin(stream);
     BOOST_CHECK_EQUAL(readVarNumber(begin, end, value), true);
   }
   {
-    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 10, 9);
+    ArrayStream stream(reinterpret_cast<const char*>(BUFFER) + 11, 9);
     StreamIterator begin(stream);
     BOOST_CHECK_NO_THROW(readVarNumber(begin, end));
     BOOST_CHECK_EQUAL(value, 4294967296);
@@ -346,6 +368,72 @@
 
 BOOST_AUTO_TEST_SUITE_END() // VarNumber
 
+BOOST_AUTO_TEST_SUITE(Type)
+
+static const uint8_t BUFFER[] = {
+  0x00, // == 0 (illegal)
+  0x01, // == 1
+  0xfd, 0x00, 0xfd, // == 253
+  0xfe, 0xff, 0xff, 0xff, 0xff, // == 4294967295
+  0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 // == 4294967296 (illegal)
+};
+
+BOOST_AUTO_TEST_CASE(Read)
+{
+  const uint8_t* begin;
+  uint32_t type;
+
+  begin = BUFFER;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 1, type), false);
+  begin = BUFFER;
+  BOOST_CHECK_THROW(readType(begin, begin + 1), Error);
+
+  begin = BUFFER + 1;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 1, type), true);
+  begin = BUFFER + 1;
+  BOOST_CHECK_NO_THROW(readType(begin, begin + 1));
+  BOOST_CHECK_EQUAL(type, 1);
+
+  begin = BUFFER + 2;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 1, type), false);
+  begin = BUFFER + 2;
+  BOOST_CHECK_THROW(readType(begin, begin + 1), Error);
+
+  begin = BUFFER + 2;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 2, type), false);
+  begin = BUFFER + 2;
+  BOOST_CHECK_THROW(readType(begin, begin + 2), Error);
+
+  begin = BUFFER + 2;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 3, type), true);
+  begin = BUFFER + 2;
+  BOOST_CHECK_NO_THROW(readType(begin, begin + 3));
+  BOOST_CHECK_EQUAL(type, 253);
+
+  begin = BUFFER + 5;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 1, type), false);
+  begin = BUFFER + 5;
+  BOOST_CHECK_THROW(readType(begin, begin + 1), Error);
+
+  begin = BUFFER + 5;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 5, type), true);
+  begin = BUFFER + 5;
+  BOOST_CHECK_NO_THROW(readType(begin, begin + 5));
+  BOOST_CHECK_EQUAL(type, 4294967295);
+
+  begin = BUFFER + 10;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 1, type), false);
+  begin = BUFFER + 10;
+  BOOST_CHECK_THROW(readType(begin, begin + 1), Error);
+
+  begin = BUFFER + 10;
+  BOOST_CHECK_EQUAL(readType(begin, begin + 9, type), false);
+  begin = BUFFER + 10;
+  BOOST_CHECK_THROW(readType(begin, begin + 9), Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // Type
+
 BOOST_AUTO_TEST_SUITE(NonNegativeInteger)
 
 // This check ensures readNonNegativeInteger only requires InputIterator concept and nothing more.
@@ -388,7 +476,7 @@
   writeNonNegativeInteger(os, 72340172838076674);
 
   std::string buffer = os.str();
-  const uint8_t* actual = reinterpret_cast<const uint8_t*>(buffer.c_str());
+  const uint8_t* actual = reinterpret_cast<const uint8_t*>(buffer.data());
 
   BOOST_CHECK_EQUAL_COLLECTIONS(BUFFER, BUFFER + sizeof(BUFFER),
                                 actual, actual + sizeof(BUFFER));