table: clear StrategyInfo only if Strategy type differs

refs #3868

Change-Id: I164ccba3bd6c69cef9d2ebba303f8d8d941aac99
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index 9f2dd19..4aeb015 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -102,6 +102,12 @@
   return instance;
 }
 
+bool
+Strategy::areSameType(const Name& instanceNameA, const Name& instanceNameB)
+{
+  return Strategy::find(instanceNameA) == Strategy::find(instanceNameB);
+}
+
 std::set<Name>
 Strategy::listRegistered()
 {
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index b7b7adb..99ed1dc 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -70,6 +70,11 @@
   static unique_ptr<Strategy>
   create(const Name& instanceName, Forwarder& forwarder);
 
+  /** \return whether \p instanceNameA and \p instanceNameA will initiate same strategy type
+   */
+  static bool
+  areSameType(const Name& instanceNameA, const Name& instanceNameB);
+
   /** \return registered versioned strategy names
    */
   static std::set<Name>
diff --git a/daemon/table/strategy-choice.cpp b/daemon/table/strategy-choice.cpp
index 77f0bf5..01756f5 100644
--- a/daemon/table/strategy-choice.cpp
+++ b/daemon/table/strategy-choice.cpp
@@ -219,14 +219,18 @@
 void
 StrategyChoice::changeStrategy(Entry& entry, Strategy& oldStrategy, Strategy& newStrategy)
 {
-  ///\todo #3868 don't clear StrategyInfo if only parameter differs
-  if (&oldStrategy == &newStrategy) {
+  const Name& oldInstanceName = oldStrategy.getInstanceName();
+  const Name& newInstanceName = newStrategy.getInstanceName();
+  if (Strategy::areSameType(oldInstanceName, newInstanceName)) {
+    // same Strategy subclass type: no need to clear StrategyInfo
+    NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ") "
+                 << oldInstanceName << " -> " << newInstanceName
+                 << " same-type");
     return;
   }
 
-  NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ")"
-               << " from " << oldStrategy.getInstanceName()
-               << " to " << newStrategy.getInstanceName());
+  NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ") "
+               << oldInstanceName << " -> " << newInstanceName);
 
   // reset StrategyInfo on a portion of NameTree,
   // where entry's effective strategy is covered by the changing StrategyChoice entry
diff --git a/tests/daemon/table/strategy-choice.t.cpp b/tests/daemon/table/strategy-choice.t.cpp
index 7dd0e1a..eeba048 100644
--- a/tests/daemon/table/strategy-choice.t.cpp
+++ b/tests/daemon/table/strategy-choice.t.cpp
@@ -289,7 +289,6 @@
   }
 };
 
-BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(ClearStrategyInfo, 2)
 BOOST_AUTO_TEST_CASE(ClearStrategyInfo)
 {
   Measurements& measurements = forwarder.getMeasurements();
@@ -305,14 +304,14 @@
   // { '/'=>P, '/A/B'=>P }
   BOOST_CHECK(measurements.get("/").getStrategyInfo<PStrategyInfo>() != nullptr);
   BOOST_CHECK(measurements.get("/A").getStrategyInfo<PStrategyInfo>() != nullptr);
-  BOOST_CHECK(measurements.get("/A/B").getStrategyInfo<PStrategyInfo>() != nullptr); // expected failure
+  BOOST_CHECK(measurements.get("/A/B").getStrategyInfo<PStrategyInfo>() != nullptr);
   BOOST_CHECK(measurements.get("/A/C").getStrategyInfo<PStrategyInfo>() != nullptr);
 
   BOOST_CHECK(sc.insert("/A", strategyNameQ));
   // { '/'=>P, '/A/B'=>P, '/A'=>Q }
   BOOST_CHECK(measurements.get("/").getStrategyInfo<PStrategyInfo>() != nullptr);
   BOOST_CHECK(measurements.get("/A").getStrategyInfo<PStrategyInfo>() == nullptr);
-  BOOST_CHECK(measurements.get("/A/B").getStrategyInfo<PStrategyInfo>() != nullptr); // expected failure
+  BOOST_CHECK(measurements.get("/A/B").getStrategyInfo<PStrategyInfo>() != nullptr);
   BOOST_CHECK(measurements.get("/A/C").getStrategyInfo<PStrategyInfo>() == nullptr);
 
   sc.erase("/A/B");