security: return a span from Certificate::getPublicKey()

Also, tighten the FreshnessPeriod check in the constructor
and expand test coverage of various functions

Change-Id: I70837e20bbea8f1174baf2b252f39894e5346c34
diff --git a/tests/unit/security/certificate.t.cpp b/tests/unit/security/certificate.t.cpp
index a9df438..f113ca9 100644
--- a/tests/unit/security/certificate.t.cpp
+++ b/tests/unit/security/certificate.t.cpp
@@ -141,18 +141,20 @@
 {
   Block block(CERT);
   Certificate certificate(block);
+  const ValidityPeriod vp(time::fromIsoString("20150814T223739"),
+                          time::fromIsoString("20150818T223738"));
 
   BOOST_CHECK_EQUAL(certificate.getName(), "/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
   BOOST_CHECK_EQUAL(certificate.getKeyName(), "/ndn/site1/KEY/ksk-1416425377094");
   BOOST_CHECK_EQUAL(certificate.getIdentity(), "/ndn/site1");
-  BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
   BOOST_CHECK_EQUAL(certificate.getKeyId(), name::Component("ksk-1416425377094"));
+  BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
+  BOOST_TEST(certificate.getPublicKey() == PUBLIC_KEY, boost::test_tools::per_element());
   BOOST_CHECK_EQUAL(certificate.getKeyLocator().value().getName(), "/ndn/site1/KEY/ksk-2516425377094");
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate.getValidityPeriod()),
-                    "(20150814T223739, 20150818T223738)");
+  BOOST_CHECK_EQUAL(certificate.getValidityPeriod(), vp);
 
-  BOOST_CHECK_THROW(certificate.getExtension(12345), Data::Error);
-  BOOST_CHECK_NO_THROW(certificate.getPublicKey());
+  BOOST_CHECK_EQUAL(certificate.getExtension(tlv::ValidityPeriod), vp.wireEncode());
+  BOOST_CHECK_THROW(certificate.getExtension(12345), tlv::Error);
 
   Data data(block);
   Certificate certificate2(std::move(data));
@@ -167,17 +169,20 @@
   certificate.setContent(PUBLIC_KEY);
   generateFakeSignature(certificate);
 
+  const ValidityPeriod vp(time::fromIsoString("20141111T050000"),
+                          time::fromIsoString("20141111T060000"));
+
   BOOST_CHECK_EQUAL(certificate.getName(), "/ndn/site1/KEY/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
   BOOST_CHECK_EQUAL(certificate.getKeyName(), "/ndn/site1/KEY/ksk-1416425377094");
   BOOST_CHECK_EQUAL(certificate.getIdentity(), "/ndn/site1");
-  BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
   BOOST_CHECK_EQUAL(certificate.getKeyId(), name::Component("ksk-1416425377094"));
+  BOOST_CHECK_EQUAL(certificate.getIssuerId(), name::Component("0123"));
+  BOOST_TEST(certificate.getPublicKey() == PUBLIC_KEY, boost::test_tools::per_element());
   BOOST_CHECK_EQUAL(certificate.getKeyLocator().value().getName(), "/ndn/site1/KEY/ksk-2516425377094");
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(certificate.getValidityPeriod()),
-                    "(20141111T050000, 20141111T060000)");
+  BOOST_CHECK_EQUAL(certificate.getValidityPeriod(), vp);
 
-  BOOST_CHECK_THROW(certificate.getExtension(12345), Data::Error);
-  BOOST_CHECK_NO_THROW(certificate.getPublicKey());
+  BOOST_CHECK_EQUAL(certificate.getExtension(tlv::ValidityPeriod), vp.wireEncode());
+  BOOST_CHECK_THROW(certificate.getExtension(12345), tlv::Error);
 }
 
 BOOST_AUTO_TEST_CASE(ValidityPeriodChecking)
@@ -216,35 +221,30 @@
 {
   Data data(m_certBase);
   data.setName("/ndn/site1/ksk-1416425377094/0123/%FD%00%00%01I%C9%8B");
-  generateFakeSignature(data);
 
-  BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
-  BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
+  BOOST_CHECK_EXCEPTION(Certificate{std::move(data)}, Certificate::Error, [] (const auto& e) {
+    return e.what() == "Certificate name does not follow the naming conventions"s;
+  });
 }
 
