/* -*- 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/>.
 */

#include "ndn-autoconfig-server/program.hpp"

#include "tests/identity-management-fixture.hpp"
#include <ndn-cxx/encoding/buffer.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>

namespace ndn {
namespace tools {
namespace autoconfig_server {
namespace tests {

using namespace ::nfd::tests;

class AutoconfigServerFixture : public IdentityManagementFixture
{
public:
  AutoconfigServerFixture()
    : face({true, true})
  {
  }

  void
  initialize(const Options& options)
  {
    program = make_unique<Program>(options, face, m_keyChain);
    face.processEvents(time::milliseconds(1));
    face.sentInterests.clear();
  }

public:
  util::DummyClientFace face;
  unique_ptr<Program> program;
};

BOOST_AUTO_TEST_SUITE(NdnAutoconfigServer)
BOOST_FIXTURE_TEST_SUITE(TestProgram, AutoconfigServerFixture)

BOOST_AUTO_TEST_CASE(HubData)
{
  Options options;
  options.hubFaceUri = FaceUri("udp4://192.0.2.1:6363");
  this->initialize(options);

  Interest interest("/localhop/ndn-autoconf/hub");
  face.receive(interest);
  face.processEvents(time::milliseconds(1));

  BOOST_CHECK_EQUAL(face.sentData.size(), 1);
  const Name& dataName = face.sentData.at(0).getName();
  BOOST_CHECK_EQUAL(dataName.size(), interest.getName().size() + 1);
  BOOST_CHECK(interest.getName().isPrefixOf(dataName));
  BOOST_CHECK(dataName.at(-1).isVersion());

  // interest2 asks for a different version, and should not be responded
  Interest interest2(Name(interest.getName()).appendVersion(dataName.at(-1).toVersion() - 1));
  face.receive(interest2);
  face.processEvents(time::milliseconds(1));
  BOOST_CHECK_EQUAL(face.sentData.size(), 1);
}

BOOST_AUTO_TEST_CASE(RoutablePrefixesDataset)
{
  Options options;
  options.hubFaceUri = FaceUri("udp4://192.0.2.1:6363");
  const int nRoutablePrefixes = 2000;
  for (int i = 0; i < nRoutablePrefixes; ++i) {
    options.routablePrefixes.push_back(Name("/PREFIX").appendNumber(i));
  }
  this->initialize(options);

  Interest interest("/localhop/nfd/rib/routable-prefixes");
  face.receive(interest);
  face.processEvents(time::milliseconds(1));

  BOOST_CHECK_EQUAL(face.sentData.size(), 1);
  const Name& dataName0 = face.sentData.at(0).getName();
  BOOST_CHECK_EQUAL(dataName0.size(), interest.getName().size() + 2);
  BOOST_CHECK(interest.getName().isPrefixOf(dataName0));
  BOOST_CHECK(dataName0.at(-2).isVersion());
  BOOST_CHECK(dataName0.at(-1).isSegment());

  while (face.sentData.back().getFinalBlockId() != face.sentData.back().getName().at(-1)) {
    const Name& lastName = face.sentData.back().getName();
    Interest interest2(lastName.getPrefix(-1).appendSegment(lastName.at(-1).toSegment() + 1));
    face.receive(interest2);
    face.processEvents(time::milliseconds(1));
  }

  auto buffer = make_shared<Buffer>();
  for (const Data& data : face.sentData) {
    const Block& content = data.getContent();
    std::copy(content.value_begin(), content.value_end(), std::back_inserter(*buffer));
  }

  Block payload(tlv::Content, buffer);
  payload.parse();
  BOOST_CHECK_EQUAL(payload.elements_size(), nRoutablePrefixes);
  for (int i = 0; i < nRoutablePrefixes; ++i) {
    BOOST_CHECK_EQUAL(Name(payload.elements().at(i)), options.routablePrefixes.at(i));
  }
}

BOOST_AUTO_TEST_CASE(RoutablePrefixesDisabled)
{
  Options options;
  options.hubFaceUri = FaceUri("udp4://192.0.2.1:6363");
  this->initialize(options);

  Interest interest("/localhop/nfd/rib/routable-prefixes");
  face.receive(interest);
  face.processEvents(time::milliseconds(1));
  BOOST_CHECK_EQUAL(face.sentData.size(), 0);
}

BOOST_AUTO_TEST_SUITE_END() // TestProgram
BOOST_AUTO_TEST_SUITE_END() // NdnAutoconfigServer

} // namespace tests
} // namespace autoconfig_server
} // namespace tools
} // namespace ndn
