management: Implementing ChannelStatus and StrategyChoice dataset abstractions

Change-Id: I5122239dbc8b9316d6753ab22f0a303f54005476
Refs: #1625
diff --git a/src/encoding/tlv-nfd.hpp b/src/encoding/tlv-nfd.hpp
index ad86636..ec315d6 100644
--- a/src/encoding/tlv-nfd.hpp
+++ b/src/encoding/tlv-nfd.hpp
@@ -54,13 +54,18 @@
   // Face Management
   FaceStatus            = 128,
   LocalUri              = 129,
+  ChannelStatus         = 130,
   FaceFlags             = 194,
   FaceEventNotification = 192,
   FaceEventKind         = 193,
 
   // FIB Management
   FibEntry      = 128,
-  NextHopRecord = 129
+  NextHopRecord = 129,
+
+  // Strategy Choice Management
+  StrategyChoice = 128
+
 };
 
 enum {
diff --git a/src/management/nfd-channel-status.hpp b/src/management/nfd-channel-status.hpp
new file mode 100644
index 0000000..6ac5aae
--- /dev/null
+++ b/src/management/nfd-channel-status.hpp
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#ifndef NDN_MANAGEMENT_NFD_CHANNEL_STATUS_HPP
+#define NDN_MANAGEMENT_NFD_CHANNEL_STATUS_HPP
+
+#include "../encoding/tlv-nfd.hpp"
+#include "../encoding/encoding-buffer.hpp"
+#include "../encoding/block-helpers.hpp"
+
+#include "../util/time.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * @ingroup management
+ * @brief represents NFD Channel Status dataset
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Channel-Dataset
+ */
+class ChannelStatus
+{
+public:
+  class Error : public Tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Tlv::Error(what)
+    {
+    }
+  };
+
+  ChannelStatus()
+  {
+  }
+
+  explicit
+  ChannelStatus(const Block& payload)
+  {
+    this->wireDecode(payload);
+  }
+
+  template<bool T>
+  size_t
+  wireEncode(EncodingImpl<T>& encoder) const;
+
+  const Block&
+  wireEncode() const;
+
+  void
+  wireDecode(const Block& wire);
+
+public: // getters & setters
+  const std::string&
+  getLocalUri() const
+  {
+    return m_localUri;
+  }
+
+  ChannelStatus&
+  setLocalUri(const std::string localUri)
+  {
+    m_wire.reset();
+    m_localUri = localUri;
+    return *this;
+  }
+
+private:
+  std::string m_localUri;
+
+  mutable Block m_wire;
+};
+
+
+template<bool T>
+inline size_t
+ChannelStatus::wireEncode(EncodingImpl<T>& encoder) const
+{
+  size_t totalLength = 0;
+
+  totalLength += prependByteArrayBlock(encoder, tlv::nfd::LocalUri,
+                 reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(tlv::nfd::ChannelStatus);
+  return totalLength;
+}
+
+inline const Block&
+ChannelStatus::wireEncode() const
+{
+  if (m_wire.hasWire())
+    return m_wire;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+  return m_wire;
+}
+
+inline void
+ChannelStatus::wireDecode(const Block& block)
+{
+  if (block.type() != tlv::nfd::ChannelStatus) {
+    throw Error("expecting ChannelStatus block");
+  }
+  m_wire = block;
+  m_wire.parse();
+  Block::element_const_iterator val = m_wire.elements_begin();
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+    m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+    ++val;
+  }
+  else {
+    throw Error("missing required LocalUri field");
+  }
+}
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NFD_CHANNEL_STATUS_HPP
diff --git a/src/management/nfd-control-command.hpp b/src/management/nfd-control-command.hpp
index bde5725..1bf0c0c 100644
--- a/src/management/nfd-control-command.hpp
+++ b/src/management/nfd-control-command.hpp
@@ -19,8 +19,10 @@
 namespace ndn {
 namespace nfd {
 
-/** \brief base class of NFD ControlCommand
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+/**
+ * \ingroup management
+ * \brief base class of NFD ControlCommand
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
  */
 class ControlCommand : noncopyable
 {
@@ -174,8 +176,10 @@
 };
 
 
-/** \brief represents a faces/create command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Create-a-face
+/**
+ * \ingroup management
+ * \brief represents a faces/create command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Create-a-face
  */
 class FaceCreateCommand : public ControlCommand
 {
@@ -202,8 +206,10 @@
 };
 
 
-/** \brief represents a faces/destroy command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Destroy-a-face
+/**
+ * \ingroup management
+ * \brief represents a faces/destroy command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Destroy-a-face
  */
 class FaceDestroyCommand : public ControlCommand
 {
@@ -233,7 +239,10 @@
   }
 };
 
-
+/**
+ * \ingroup management
+ * \brief Base class for faces/[*]-local-control commands
+ */
 class FaceLocalControlCommand : public ControlCommand
 {
 public:
@@ -269,8 +278,10 @@
 };
 
 
-/** \brief represents a faces/enable-local-control command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Enable-a-LocalControlHeader-feature
+/**
+ * \ingroup management
+ * \brief represents a faces/enable-local-control command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Enable-a-LocalControlHeader-feature
  */
 class FaceEnableLocalControlCommand : public FaceLocalControlCommand
 {
@@ -282,8 +293,10 @@
 };
 
 
-/** \brief represents a faces/disable-local-control command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Disable-a-LocalControlHeader-feature
+/**
+ * \ingroup management
+ * \brief represents a faces/disable-local-control command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Disable-a-LocalControlHeader-feature
  */
 class FaceDisableLocalControlCommand : public FaceLocalControlCommand
 {
@@ -295,8 +308,10 @@
 };
 
 
-/** \brief represents a fib/add-nexthop command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Add-a-nexthop
+/**
+ * \ingroup management
+ * \brief represents a fib/add-nexthop command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Add-a-nexthop
  */
 class FibAddNextHopCommand : public ControlCommand
 {
@@ -334,8 +349,10 @@
 };
 
 
-/** \brief represents a fib/remove-nexthop command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Remove-a-nexthop
+/**
+ * \ingroup management
+ * \brief represents a fib/remove-nexthop command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Remove-a-nexthop
  */
 class FibRemoveNextHopCommand : public ControlCommand
 {
@@ -363,8 +380,10 @@
 };
 
 
-/** \brief represents a strategy-choice/set command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Set-the-strategy-for-a-namespace
+/**
+ * \ingroup management
+ * \brief represents a strategy-choice/set command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Set-the-strategy-for-a-namespace
  */
 class StrategyChoiceSetCommand : public ControlCommand
 {
@@ -380,8 +399,10 @@
 };
 
 
-/** \brief represents a strategy-choice/set command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Unset-the-strategy-for-a-namespace
+/**
+ * \ingroup management
+ * \brief represents a strategy-choice/set command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Unset-the-strategy-for-a-namespace
  */
 class StrategyChoiceUnsetCommand : public ControlCommand
 {
@@ -412,6 +433,9 @@
 };
 
 
+/**
+ * \ingroup management
+ */
 enum {
   // route origin
   ROUTE_ORIGIN_APP    = 0,
@@ -424,8 +448,10 @@
 };
 
 
-/** \brief represents a rib/register command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Register-a-route
+/**
+ * \ingroup management
+ * \brief represents a rib/register command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Register-a-route
  */
 class RibRegisterCommand : public ControlCommand
 {
@@ -486,8 +512,10 @@
 };
 
 
-/** \brief represents a rib/unregister command
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Unregister-a-route
+/**
+ * \ingroup management
+ * \brief represents a rib/unregister command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Unregister-a-route
  */
 class RibUnregisterCommand : public ControlCommand
 {
diff --git a/src/management/nfd-control-parameters.hpp b/src/management/nfd-control-parameters.hpp
index ea13b82..de9bf98 100644
--- a/src/management/nfd-control-parameters.hpp
+++ b/src/management/nfd-control-parameters.hpp
@@ -19,6 +19,9 @@
 namespace ndn {
 namespace nfd {
 
+/**
+ * \ingroup management
+ */
 enum ControlParameterField {
   CONTROL_PARAMETER_NAME,
   CONTROL_PARAMETER_FACE_ID,
@@ -44,13 +47,18 @@
   "ExpirationPeriod",
 };
 
+/**
+ * \ingroup management
+ */
 enum LocalControlFeature {
   LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID = 1,
   LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID = 2
 };
 
-/** \brief represents parameters in a ControlCommand request or response
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+/**
+ * \ingroup management
+ * \brief represents parameters in a ControlCommand request or response
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
  */
 class ControlParameters
 {
diff --git a/src/management/nfd-control-response.hpp b/src/management/nfd-control-response.hpp
index c239804..307200f 100644
--- a/src/management/nfd-control-response.hpp
+++ b/src/management/nfd-control-response.hpp
@@ -21,6 +21,7 @@
 namespace nfd {
 
 /**
+ * @ingroup management
  * @brief Class defining abstraction of ControlResponse for NFD Control Protocol
  *
  * @see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
diff --git a/src/management/nfd-controller.hpp b/src/management/nfd-controller.hpp
index 52b37a6..34b6e54 100644
--- a/src/management/nfd-controller.hpp
+++ b/src/management/nfd-controller.hpp
@@ -19,7 +19,13 @@
 namespace ndn {
 namespace nfd {
 
-/** \brief NFD Management protocol - ControlCommand client
+/**
+ * \defgroup management
+ * \brief Classes and data structures to manage NDN forwarder
+ */
+/**
+ * \ingroup management
+ * \brief NFD Management protocol - ControlCommand client
  */
 class Controller : noncopyable
 {
diff --git a/src/management/nfd-face-event-notification.hpp b/src/management/nfd-face-event-notification.hpp
index 6432d30..7f5b5fa 100644
--- a/src/management/nfd-face-event-notification.hpp
+++ b/src/management/nfd-face-event-notification.hpp
@@ -23,13 +23,18 @@
 namespace ndn {
 namespace nfd {
 
+/**
+ * \ingroup management
+ */
 enum FaceEventKind {
   FACE_EVENT_CREATED = 1,
   FACE_EVENT_DESTROYED = 2
 };
 
-/** \brief represents a Face status change notification
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Status-Change-Notification
+/**
+ * \ingroup management
+ * \brief represents a Face status change notification
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Status-Change-Notification
  */
 class FaceEventNotification : public FaceFlagsTraits<FaceEventNotification>
 {
diff --git a/src/management/nfd-face-flags.hpp b/src/management/nfd-face-flags.hpp
index 9671ee4..15595ed 100644
--- a/src/management/nfd-face-flags.hpp
+++ b/src/management/nfd-face-flags.hpp
@@ -16,8 +16,10 @@
 namespace ndn {
 namespace nfd {
 
-/** \class FaceFlags
- *  \brief provides additional information about a face
+/**
+ * \ingroup management
+ * \enum FaceFlags
+ * \brief provides additional information about a face
  */
 enum {
   /** \brief face is local (for scope control purpose)
@@ -31,10 +33,12 @@
   // FACE_? = 8
 };
 
-/** \brief implements getters to each face flag
+/**
+ * \ingroup management
+ * \brief implements getters to each face flag
  *
- *  \tparam T class containing a FaceFlags field and implements
- *            `FaceFlags getFlags() const` method
+ * \tparam T class containing a FaceFlags field and implements
+ *           `FaceFlags getFlags() const` method
  */
 template<typename T>
 class FaceFlagsTraits
diff --git a/src/management/nfd-face-status.hpp b/src/management/nfd-face-status.hpp
index 02e9b9a..b4ae417 100644
--- a/src/management/nfd-face-status.hpp
+++ b/src/management/nfd-face-status.hpp
@@ -23,8 +23,10 @@
 namespace ndn {
 namespace nfd {
 
-/** \brief represents Face status
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset
+/**
+ * \ingroup management
+ * \brief represents Face status
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset
  */
 class FaceStatus : public FaceFlagsTraits<FaceStatus>
 {
diff --git a/src/management/nfd-fib-entry.hpp b/src/management/nfd-fib-entry.hpp
index eaa372c..74a2b5e 100644
--- a/src/management/nfd-fib-entry.hpp
+++ b/src/management/nfd-fib-entry.hpp
@@ -27,6 +27,9 @@
 //                    FaceId
 //                    Cost
 
+/**
+ * @ingroup management
+ */
 class NextHopRecord
 {
 public:
@@ -171,6 +174,9 @@
 //                    Name
 //                    NextHopRecord*
 
+/**
+ * @ingroup management
+ */
 class FibEntry
 {
 public:
diff --git a/src/management/nfd-forwarder-status.hpp b/src/management/nfd-forwarder-status.hpp
index 43e6150..db0bdbe 100644
--- a/src/management/nfd-forwarder-status.hpp
+++ b/src/management/nfd-forwarder-status.hpp
@@ -22,8 +22,10 @@
 namespace ndn {
 namespace nfd {
 
-/** \brief represents NFD Forwarder Status
- *  \sa http://redmine.named-data.net/projects/nfd/wiki/ForwarderStatus
+/**
+ * \ingroup management
+ * \brief represents NFD Forwarder Status
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ForwarderStatus
  */
 class ForwarderStatus
 {
diff --git a/src/management/nfd-local-control-header.hpp b/src/management/nfd-local-control-header.hpp
index e6fae95..fc73b50 100644
--- a/src/management/nfd-local-control-header.hpp
+++ b/src/management/nfd-local-control-header.hpp
@@ -19,6 +19,11 @@
 namespace ndn {
 namespace nfd {
 
+/**
+ * @ingroup management
+ * @brief Class to handle work with LocalControlHeader
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/LocalControlHeader
+ */
 class LocalControlHeader
 {
 public:
diff --git a/src/management/nfd-strategy-choice.hpp b/src/management/nfd-strategy-choice.hpp
new file mode 100644
index 0000000..3f9fa8c
--- /dev/null
+++ b/src/management/nfd-strategy-choice.hpp
@@ -0,0 +1,165 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#ifndef NDN_MANAGEMENT_NFD_STRATEGY_CHOICE_HPP
+#define NDN_MANAGEMENT_NFD_STRATEGY_CHOICE_HPP
+
+#include "../encoding/tlv-nfd.hpp"
+#include "../encoding/encoding-buffer.hpp"
+#include "../encoding/block-helpers.hpp"
+#include "../name.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * @ingroup management
+ * @brief represents NFD StrategyChoice dataset
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Strategy-Choice-Dataset
+ */
+class StrategyChoice
+{
+public:
+  class Error : public Tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Tlv::Error(what)
+    {
+    }
+  };
+
+  StrategyChoice()
+  {
+  }
+
+  explicit
+  StrategyChoice(const Block& payload)
+  {
+    this->wireDecode(payload);
+  }
+
+  template<bool T>
+  size_t
+  wireEncode(EncodingImpl<T>& encoder) const;
+
+  const Block&
+  wireEncode() const;
+
+  void
+  wireDecode(const Block& wire);
+
+public: // getters & setters
+  const Name&
+  getName() const
+  {
+    return m_name;
+  }
+
+  StrategyChoice&
+  setName(const Name& name)
+  {
+    m_wire.reset();
+    m_name = name;
+    return *this;
+  }
+
+  const Name&
+  getStrategy() const
+  {
+    return m_strategy;
+  }
+
+  StrategyChoice&
+  setStrategy(const Name& strategy)
+  {
+    m_wire.reset();
+    m_strategy = strategy;
+    return *this;
+  }
+
+private:
+  Name m_name; // namespace
+  Name m_strategy; // strategy for the namespace
+
+  mutable Block m_wire;
+};
+
+
+template<bool T>
+inline size_t
+StrategyChoice::wireEncode(EncodingImpl<T>& encoder) const
+{
+  size_t totalLength = 0;
+
+  totalLength += prependNestedBlock(encoder, tlv::nfd::Strategy, m_strategy);
+  totalLength += m_name.wireEncode(encoder);
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(tlv::nfd::StrategyChoice);
+  return totalLength;
+}
+
+inline const Block&
+StrategyChoice::wireEncode() const
+{
+  if (m_wire.hasWire())
+    return m_wire;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+  return m_wire;
+}
+
+inline void
+StrategyChoice::wireDecode(const Block& block)
+{
+  if (block.type() != tlv::nfd::StrategyChoice) {
+    throw Error("expecting StrategyChoice block");
+  }
+  m_wire = block;
+  m_wire.parse();
+  Block::element_const_iterator val = m_wire.elements_begin();
+
+  if (val != m_wire.elements_end() && val->type() == Tlv::Name) {
+    m_name.wireDecode(*val);
+    ++val;
+  }
+  else {
+    throw Error("missing required Name field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::Strategy) {
+    val->parse();
+    if (val->elements().empty()) {
+      throw Error("expecting Strategy/Name");
+    }
+    else {
+      m_strategy.wireDecode(*val->elements_begin());
+    }
+    ++val;
+  }
+  else {
+    throw Error("missing required Strategy field");
+  }
+}
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NFD_STRATEGY_CHOICE_HPP
diff --git a/tests/management/test-nfd-channel-status.cpp b/tests/management/test-nfd-channel-status.cpp
new file mode 100644
index 0000000..52329a5
--- /dev/null
+++ b/tests/management/test-nfd-channel-status.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#include "management/nfd-channel-status.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace nfd {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(ManagementTestNfdChannelStatus)
+
+BOOST_AUTO_TEST_CASE(Encode)
+{
+  ChannelStatus status1;
+  status1
+    .setLocalUri("udp4://192.168.2.1")
+    ;
+
+  Block wire;
+  BOOST_REQUIRE_NO_THROW(wire = status1.wireEncode());
+
+  // These octets are obtained by the snippet below.
+  // This check is intended to detect unexpected encoding change in the future.
+  // for (Buffer::const_iterator it = wire.begin(); it != wire.end(); ++it) {
+  //  printf("0x%02x, ", *it);
+  // }
+  static const uint8_t expected[] = {
+    0x82, 0x14, 0x81, 0x12, 0x75, 0x64, 0x70, 0x34, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32,
+    0x2e, 0x31, 0x36, 0x38, 0x2e, 0x32, 0x2e, 0x31
+  };
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
+                                  wire.begin(), wire.end());
+
+  BOOST_REQUIRE_NO_THROW(ChannelStatus(wire));
+  ChannelStatus status2(wire);
+  BOOST_CHECK_EQUAL(status1.getLocalUri(), status2.getLocalUri());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd
+} // namespace ndn
diff --git a/tests/management/test-nfd-strategy-choice.cpp b/tests/management/test-nfd-strategy-choice.cpp
new file mode 100644
index 0000000..c88a9b4
--- /dev/null
+++ b/tests/management/test-nfd-strategy-choice.cpp
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (c) 2013-2014,  Regents of the University of California.
+ * All rights reserved.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * This file licensed under New BSD License.  See COPYING for detailed information about
+ * ndn-cxx library copyright, permissions, and redistribution restrictions.
+ */
+
+#include "management/nfd-strategy-choice.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace nfd {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(ManagementTestNfdStrategyChoice)
+
+BOOST_AUTO_TEST_CASE(Encode)
+{
+  StrategyChoice strategyChoice1;
+  strategyChoice1
+    .setName("/hello/world")
+    .setStrategy("/some/non/existing/strategy/name")
+    ;
+
+  Block wire;
+  BOOST_REQUIRE_NO_THROW(wire = strategyChoice1.wireEncode());
+
+  // These octets are obtained by the snippet below.
+  // This check is intended to detect unexpected encoding change in the future.
+  // for (Buffer::const_iterator it = wire.begin(); it != wire.end(); ++it) {
+  //  printf("0x%02x, ", *it);
+  // }
+  static const uint8_t expected[] = {
+    0x80, 0x39, 0x07, 0x0e, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x08, 0x05, 0x77,
+    0x6f, 0x72, 0x6c, 0x64, 0x6b, 0x27, 0x07, 0x25, 0x08, 0x04, 0x73, 0x6f, 0x6d, 0x65,
+    0x08, 0x03, 0x6e, 0x6f, 0x6e, 0x08, 0x08, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e,
+    0x67, 0x08, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x08, 0x04, 0x6e,
+    0x61, 0x6d, 0x65
+  };
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(expected, expected + sizeof(expected),
+                                  wire.begin(), wire.end());
+
+  BOOST_REQUIRE_NO_THROW(StrategyChoice(wire));
+  StrategyChoice strategyChoice2(wire);
+  BOOST_CHECK_EQUAL(strategyChoice1.getName(), strategyChoice2.getName());
+  BOOST_CHECK_EQUAL(strategyChoice1.getStrategy(), strategyChoice2.getStrategy());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd
+} // namespace ndn