mgmt: tables.cs_unsolicited_policy config option

This commit introduces tests/check-typeid.hpp which provides
unit testing tools to validate runtime type information.

refs #2181

Change-Id: I987c9875517001ea82878cbe2646839a03ad54f3
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index ae4369e..7fad250 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -36,7 +36,7 @@
 NFD_LOG_INIT("Forwarder");
 
 Forwarder::Forwarder()
-  : m_unsolicitedDataPolicy(new fw::AdmitLocalUnsolicitedDataPolicy())
+  : m_unsolicitedDataPolicy(new fw::DefaultUnsolicitedDataPolicy())
   , m_fib(m_nameTree)
   , m_pit(m_nameTree)
   , m_measurements(m_nameTree)
diff --git a/daemon/fw/unsolicited-data-policy.cpp b/daemon/fw/unsolicited-data-policy.cpp
index 79c6d77..67d4d37 100644
--- a/daemon/fw/unsolicited-data-policy.cpp
+++ b/daemon/fw/unsolicited-data-policy.cpp
@@ -70,5 +70,24 @@
   return UnsolicitedDataDecision::CACHE;
 }
 
+unique_ptr<UnsolicitedDataPolicy>
+makeUnsolicitedDataPolicy(const std::string& key)
+{
+  /// \todo register policy with a macro
+  if (key == "drop-all") {
+    return make_unique<DropAllUnsolicitedDataPolicy>();
+  }
+  if (key == "admit-local") {
+    return make_unique<AdmitLocalUnsolicitedDataPolicy>();
+  }
+  if (key == "admit-network") {
+    return make_unique<AdmitNetworkUnsolicitedDataPolicy>();
+  }
+  if (key == "admit-all") {
+    return make_unique<AdmitAllUnsolicitedDataPolicy>();
+  }
+  return nullptr;
+}
+
 } // namespace fw
 } // namespace nfd
diff --git a/daemon/fw/unsolicited-data-policy.hpp b/daemon/fw/unsolicited-data-policy.hpp
index 2cbad2a..06354d0 100644
--- a/daemon/fw/unsolicited-data-policy.hpp
+++ b/daemon/fw/unsolicited-data-policy.hpp
@@ -92,6 +92,15 @@
   decide(const Face& inFace, const Data& data) const final;
 };
 
+/** \return an UnsolicitedDataPolicy identified by \p key, or nullptr if \p key is unknown
+ */
+unique_ptr<UnsolicitedDataPolicy>
+makeUnsolicitedDataPolicy(const std::string& key);
+
+/** \brief the default UnsolicitedDataPolicy
+ */
+typedef AdmitLocalUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy;
+
 } // namespace fw
 } // namespace nfd
 
diff --git a/daemon/mgmt/tables-config-section.cpp b/daemon/mgmt/tables-config-section.cpp
index 57230cd..2773a24 100644
--- a/daemon/mgmt/tables-config-section.cpp
+++ b/daemon/mgmt/tables-config-section.cpp
@@ -50,6 +50,7 @@
   }
 
   m_forwarder.getCs().setLimit(DEFAULT_CS_MAX_PACKETS);
+  m_forwarder.setUnsolicitedDataPolicy(make_unique<fw::DefaultUnsolicitedDataPolicy>());
 
   m_isConfigured = true;
 }
@@ -65,6 +66,20 @@
     nCsMaxPackets = ConfigFile::parseNumber<size_t>(*csMaxPacketsNode, "cs_max_packets", "tables");
   }
 
+  unique_ptr<fw::UnsolicitedDataPolicy> unsolicitedDataPolicy;
+  OptionalNode unsolicitedDataPolicyNode = section.get_child_optional("cs_unsolicited_policy");
+  if (unsolicitedDataPolicyNode) {
+    std::string policyKey = unsolicitedDataPolicyNode->get_value<std::string>();
+    unsolicitedDataPolicy = fw::makeUnsolicitedDataPolicy(policyKey);
+    if (unsolicitedDataPolicy == nullptr) {
+      BOOST_THROW_EXCEPTION(ConfigFile::Error(
+        "Unknown cs_unsolicited_policy \"" + policyKey + "\" in \"tables\" section"));
+    }
+  }
+  else {
+    unsolicitedDataPolicy = make_unique<fw::DefaultUnsolicitedDataPolicy>();
+  }
+
   OptionalNode strategyChoiceSection = section.get_child_optional("strategy_choice");
   if (strategyChoiceSection) {
     processStrategyChoiceSection(*strategyChoiceSection, isDryRun);
@@ -81,6 +96,8 @@
 
   m_forwarder.getCs().setLimit(nCsMaxPackets);
 
+  m_forwarder.setUnsolicitedDataPolicy(std::move(unsolicitedDataPolicy));
+
   m_isConfigured = true;
 }
 
