name: check TLV type when constructing Name from Block

Change-Id: I5006d188c738597e684638fad89865c6776e2c94
diff --git a/.jenkins.d/20-tests.sh b/.jenkins.d/20-tests.sh
index ab14284..ea5f998 100755
--- a/.jenkins.d/20-tests.sh
+++ b/.jenkins.d/20-tests.sh
@@ -1,14 +1,15 @@
 #!/usr/bin/env bash
 set -eo pipefail
 
+# https://github.com/google/sanitizers/wiki/SanitizerCommonFlags
 # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
 ASAN_OPTIONS="color=always"
+ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
 ASAN_OPTIONS+=":check_initialization_order=1"
 ASAN_OPTIONS+=":detect_stack_use_after_return=1"
 ASAN_OPTIONS+=":strict_init_order=1"
 ASAN_OPTIONS+=":strict_string_checks=1"
 ASAN_OPTIONS+=":detect_invalid_pointer_pairs=2"
-ASAN_OPTIONS+=":strip_path_prefix=${PWD}/"
 export ASAN_OPTIONS
 
 # https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/runtime_config/summary.html
diff --git a/ndn-cxx/data.hpp b/ndn-cxx/data.hpp
index ac8ef0a..b4f8179 100644
--- a/ndn-cxx/data.hpp
+++ b/ndn-cxx/data.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2023 Regents of the University of California.
+ * Copyright (c) 2013-2024 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -53,7 +53,7 @@
   Data(const Name& name = Name());
 
   /** @brief Construct a Data packet by decoding from @p wire.
-   *  @param wire TLV block of type tlv::Data; may be signed or unsigned.
+   *  @param wire TLV element of type tlv::Data; may be signed or unsigned.
    *  @warning In certain contexts that use `Data::shared_from_this()`, Data must be created using
    *           `std::make_shared`. Otherwise, `shared_from_this()` may trigger undefined behavior.
    *           One example where this is necessary is storing Data into a subclass of InMemoryStorage.
@@ -188,7 +188,7 @@
 
   /**
    * @brief Set `Content` from a Block.
-   * @param block TLV block to be used as Content; must be valid
+   * @param block TLV element to be used as Content; must be valid
    * @return A reference to this Data, to allow chaining.
    *
    * If the block's TLV-TYPE is tlv::Content, it will be used directly as this Data's
diff --git a/ndn-cxx/interest.hpp b/ndn-cxx/interest.hpp
index 7b817ab..965da32 100644
--- a/ndn-cxx/interest.hpp
+++ b/ndn-cxx/interest.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2023 Regents of the University of California.
+ * Copyright (c) 2013-2024 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -323,7 +323,7 @@
 
   /**
    * @brief Set `ApplicationParameters` from a Block.
-   * @param block TLV block to be used as ApplicationParameters; must be valid
+   * @param block TLV element to be used as ApplicationParameters; must be valid
    * @return A reference to this Interest.
    *
    * If the block's TLV-TYPE is tlv::ApplicationParameters, it will be used directly as
diff --git a/ndn-cxx/name.cpp b/ndn-cxx/name.cpp
index 9f38e4a..240edc5 100644
--- a/ndn-cxx/name.cpp
+++ b/ndn-cxx/name.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2023 Regents of the University of California.
+ * Copyright (c) 2013-2024 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -39,9 +39,8 @@
 Name::Name() = default;
 
 Name::Name(const Block& wire)
-  : m_wire(wire)
 {
-  m_wire.parse();
+  wireDecode(wire);
 }
 
 Name::Name(std::string_view uri)
diff --git a/ndn-cxx/name.hpp b/ndn-cxx/name.hpp
index ad68c33..5f72ef8 100644
--- a/ndn-cxx/name.hpp
+++ b/ndn-cxx/name.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2023 Regents of the University of California.
+ * Copyright (c) 2013-2024 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -71,14 +71,16 @@
   Name();
 
   /**
-   * @brief Decode Name from wire encoding.
-   * @throw tlv::Error wire encoding is invalid
+   * @brief Create Name from wire encoding.
+   * @param wire TLV element of type tlv::Name
    *
-   * This is a more efficient equivalent for:
+   * This is equivalent to:
    * @code
    * Name name;
    * name.wireDecode(wire);
    * @endcode
+   *
+   * @throw tlv::Error The wire encoding is invalid.
    */
   explicit
   Name(const Block& wire);
@@ -93,7 +95,7 @@
   /**
    * @brief Create name from NDN URI.
    * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
-   * @note This constructor enables implicit conversion from a string literal
+   * @note This constructor enables implicit conversion from a string literal.
    */
   Name(const char* uri)
     : Name(std::string_view(uri))