-BOOST_FIXTURE_TEST_CASE(InvalidType, InvalidCertFixture)
+BOOST_FIXTURE_TEST_CASE(InvalidContentType, InvalidCertFixture)
 {
   Data data(m_certBase);
   data.setContentType(tlv::ContentType_Blob);
-  generateFakeSignature(data);
 
-  BOOST_CHECK_THROW((Certificate(data)), Certificate::Error);
-  BOOST_CHECK_THROW((Certificate(std::move(data))), Certificate::Error);
+  BOOST_CHECK_EXCEPTION(Certificate{std::move(data)}, Certificate::Error, [] (const auto& e) {
+    return e.what() == "Expecting ContentType=Key, got 0"s;
+  });
 }
 
-BOOST_FIXTURE_TEST_CASE(EmptyContent, InvalidCertFixture)
+BOOST_FIXTURE_TEST_CASE(InvalidFreshnessPeriod, InvalidCertFixture)
 {
   Data data(m_certBase);
-  data.setContent(span<uint8_t>{});
-  generateFakeSignature(data);
+  data.setFreshnessPeriod(0_ms);
 
-  BOOST_CHECK_THROW(Certificate{data}, Certificate::Error);
-  BOOST_CHECK_THROW(Certificate{std::move(data)}, Certificate::Error);
-
-  Certificate cert(m_certBase);
-  cert.setContent(span<uint8_t>{});
-  generateFakeSignature(cert);
-  BOOST_CHECK_THROW(cert.getPublicKey(), Certificate::Error);
+  BOOST_CHECK_EXCEPTION(Certificate{std::move(data)}, Certificate::Error, [] (const auto& e) {
+    return e.what() == "Certificate FreshnessPeriod cannot be zero"s;
+  });
 }
 
 BOOST_AUTO_TEST_CASE(Print)
@@ -372,6 +372,25 @@
   BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cert6), expected6);
 }
 