diff --git a/daemon/mgmt/tables-config-section.hpp b/daemon/mgmt/tables-config-section.hpp
index 4aff010..8afa608 100644
--- a/daemon/mgmt/tables-config-section.hpp
+++ b/daemon/mgmt/tables-config-section.hpp
@@ -39,6 +39,8 @@
  *  {
  *    cs_max_packets 65536
  *
+ *    cs_unsolicited_policy drop-all
+ *
  *    strategy_choice
  *    {
  *      /               /localhost/nfd/strategy/best-route
@@ -54,6 +56,16 @@
  *    }
  *  }
  *  \endcode
+ *
+ *  During a configuration reload,
+ *  \li cs_max_packets and cs_unsolicited_policy are applied;
+ *      defaults are used if an option is omitted.
+ *  \li strategy_choice entries are inserted, but old entries are not deleted.
+ *  \li network_region is applied; it's kept unchanged if the section is omitted.
+ *
+ *  It's necessary to call \p ensureConfigured() after initial configuration and
+ *  configuration reload, so that the correct defaults are applied in case
+ *  tables section is omitted.
  */
 class TablesConfigSection : noncopyable
 {
@@ -80,7 +92,6 @@
   processNetworkRegionSection(const ConfigSection& section, bool isDryRun);
 
 private:
-private:
   static const size_t DEFAULT_CS_MAX_PACKETS;
 
   Forwarder& m_forwarder;
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index 682b8e7..ceaa246 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -49,6 +49,10 @@
   ; default is 65536, about 500MB with 8KB packet size
   cs_max_packets 65536
 
+  ; Set a policy to decide whether to cache or drop unsolicited Data.
+  ; Available policies are: drop-all, admit-local, admit-network, admit-all
+  cs_unsolicited_policy admit-local
+
   ; Set the forwarding strategy for the specified prefixes:
   ;   <prefix> <strategy>
   strategy_choice
diff --git a/tests/check-typeid.hpp b/tests/check-typeid.hpp
new file mode 100644
index 0000000..58d9fb6
--- /dev/null
+++ b/tests/check-typeid.hpp
@@ -0,0 +1,85 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ *  \brief provides unit testing tools to validate runtime type information
+ */
+
+#ifndef NFD_TESTS_CHECK_TYPEID_HPP
+#define NFD_TESTS_CHECK_TYPEID_HPP
+
+#include "boost-test.hpp"
+#include <typeinfo>
+
+/** \def NFD_TYPEID_NAME(x)
+ *  \return type name of typeid(x) as std::string
+ */
+#if BOOST_VERSION >= 105600
+#include <boost/core/demangle.hpp>
+#define NFD_TYPEID_NAME(x) (::boost::core::demangle(typeid(x).name()))
+#else
+#define NFD_TYPEID_NAME(x) (::std::string(typeid(x).name()))
+#endif
+
+/** (implementation detail)
+ */
+#define NFD_TEST_TYPEID_REL(level, a, op, b) \
+  BOOST_##level##_MESSAGE((typeid(a) op typeid(b)), \
+                          "expect typeid(" #a ") " #op " typeid(" #b ") [" << \
+                          NFD_TYPEID_NAME(a) << " " #op " " << NFD_TYPEID_NAME(b) << "]")
+
+/** (implementation detail)
+ */
+#define NFD_TEST_TYPEID_EQUAL(level, a, b) NFD_TEST_TYPEID_REL(level, a, ==, b)
+
+/** (implementation detail)
+ */
+#define NFD_TEST_TYPEID_NE(level, a, b) NFD_TEST_TYPEID_REL(level, a, !=, b)
+
+/** \brief equivalent to BOOST_REQUIRE(typeid(a) == typeid(b))
+ */
+#define NFD_REQUIRE_TYPEID_EQUAL(a, b) NFD_TEST_TYPEID_EQUAL(REQUIRE, a, b)
+
+/** \brief equivalent to BOOST_REQUIRE(typeid(a) != typeid(b))
+ */
+#define NFD_REQUIRE_TYPEID_NE(a, b) NFD_TEST_TYPEID_NE(REQUIRE, a, b)
+
+/** \brief equivalent to BOOST_CHECK(typeid(a) == typeid(b))
+ */
+#define NFD_CHECK_TYPEID_EQUAL(a, b) NFD_TEST_TYPEID_EQUAL(CHECK, a, b)
+
+/** \brief equivalent to BOOST_CHECK(typeid(a) != typeid(b))
+ */
+#define NFD_CHECK_TYPEID_NE(a, b) NFD_TEST_TYPEID_NE(CHECK, a, b)
+
+/** \brief equivalent to BOOST_WARN(typeid(a) == typeid(b))
+ */
+#define NFD_WARN_TYPEID_EQUAL(a, b) NFD_TEST_TYPEID_EQUAL(WARN, a, b)
+
+/** \brief equivalent to BOOST_WARN(typeid(a) != typeid(b))
+ */
+#define NFD_WARN_TYPEID_NE(a, b) NFD_TEST_TYPEID_NE(WARN, a, b)
+
+#endif // NFD_TESTS_CHECK_TYPEID_HPP
diff --git a/tests/daemon/mgmt/tables-config-section.t.cpp b/tests/daemon/mgmt/tables-config-section.t.cpp
index d87c6e6..139d61c 100644
--- a/tests/daemon/mgmt/tables-config-section.t.cpp
+++ b/tests/daemon/mgmt/tables-config-section.t.cpp
@@ -27,6 +27,7 @@
 #include "fw/forwarder.hpp"
 
 #include "tests/test-common.hpp"
+#include "tests/check-typeid.hpp"
 #include "../fw/dummy-strategy.hpp"
 #include "../fw/install-strategy.hpp"
 
@@ -35,205 +36,248 @@
 
 class TablesConfigSectionFixture : protected BaseFixture
 {
-public:
-
+protected:
   TablesConfigSectionFixture()
-    : m_cs(m_forwarder.getCs())
-    , m_pit(m_forwarder.getPit())
-    , m_fib(m_forwarder.getFib())
-    , m_strategyChoice(m_forwarder.getStrategyChoice())
-    , m_measurements(m_forwarder.getMeasurements())
-    , m_networkRegionTable(m_forwarder.getNetworkRegionTable())
-    , m_tablesConfig(m_forwarder)
+    : cs(forwarder.getCs())
+    , strategyChoice(forwarder.getStrategyChoice())
+    , networkRegionTable(forwarder.getNetworkRegionTable())
+    , tablesConfig(forwarder)
   {
-    m_tablesConfig.setConfigFile(m_config);
   }
 
   void
-  runConfig(const std::string& CONFIG, bool isDryRun)
+  runConfig(const std::string& config, bool isDryRun)
   {
-    m_config.parse(CONFIG, isDryRun, "dummy-config");
+    ConfigFile cf;
+    tablesConfig.setConfigFile(cf);
+    cf.parse(config, isDryRun, "dummy-config");
   }
 
 protected:
-  Forwarder m_forwarder;
+  Forwarder forwarder;
+  Cs& cs;
+  StrategyChoice& strategyChoice;
+  NetworkRegionTable& networkRegionTable;
 
-  Cs& m_cs;
-  Pit& m_pit;
-  Fib& m_fib;
-  StrategyChoice& m_strategyChoice;
-  Measurements& m_measurements;
-  NetworkRegionTable& m_networkRegionTable;
-
-  TablesConfigSection m_tablesConfig;
-  ConfigFile m_config;
+  TablesConfigSection tablesConfig;
 };
 
-BOOST_FIXTURE_TEST_SUITE(Mgmt, TablesConfigSectionFixture)
-BOOST_AUTO_TEST_SUITE(TestTablesConfigSection)
+BOOST_AUTO_TEST_SUITE(Mgmt)
+BOOST_FIXTURE_TEST_SUITE(TestTablesConfigSection, TablesConfigSectionFixture)
 
-BOOST_AUTO_TEST_CASE(ConfigureTablesWithDefaults)
+BOOST_AUTO_TEST_SUITE(CsMaxPackets)
+
+BOOST_AUTO_TEST_CASE(NoSection)
 {
-  const size_t initialLimit = m_cs.getLimit();
+  const size_t initialLimit = cs.getLimit();
 
-  m_tablesConfig.ensureConfigured();
-  BOOST_CHECK_NE(initialLimit, m_cs.getLimit());
+  tablesConfig.ensureConfigured();
+  BOOST_CHECK_NE(cs.getLimit(), initialLimit);
 }
 
-BOOST_AUTO_TEST_CASE(EmptyTablesSection)
+BOOST_AUTO_TEST_CASE(Default)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+    }
+  )CONFIG";
 