@@ -103,28 +105,31 @@
   /**
    * @brief Create name from NDN URI.
    * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
-   * @note This constructor enables implicit conversion from `std::string`
+   * @note This constructor enables implicit conversion from `std::string`.
    */
   Name(const std::string& uri)
     : Name(std::string_view(uri))
   {
   }
 
-  /** @brief Write URI representation of the name to the output stream.
-   *  @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
+  /**
+   * @brief Write URI representation of the name to the output stream.
+   * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
    */
   void
   toUri(std::ostream& os, name::UriFormat format = name::UriFormat::DEFAULT) const;
 
-  /** @brief Get URI representation of the name.
-   *  @return URI representation; the "ndn:" scheme identifier is not included
-   *  @note To print URI representation into a stream, it is more efficient to use `os << name`.
-   *  @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
+  /**
+   * @brief Get URI representation of the name.
+   * @return URI representation; the "ndn:" scheme identifier is not included.
+   * @note To print the URI representation to a stream, it is more efficient to use `os << name`.
+   * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
    */
   std::string
   toUri(name::UriFormat format = name::UriFormat::DEFAULT) const;
 
-  /** @brief Check if this instance already has wire encoding.
+  /**
+   * @brief Check if this instance already has wire encoding.
    */
   bool
   hasWire() const noexcept
@@ -132,26 +137,30 @@
     return m_wire.hasWire();
   }
 
-  /** @brief Fast encoding or block size estimation.
+  /**
+   * @brief Prepend wire encoding to @p encoder.
    */
   template<encoding::Tag TAG>
   size_t
   wireEncode(EncodingImpl<TAG>& encoder) const;
 
-  /** @brief Perform wire encoding, or return existing wire encoding.
-   *  @post hasWire() == true
+  /**
+   * @brief Perform wire encoding, or return existing (cached) wire encoding.
+   * @post hasWire() == true
    */
   const Block&
   wireEncode() const;
 
-  /** @brief Decode name from wire encoding.
-   *  @throw tlv::Error wire encoding is invalid
-   *  @post hasWire() == true
+  /**
+   * @brief Decode name from wire encoding.
+   * @throw tlv::Error The wire encoding is invalid.
+   * @post hasWire() == true
    */
   void
   wireDecode(const Block& wire);
 
-  /** @brief Make a deep copy of the name, reallocating the underlying memory buffer.
+  /**
+   * @brief Make a deep copy of the name, reallocating the underlying memory buffer.
    */
   Name
   deepCopy() const;
@@ -335,7 +344,7 @@
     return append(Component(tlv::GenericNameComponent, value));
   }
 
-  /** @brief Append a `NameComponent` of TLV-TYPE @p type, copying TLV-VALUE from a range.
+  /** @brief Append a `NameComponent` of TLV-TYPE @p type, copying the TLV-VALUE from a range.
    *  @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
    *                   implementation is available when it is a @c RandomAccessIterator.
    *  @param type      the TLV-TYPE.
@@ -350,7 +359,7 @@
     return append(Component(type, first, last));
   }
 
-  /** @brief Append a `GenericNameComponent`, copying TLV-VALUE from a range.
+  /** @brief Append a `GenericNameComponent`, copying the TLV-VALUE from a range.
    *  @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
    *                   implementation is available when it is a @c RandomAccessIterator.
    *  @param first     beginning of the range.
@@ -382,9 +391,10 @@
   Name&
   append(const PartialName& name);
 
-  /** @brief Append a component with a NonNegativeInteger.
-   *  @return A reference to this Name, to allow chaining.
-   *  @sa https://docs.named-data.net/NDN-packet-spec/0.3/tlv.html#non-negative-integer-encoding
+  /**
+   * @brief Append a component with a NonNegativeInteger.
+   * @return A reference to this Name, to allow chaining.
+   * @sa https://docs.named-data.net/NDN-packet-spec/0.3/tlv.html#non-negative-integer-encoding
    */
   Name&
   appendNumber(uint64_t number)