+BOOST_AUTO_TEST_CASE(Helpers)
+{
+  BOOST_CHECK_EQUAL(extractIdentityFromCertName("/KEY/hello/world/v=1"), "/");
+  BOOST_CHECK_EQUAL(extractIdentityFromCertName("/hello/world/KEY/!/self/v=42"), "/hello/world");
+
+  BOOST_CHECK_THROW(extractIdentityFromCertName("/hello"), std::invalid_argument);
+  BOOST_CHECK_THROW(extractIdentityFromCertName("/hello/KEY/keyid"), std::invalid_argument);
+  BOOST_CHECK_THROW(extractIdentityFromCertName("/hello/KEY/keyid/issuer"), std::invalid_argument);
+  BOOST_CHECK_THROW(extractIdentityFromCertName("/a/long/enough/but/invalid/name"), std::invalid_argument);
+
+  BOOST_CHECK_EQUAL(extractKeyNameFromCertName("/KEY/hello/world/v=1"), "/KEY/hello");
+  BOOST_CHECK_EQUAL(extractKeyNameFromCertName("/hello/world/KEY/!/self/v=42"), "/hello/world/KEY/!");
+
+  BOOST_CHECK_THROW(extractKeyNameFromCertName("/hello"), std::invalid_argument);
+  BOOST_CHECK_THROW(extractKeyNameFromCertName("/hello/KEY/keyid"), std::invalid_argument);
+  BOOST_CHECK_THROW(extractKeyNameFromCertName("/hello/KEY/keyid/issuer"), std::invalid_argument);
+  BOOST_CHECK_THROW(extractKeyNameFromCertName("/a/long/enough/but/invalid/name"), std::invalid_argument);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestCertificate
 BOOST_AUTO_TEST_SUITE_END() // Security
 
diff --git a/tests/unit/security/detail/certificate-bundle-decoder.t.cpp b/tests/unit/security/detail/certificate-bundle-decoder.t.cpp
index 1199994..a9fe998 100644
--- a/tests/unit/security/detail/certificate-bundle-decoder.t.cpp
+++ b/tests/unit/security/detail/certificate-bundle-decoder.t.cpp
@@ -156,7 +156,7 @@
   BOOST_CHECK_EQUAL(nCertsCompleted, 1);
 
   BOOST_CHECK_EXCEPTION(cbd.append(d2.getContent()), tlv::Error, [] (const auto& e) {
-    return e.what() == "Name does not follow the naming convention for certificate"s;
+    return e.what() == "Certificate name does not follow the naming conventions"s;
   });
   BOOST_CHECK_EQUAL(cbd.hasError(), true);
   BOOST_CHECK_EQUAL(nCertsCompleted, 1);
diff --git a/tests/unit/security/key-chain.t.cpp b/tests/unit/security/key-chain.t.cpp
index b3ea456..ba84081 100644
--- a/tests/unit/security/key-chain.t.cpp
+++ b/tests/unit/security/key-chain.t.cpp
@@ -611,8 +611,7 @@
     BOOST_CHECK_EQUAL(cert.getContentType(), tlv::ContentType_Key);
     BOOST_CHECK_EQUAL(cert.getFreshnessPeriod(), 1_h);
 
-    BOOST_TEST(cert.getContent().value_bytes() == requester.getPublicKey(),
-               boost::test_tools::per_element());
+    BOOST_TEST(cert.getPublicKey() == requester.getPublicKey(), boost::test_tools::per_element());
 
     checkKeyLocatorName(cert);
 
diff --git a/tests/unit/security/pib/pib-data-fixture.cpp b/tests/unit/security/pib/pib-data-fixture.cpp
index c160042..488d11e 100644
--- a/tests/unit/security/pib/pib-data-fixture.cpp
+++ b/tests/unit/security/pib/pib-data-fixture.cpp
@@ -374,10 +374,10 @@
   , id2Key1Name(id2Key1Cert1.getKeyName())
   , id2Key2Name(id2Key2Cert1.getKeyName())
 
-  , id1Key1(id1Key1Cert1.getPublicKey())
-  , id1Key2(id1Key2Cert1.getPublicKey())
-  , id2Key1(id2Key1Cert1.getPublicKey())
-  , id2Key2(id2Key2Cert1.getPublicKey())
+  , id1Key1(id1Key1Cert1.getPublicKey().begin(), id1Key1Cert1.getPublicKey().end())
+  , id1Key2(id1Key2Cert1.getPublicKey().begin(), id1Key2Cert1.getPublicKey().end())
+  , id2Key1(id2Key1Cert1.getPublicKey().begin(), id2Key1Cert1.getPublicKey().end())
+  , id2Key2(id2Key2Cert1.getPublicKey().begin(), id2Key2Cert1.getPublicKey().end())
 {
   BOOST_ASSERT(id1Key1Cert2.getIdentity() == id1);
   BOOST_ASSERT(id1Key2Cert1.getIdentity() == id1);
@@ -391,10 +391,10 @@
   BOOST_ASSERT(id2Key1Cert2.getKeyName() == id2Key1Name);
   BOOST_ASSERT(id2Key2Cert2.getKeyName() == id2Key2Name);
 
-  BOOST_ASSERT(id1Key1Cert2.getPublicKey() == id1Key1);
-  BOOST_ASSERT(id1Key2Cert2.getPublicKey() == id1Key2);
-  BOOST_ASSERT(id2Key1Cert2.getPublicKey() == id2Key1);
-  BOOST_ASSERT(id2Key2Cert2.getPublicKey() == id2Key2);
+  BOOST_ASSERT(id1Key1Cert2.getContent() == id1Key1Cert1.getContent());
+  BOOST_ASSERT(id1Key2Cert2.getContent() == id1Key2Cert1.getContent());
+  BOOST_ASSERT(id2Key1Cert2.getContent() == id2Key1Cert1.getContent());
+  BOOST_ASSERT(id2Key2Cert2.getContent() == id2Key2Cert1.getContent());
 }
 
 shared_ptr<PibImpl>