security: ValidatorConfig rule should pass with at least one checker

refs #5145

Change-Id: Id4c70806f2da24453bb7ec50e88475bd742541d6
diff --git a/tests/unit/security/validator-config/checker.t.cpp b/tests/unit/security/validator-config/checker.t.cpp
index 2485a82..84901ec 100644
--- a/tests/unit/security/validator-config/checker.t.cpp
+++ b/tests/unit/security/validator-config/checker.t.cpp
@@ -66,6 +66,21 @@
     return Name(name).append(suffix);
   }
 
+  template<typename PktType, typename C>
+  static void
+  testChecker(C& checker, const Name& pktName, const Name& klName, bool expectedOutcome)
+  {
+    BOOST_TEST_CONTEXT("pkt=" << pktName << " kl=" << klName) {
+      auto state = PktType::makeState();
+      auto result = checker.check(PktType::getType(), pktName, klName, *state);
+      BOOST_CHECK_EQUAL(bool(result), expectedOutcome);
+      BOOST_CHECK(boost::logic::indeterminate(state->getOutcome()));
+      if (!result) {
+        BOOST_CHECK_NE(result.getErrorMessage(), "");
+      }
+    }
+  }
+
 public:
   std::vector<Name> names;
 };
@@ -305,27 +320,16 @@
   BOOST_REQUIRE_EQUAL(this->outcomes.size(), this->names.size());
   for (size_t i = 0; i < this->names.size(); ++i) {
     BOOST_REQUIRE_EQUAL(this->outcomes[i].size(), this->names.size());
+
+    auto pktName = PktType::makeName(this->names[i], this->m_keyChain);
     for (size_t j = 0; j < this->names.size(); ++j) {
-      auto pktName = PktType::makeName(this->names[i], this->m_keyChain);
       bool expectedOutcome = this->outcomes[i][j];
 
-      {
-        auto klName = this->makeKeyLocatorKeyName(this->names[j]);
+      auto klName = this->makeKeyLocatorKeyName(this->names[j]);
+      this->template testChecker<PktType>(this->checker, pktName, klName, expectedOutcome);
 
-        auto state = PktType::makeState();
-        BOOST_CHECK_EQUAL(this->checker.check(PktType::getType(), pktName, klName, state), expectedOutcome);
-        BOOST_CHECK_EQUAL(boost::logic::indeterminate(state->getOutcome()), expectedOutcome);
-        BOOST_CHECK_EQUAL(bool(state->getOutcome()), false);
-      }
-
-      {
-        auto klName = this->makeKeyLocatorCertName(this->names[j]);
-
-        auto state = PktType::makeState();
-        BOOST_CHECK_EQUAL(this->checker.check(PktType::getType(), pktName, klName, state), expectedOutcome);
-        BOOST_CHECK_EQUAL(boost::logic::indeterminate(state->getOutcome()), expectedOutcome);
-        BOOST_CHECK_EQUAL(bool(state->getOutcome()), false);
-      }
+      klName = this->makeKeyLocatorCertName(this->names[j]);
+      this->template testChecker<PktType>(this->checker, pktName, klName, expectedOutcome);
     }
   }
 }
diff --git a/tests/unit/security/validator-config/rule.t.cpp b/tests/unit/security/validator-config/rule.t.cpp
index 04c6e8d..0410d9f 100644
--- a/tests/unit/security/validator-config/rule.t.cpp
+++ b/tests/unit/security/validator-config/rule.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2021 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -96,23 +96,36 @@
 
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(Checkers, PktType, PktTypes, RuleFixture<PktType>)
 {
-  this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
-                                                        "^<not>?(<>+)$", "\\1",
-                                                        NameRelation::EQUAL));
+  auto testChecker = [this] (const Name& klName, bool expectedOutcome) {
+    BOOST_TEST_CONTEXT(klName << " expected=" << expectedOutcome) {
+      this->state = PktType::makeState(); // reset state
+      BOOST_CHECK_EQUAL(this->rule.check(PktType::getType(), this->pktName, klName, this->state),
+                        expectedOutcome);
 
-  BOOST_CHECK_EQUAL(this->rule.check(PktType::getType(), this->pktName, "/foo/bar", this->state), true);
-
-  this->state = PktType::makeState(); // reset state
-  BOOST_CHECK_EQUAL(this->rule.check(PktType::getType(), this->pktName, "/not/foo/bar", this->state), true);
+      auto outcome = this->state->getOutcome();
+      if (expectedOutcome) {
+        BOOST_CHECK(boost::logic::indeterminate(outcome));
+      }
+      else {
+        BOOST_CHECK(!boost::logic::indeterminate(outcome));
+        BOOST_CHECK(!bool(outcome));
+      }
+    }
+  };
 
   this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
-                                                        "^(<>+)$", "\\1",
-                                                        NameRelation::EQUAL));
-  this->state = PktType::makeState(); // reset state
-  BOOST_CHECK_EQUAL(this->rule.check(PktType::getType(), this->pktName, "/foo/bar", this->state), true);
+                                                          "^<always>(<>+)$", "\\1",
+                                                          NameRelation::EQUAL));
+  testChecker("/always/foo/bar", true);
+  testChecker("/seldomly/foo/bar", false);
+  testChecker("/never/foo/bar", false);
 
-  this->state = PktType::makeState(); // reset state
-  BOOST_CHECK_EQUAL(this->rule.check(PktType::getType(), this->pktName, "/not/foo/bar", this->state), false);
+  this->rule.addChecker(make_unique<HyperRelationChecker>("^(<>+)$", "\\1",
+                                                          "^<seldomly>(<>+)$", "\\1",
+                                                          NameRelation::EQUAL));
+  testChecker("/always/foo/bar", true);
+  testChecker("/seldomly/foo/bar", true);
+  testChecker("/never/foo/bar", false);
 }
 
 BOOST_AUTO_TEST_SUITE(Create)