diff --git a/tests/unit/name.t.cpp b/tests/unit/name.t.cpp
index 734edb7..b105818 100644
--- a/tests/unit/name.t.cpp
+++ b/tests/unit/name.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2023 Regents of the University of California.
+ * Copyright (c) 2013-2024 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -49,8 +49,10 @@
 
 BOOST_AUTO_TEST_CASE(EncodeDecode)
 {
-  std::string uri = "/Emid/25042=P3/.../..../%1C%9F/"
-                    "sha256digest=0415e3624a151850ac686c84f155f29808c0dd73819aa4a4c20be73a4d8a874c";
+  constexpr auto uri = "/Emid/25042=P3/.../..../%1C%9F/"
+                       "sha256digest=0415e3624a151850ac686c84f155f29808c0dd73819aa4a4c20be73a4d8a874c"sv;
+
+  // construct from std::string_view
   Name name(uri);
   BOOST_CHECK_EQUAL(name.size(), 6);
   BOOST_CHECK_EQUAL(name[0], Component("Emid"));
@@ -66,11 +68,22 @@
 
   Block wire = name.wireEncode();
   BOOST_CHECK_EQUAL(wire,
-    "0737 0804456D6964 FD61D2025033 0800 08012E 08021C9F "
-    "01200415E3624A151850AC686C84F155F29808C0DD73819AA4A4C20BE73A4D8A874C"_block);
+                    "0737 0804456D6964 FD61D2025033 0800 08012E 08021C9F "
+                    "01200415E3624A151850AC686C84F155F29808C0DD73819AA4A4C20BE73A4D8A874C"_block);
 
+  // construct from Block
   Name decoded(wire);
-  BOOST_CHECK_EQUAL(decoded, name);
+  BOOST_TEST(decoded == name);
+  BOOST_CHECK_EXCEPTION(Name("0802CAFE"_block), tlv::Error,
+                        [] (const auto& e) { return e.what() == "Expecting Name element, but TLV has type 8"sv; });
+
+  // implicit conversion from char*
+  name = "/hello";
+  BOOST_TEST(name.toUri(name::UriFormat::CANONICAL) == "/8=hello");
+
+  // implicit conversion from std::string
+  name = "/world"s;
+  BOOST_TEST(name.toUri(name::UriFormat::CANONICAL) == "/8=world");
 }
 
 BOOST_AUTO_TEST_CASE(ParseUri)
@@ -332,34 +345,34 @@
   Name name;
   uint64_t number;
 
-  BOOST_CHECK_NO_THROW(number = name.appendSegment(30923).at(-1).toSegment());
+  number = name.appendSegment(30923).at(-1).toSegment();
   BOOST_TEST(number == 30923);
 
-  BOOST_CHECK_NO_THROW(number = name.appendByteOffset(41880).at(-1).toByteOffset());
+  number = name.appendByteOffset(41880).at(-1).toByteOffset();
   BOOST_TEST(number == 41880);
 
   auto before = time::toUnixTimestamp(time::system_clock::now());
-  BOOST_CHECK_NO_THROW(number = name.appendVersion().at(-1).toVersion());
+  number = name.appendVersion().at(-1).toVersion();
   auto after = time::toUnixTimestamp(time::system_clock::now());
   BOOST_TEST(number >= before.count());
   BOOST_TEST(number <= after.count());
 
-  BOOST_CHECK_NO_THROW(number = name.appendVersion(25912).at(-1).toVersion());
+  number = name.appendVersion(25912).at(-1).toVersion();
   BOOST_TEST(number == 25912);
 
   const auto tp = time::system_clock::now();
   time::system_clock::time_point tp2;
-  BOOST_CHECK_NO_THROW(tp2 = name.appendTimestamp(tp).at(-1).toTimestamp());
+  tp2 = name.appendTimestamp(tp).at(-1).toTimestamp();
   BOOST_TEST(time::abs(tp2 - tp) <= 1_us);
 
-  BOOST_CHECK_NO_THROW(number = name.appendSequenceNumber(11676).at(-1).toSequenceNumber());
+  number = name.appendSequenceNumber(11676).at(-1).toSequenceNumber();
   BOOST_TEST(number == 11676);
 
   name.appendKeyword({0xab, 0xcd, 0xef});
-  BOOST_TEST(name.at(-1) == Component::fromEscapedString("32=%AB%CD%EF"));
+  BOOST_TEST(name.at(-1) == Component::fromEscapedString("32=%AB%CD%EF"sv));
 
   name.appendKeyword("test-keyword");
-  BOOST_TEST(name.at(-1) == Component::fromEscapedString("32=test-keyword"));
+  BOOST_TEST(name.at(-1) == Component::fromEscapedString("32=test-keyword"sv));
 }
 
 BOOST_AUTO_TEST_CASE(EraseComponent)
@@ -543,7 +556,7 @@
   BOOST_CHECK_GT   (Name("/Z/A/C/Y").compare(1, 2, Name("/X/A"),   1), 0);
 }
 
-BOOST_AUTO_TEST_CASE(UnorderedMap)
+BOOST_AUTO_TEST_CASE(UnorderedMapKey)
 {
   std::unordered_map<Name, int> map;
   Name name1("/1");