-  const size_t nCsMaxPackets = m_cs.getLimit();
+  const size_t initialLimit = cs.getLimit();
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
-  BOOST_CHECK_EQUAL(m_cs.getLimit(), nCsMaxPackets);
+  BOOST_CHECK_EQUAL(cs.getLimit(), initialLimit);
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
-  BOOST_CHECK_NE(m_cs.getLimit(), nCsMaxPackets);
-
-  const size_t defaultLimit = m_cs.getLimit();
-
-  m_tablesConfig.ensureConfigured();
-  BOOST_CHECK_EQUAL(defaultLimit, m_cs.getLimit());
+  BOOST_CHECK_NE(cs.getLimit(), initialLimit);
 }
 
-BOOST_AUTO_TEST_CASE(MissingTablesSection)
+BOOST_AUTO_TEST_CASE(Valid)
 {
-  const std::string CONFIG =
-    "not_tables\n"
-    "{\n"
-    "  some_other_field 0\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      cs_max_packets 101
+    }
+  )CONFIG";
 
-  ConfigFile passiveConfig(&ConfigFile::ignoreUnknownSection);
-
-  const size_t initialLimit = m_cs.getLimit();
-
-  passiveConfig.parse(CONFIG, true, "dummy-config");
-  BOOST_REQUIRE_EQUAL(initialLimit, m_cs.getLimit());
-
-  passiveConfig.parse(CONFIG, false, "dummy-config");
-  BOOST_REQUIRE_EQUAL(initialLimit, m_cs.getLimit());
-
-  m_tablesConfig.ensureConfigured();
-  BOOST_CHECK_NE(initialLimit, m_cs.getLimit());
-}
-
-BOOST_AUTO_TEST_SUITE(Cs)
-
-BOOST_AUTO_TEST_CASE(ValidCsMaxPackets)
-{
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  cs_max_packets 101\n"
-    "}\n";
-
-  BOOST_REQUIRE_NE(m_cs.getLimit(), 101);
+  BOOST_REQUIRE_NE(cs.getLimit(), 101);
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
-  BOOST_CHECK_NE(m_cs.getLimit(), 101);
+  BOOST_CHECK_NE(cs.getLimit(), 101);
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
-  BOOST_CHECK_EQUAL(m_cs.getLimit(), 101);
+  BOOST_CHECK_EQUAL(cs.getLimit(), 101);
 
-  m_tablesConfig.ensureConfigured();
-  BOOST_CHECK_EQUAL(m_cs.getLimit(), 101);
+  tablesConfig.ensureConfigured();
+  BOOST_CHECK_EQUAL(cs.getLimit(), 101);
 }
 
