/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2017,  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/>.
 */

#ifndef NFD_TESTS_TOOLS_NFDC_STATUS_FIXTURE_HPP
#define NFD_TESTS_TOOLS_NFDC_STATUS_FIXTURE_HPP

#include "mock-nfd-mgmt-fixture.hpp"
#include "nfdc/module.hpp"
#include <ndn-cxx/security/validator-null.hpp>

namespace nfd {
namespace tools {
namespace nfdc {
namespace tests {

using ndn::Face;
using ndn::KeyChain;
using ndn::security::v2::Validator;
using ndn::security::v2::ValidatorNull;
using boost::test_tools::output_test_stream;

class MakeValidatorNull
{
public:
  unique_ptr<ValidatorNull>
  operator()(Face&, KeyChain&) const
  {
    return make_unique<ValidatorNull>();
  };
};

/** \brief fixture to test status fetching routines in a \p Module
 *  \tparam M a subclass of \p Module
 *  \tparam MakeValidator a callable to make a Validator for use in \p controller;
 *                        MakeValidator()(Face&, KeyChain&) should return a unique_ptr
 *                        to Validator or its subclass
 */
template<typename M, typename MakeValidator = MakeValidatorNull>
class StatusFixture : public MockNfdMgmtFixture
{
protected:
  using ValidatorUniquePtr = typename std::result_of<MakeValidator(Face&, KeyChain&)>::type;

  StatusFixture()
    : validator(MakeValidator()(face, m_keyChain))
    , controller(face, m_keyChain, *validator)
    , nFetchStatusSuccess(0)
  {
  }

protected: // status fetching
  /** \brief start fetching status
   *
   *  A test case should call \p fetchStatus, \p sendDataset, and \p prepareStatusOutput
   *  in this order, and then check \p statusXml and \p statusText contain the correct outputs.
   *  No advanceClocks is needed in between, as they are handled by the fixture.
   */
  void
  fetchStatus()
  {
    nFetchStatusSuccess = 0;
    module.fetchStatus(controller, [this] { ++nFetchStatusSuccess; },
                       [this] (uint32_t code, const std::string& reason) {
                         BOOST_FAIL("fetchStatus failure " << code << " " << reason);
                       },
                       CommandOptions());
    this->advanceClocks(time::milliseconds(1));
  }

  /** \brief prepare status output as XML and text
   *  \pre sendDataset has been invoked
   */
  void
  prepareStatusOutput()
  {
    this->advanceClocks(time::milliseconds(1));
    BOOST_REQUIRE_EQUAL(nFetchStatusSuccess, 1);

    statusXml.str("");
    module.formatStatusXml(statusXml);
    statusText.str("");
    module.formatStatusText(statusText);
  }

protected:
  ValidatorUniquePtr validator;
  Controller controller;

  M module;

  int nFetchStatusSuccess;
  output_test_stream statusXml;
  output_test_stream statusText;
};

/** \brief strips leading spaces on every line in expected XML
 *
 *  This allows expected XML to be written as:
 *  \code
 *  const std::string STATUS_XML = stripXmlSpaces(R"XML(
 *    <rootElement>
 *      <element>value</element>
 *    </rootElement>
 *  )XML");
 *  \endcode
 *  And \p STATUS_XML would be assigned:
 *  \code
 *  "<rootElement><element>value</element></rootElement>"
 *  \endcode
 */
inline std::string
stripXmlSpaces(const std::string& xml)
{
  std::string s;
  bool isSkipping = true;
  std::copy_if(xml.begin(), xml.end(), std::back_inserter(s),
               [&isSkipping] (char ch) {
                 if (ch == '\n') {
                   isSkipping = true;
                 }
                 else if (ch != ' ') {
                   isSkipping = false;
                 }
                 return !isSkipping;
               });
  return s;
}

} // namespace tests
} // namespace nfdc
} // namespace tools
} // namespace nfd

#endif // NFD_TESTS_TOOLS_NFDC_STATUS_FIXTURE_HPP