-BOOST_AUTO_TEST_CASE(MissingValueCsMaxPackets)
+BOOST_AUTO_TEST_CASE(MissingValue)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  cs_max_packets\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      cs_max_packets
+    }
+  )CONFIG";
 
   BOOST_CHECK_THROW(runConfig(CONFIG, true), ConfigFile::Error);
   BOOST_CHECK_THROW(runConfig(CONFIG, false), ConfigFile::Error);
 }
 
-BOOST_AUTO_TEST_CASE(InvalidValueCsMaxPackets)
+BOOST_AUTO_TEST_CASE(InvalidValue)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  cs_max_packets invalid\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      cs_max_packets invalid
+    }
+  )CONFIG";
 
   BOOST_CHECK_THROW(runConfig(CONFIG, true), ConfigFile::Error);
   BOOST_CHECK_THROW(runConfig(CONFIG, false), ConfigFile::Error);
 }
 
-BOOST_AUTO_TEST_SUITE_END() // Cs
+BOOST_AUTO_TEST_SUITE_END() // CsMaxPackets
 
-BOOST_AUTO_TEST_SUITE(ConfigStrategy)
+class CsUnsolicitedPolicyFixture : public TablesConfigSectionFixture
+{
+protected:
+  class DummyUnsolicitedDataPolicy : public fw::AdmitNetworkUnsolicitedDataPolicy
+  {
+  };
+
+  CsUnsolicitedPolicyFixture()
+  {
+    forwarder.setUnsolicitedDataPolicy(make_unique<DummyUnsolicitedDataPolicy>());
+  }
+};
+
+BOOST_FIXTURE_TEST_SUITE(CsUnsolicitedPolicy, CsUnsolicitedPolicyFixture)
+
+BOOST_AUTO_TEST_CASE(NoSection)
+{
+  tablesConfig.ensureConfigured();
+
+  fw::UnsolicitedDataPolicy* currentPolicy = &forwarder.getUnsolicitedDataPolicy();
+  NFD_CHECK_TYPEID_EQUAL(*currentPolicy, fw::DefaultUnsolicitedDataPolicy);
+}
+
+BOOST_AUTO_TEST_CASE(Default)
+{
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+    }
+  )CONFIG";
+
+  BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
+  fw::UnsolicitedDataPolicy* currentPolicy = &forwarder.getUnsolicitedDataPolicy();
+  NFD_CHECK_TYPEID_NE(*currentPolicy, fw::DefaultUnsolicitedDataPolicy);
+
+  BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
+  currentPolicy = &forwarder.getUnsolicitedDataPolicy();
+  NFD_CHECK_TYPEID_EQUAL(*currentPolicy, fw::DefaultUnsolicitedDataPolicy);
+}
+
+BOOST_AUTO_TEST_CASE(Known)
+{
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      cs_unsolicited_policy admit-all
+    }
+  )CONFIG";
+
+  BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
+  fw::UnsolicitedDataPolicy* currentPolicy = &forwarder.getUnsolicitedDataPolicy();
+  NFD_CHECK_TYPEID_NE(*currentPolicy, fw::AdmitAllUnsolicitedDataPolicy);
+
+  BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
+  currentPolicy = &forwarder.getUnsolicitedDataPolicy();
+  NFD_CHECK_TYPEID_EQUAL(*currentPolicy, fw::AdmitAllUnsolicitedDataPolicy);
+}
+
+BOOST_AUTO_TEST_CASE(Unknown)
+{
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      cs_unsolicited_policy unknown
+    }
+  )CONFIG";
+
+  BOOST_CHECK_THROW(runConfig(CONFIG, true), ConfigFile::Error);
+  BOOST_CHECK_THROW(runConfig(CONFIG, false), ConfigFile::Error);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // CsUnsolicitedPolicy
+
+BOOST_AUTO_TEST_SUITE(StrategyChoice)
 
 BOOST_AUTO_TEST_CASE(Unversioned)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  strategy_choice\n"
-    "  {\n"
-    "    / /localhost/nfd/strategy/test-strategy-a\n"
-    "    /a /localhost/nfd/strategy/test-strategy-b\n"
-    "  }\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      strategy_choice
+      {
+        / /localhost/nfd/strategy/test-strategy-a
+        /a /localhost/nfd/strategy/test-strategy-b
+      }
+    }
+  )CONFIG";
 
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-a");
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-b");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-a");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-b");
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
   {
-    fw::Strategy& rootStrategy = m_strategyChoice.findEffectiveStrategy("/");
+    fw::Strategy& rootStrategy = strategyChoice.findEffectiveStrategy("/");
     BOOST_REQUIRE_NE(rootStrategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
     BOOST_REQUIRE_NE(rootStrategy.getName(), "/localhost/nfd/strategy/test-strategy-b");
 
-    fw::Strategy& aStrategy = m_strategyChoice.findEffectiveStrategy("/a");
+    fw::Strategy& aStrategy = strategyChoice.findEffectiveStrategy("/a");
     BOOST_REQUIRE_NE(aStrategy.getName(), "/localhost/nfd/strategy/test-strategy-b");
     BOOST_REQUIRE_NE(aStrategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
   }
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
   {
-    fw::Strategy& rootStrategy = m_strategyChoice.findEffectiveStrategy("/");
+    fw::Strategy& rootStrategy = strategyChoice.findEffectiveStrategy("/");
     BOOST_REQUIRE_EQUAL(rootStrategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
 
-    fw::Strategy& aStrategy = m_strategyChoice.findEffectiveStrategy("/a");
+    fw::Strategy& aStrategy = strategyChoice.findEffectiveStrategy("/a");
     BOOST_REQUIRE_EQUAL(aStrategy.getName(), "/localhost/nfd/strategy/test-strategy-b");
   }
 }
 
 BOOST_AUTO_TEST_CASE(Versioned)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "strategy_choice\n"
-    "{\n"
-    "  /test/latest /localhost/nfd/strategy/test-strategy-a\n"
-    "  /test/old /localhost/nfd/strategy/test-strategy-a/%FD%01\n"
-    "}\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      strategy_choice
+      {
+        /test/latest /localhost/nfd/strategy/test-strategy-a
+        /test/old /localhost/nfd/strategy/test-strategy-a/%FD%01
+      }
+    }
+  )CONFIG";
 
-
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-a/%FD%01");
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-a/%FD%02");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-a/%FD%01");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-a/%FD%02");
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
   {
-    fw::Strategy& testLatestStrategy = m_strategyChoice.findEffectiveStrategy("/test/latest");
+    fw::Strategy& testLatestStrategy = strategyChoice.findEffectiveStrategy("/test/latest");
     BOOST_REQUIRE_NE(testLatestStrategy.getName(),
                      "/localhost/nfd/strategy/test-strategy-a/%FD%01");
     BOOST_REQUIRE_NE(testLatestStrategy.getName(),
                      "/localhost/nfd/strategy/test-strategy-a/%FD%02");
 
-    fw::Strategy& testOldStrategy = m_strategyChoice.findEffectiveStrategy("/test/old");
+    fw::Strategy& testOldStrategy = strategyChoice.findEffectiveStrategy("/test/old");
     BOOST_REQUIRE_NE(testOldStrategy.getName(),
                      "/localhost/nfd/strategy/test-strategy-a/%FD%01");
     BOOST_REQUIRE_NE(testOldStrategy.getName(),
@@ -242,11 +286,11 @@
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
   {
-    fw::Strategy& testLatestStrategy = m_strategyChoice.findEffectiveStrategy("/test/latest");
+    fw::Strategy& testLatestStrategy = strategyChoice.findEffectiveStrategy("/test/latest");
     BOOST_REQUIRE_EQUAL(testLatestStrategy.getName(),
                         "/localhost/nfd/strategy/test-strategy-a/%FD%02");
 
-    fw::Strategy& testOldStrategy = m_strategyChoice.findEffectiveStrategy("/test/old");
+    fw::Strategy& testOldStrategy = strategyChoice.findEffectiveStrategy("/test/old");
     BOOST_REQUIRE_EQUAL(testOldStrategy.getName(),
                         "/localhost/nfd/strategy/test-strategy-a/%FD%01");
   }
@@ -254,15 +298,15 @@
 
 BOOST_AUTO_TEST_CASE(NonExisting)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  strategy_choice\n"
-    "  {\n"
-    "    / /localhost/nfd/strategy/test-doesnotexist\n"
-    "  }\n"
-    "}\n";
-
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      strategy_choice
+      {
+        / /localhost/nfd/strategy/test-doesnotexist
+      }
+    }
+  )CONFIG";
 
   BOOST_CHECK_THROW(runConfig(CONFIG, true), ConfigFile::Error);
   BOOST_CHECK_THROW(runConfig(CONFIG, false), ConfigFile::Error);
@@ -270,17 +314,17 @@
 
 BOOST_AUTO_TEST_CASE(MissingPrefix)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  strategy_choice\n"
-    "  {\n"
-    "    /localhost/nfd/strategy/test-strategy-a\n"
-    "  }\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      strategy_choice
+      {
+        /localhost/nfd/strategy/test-strategy-a
+      }
+    }
+  )CONFIG";
 
-
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-a");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-a");
 
   BOOST_CHECK_THROW(runConfig(CONFIG, true), ConfigFile::Error);
   BOOST_CHECK_THROW(runConfig(CONFIG, false), ConfigFile::Error);
@@ -288,19 +332,20 @@
 
 BOOST_AUTO_TEST_CASE(Duplicate)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  strategy_choice\n"
-    "  {\n"
-    "    / /localhost/nfd/strategy/test-strategy-a\n"
-    "    /a /localhost/nfd/strategy/test-strategy-b\n"
-    "    / /localhost/nfd/strategy/test-strategy-b\n"
-    "  }\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      strategy_choice
+      {
+        / /localhost/nfd/strategy/test-strategy-a
+        /a /localhost/nfd/strategy/test-strategy-b
+        / /localhost/nfd/strategy/test-strategy-b
+      }
+    }
+  )CONFIG";
 
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-a");
-  install<DummyStrategy>(m_forwarder, "/localhost/nfd/strategy/test-strategy-b");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-a");
+  install<DummyStrategy>(forwarder, "/localhost/nfd/strategy/test-strategy-b");
 
   BOOST_CHECK_THROW(runConfig(CONFIG, true), ConfigFile::Error);
   BOOST_CHECK_THROW(runConfig(CONFIG, false), ConfigFile::Error);
@@ -312,61 +357,65 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  const std::string CONFIG =
-    "tables\n"
-    "{\n"
-    "  network_region\n"
-    "  {\n"
-    "    /test/regionA\n"
-    "    /test/regionB/component\n"
-    "  }\n"
-    "}\n";
+  const std::string CONFIG = R"CONFIG(
+    tables
+    {
+      network_region
+      {
+        /test/regionA
+        /test/regionB/component
+      }
+    }
+  )CONFIG";
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, true));
-  BOOST_CHECK_EQUAL(m_networkRegionTable.size(), 0);
+  BOOST_CHECK_EQUAL(networkRegionTable.size(), 0);
 
-  BOOST_CHECK(m_networkRegionTable.find("/test/regionA") == m_networkRegionTable.end());
-  BOOST_CHECK(m_networkRegionTable.find("/test/regionB/component") == m_networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/test/regionA") == networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/test/regionB/component") == networkRegionTable.end());
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG, false));
-  BOOST_CHECK_EQUAL(m_networkRegionTable.size(), 2);
+  BOOST_CHECK_EQUAL(networkRegionTable.size(), 2);
 
-  BOOST_CHECK(m_networkRegionTable.find("/test/regionA") != m_networkRegionTable.end());
-  BOOST_CHECK(m_networkRegionTable.find("/test/regionB/component") != m_networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/test/regionA") != networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/test/regionB/component") != networkRegionTable.end());
 }
 
 BOOST_AUTO_TEST_CASE(Reload)
 {
-  const std::string CONFIG1 =
-    "tables\n"
-    "{\n"
-    "  network_region\n"
-    "  {\n"
-    "    /some/region\n"
-    "  }\n"
-    "}\n";
+  const std::string CONFIG1 = R"CONFIG(
+    tables
+    {
+      network_region
+      {
+        /some/region
+      }
+    }
+  )CONFIG";
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG1, true));
-  BOOST_CHECK(m_networkRegionTable.find("/some/region") == m_networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/some/region") == networkRegionTable.end());
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG1, false));
-  BOOST_CHECK(m_networkRegionTable.find("/some/region") != m_networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/some/region") != networkRegionTable.end());
 
-  const std::string CONFIG2 =
-    "tables\n"
-    "{\n"
-    "  network_region\n"
-    "  {\n"
-    "    /different/region\n"
-    "  }\n"
-    "}\n";
+  const std::string CONFIG2 = R"CONFIG(
+    tables
+    {
+      network_region
+      {
+        /different/region
+      }
+    }
+  )CONFIG";
+
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG2, true));
-  BOOST_CHECK(m_networkRegionTable.find("/some/region") != m_networkRegionTable.end());
-  BOOST_CHECK(m_networkRegionTable.find("/different/region") == m_networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/some/region") != networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/different/region") == networkRegionTable.end());
 
   BOOST_REQUIRE_NO_THROW(runConfig(CONFIG2, false));
-  BOOST_CHECK(m_networkRegionTable.find("/some/region") == m_networkRegionTable.end());
-  BOOST_CHECK(m_networkRegionTable.find("/different/region") != m_networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/some/region") == networkRegionTable.end());
+  BOOST_CHECK(networkRegionTable.find("/different/region") != networkRegionTable.end());
 }
 
 BOOST_AUTO_TEST_SUITE_END() // NetworkRegion