/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (C) 2014 Named Data Networking Project
 * See COPYING for copyright and distribution information.
 */

#include "mgmt/status-server.hpp"
#include "fw/forwarder.hpp"
#include "core/version.hpp"
#include "mgmt/internal-face.hpp"

#include "tests/test-common.hpp"
#include "tests/face/dummy-face.hpp"

namespace nfd {
namespace tests {

BOOST_FIXTURE_TEST_SUITE(MgmtStatusServer, BaseFixture)

static inline ndn::nfd::Status::Timestamp
now()
{
  return ndn::nfd::Status::Timestamp(
    boost::chrono::duration_cast<ndn::nfd::Status::Timestamp::duration>(
      boost::chrono::system_clock::now().time_since_epoch()
    )
  );
}

shared_ptr<const Data> g_response;

void
interceptResponse(const Data& data)
{
  g_response = data.shared_from_this();
}

BOOST_AUTO_TEST_CASE(Status)
{
  // initialize
  ndn::nfd::Status::Timestamp t1 = now();
  Forwarder forwarder;
  shared_ptr<InternalFace> internalFace = make_shared<InternalFace>();
  internalFace->onReceiveData += &interceptResponse;
  StatusServer statusServer(internalFace, boost::ref(forwarder));
  ndn::nfd::Status::Timestamp t2 = now();
  
  // populate tables
  forwarder.getFib().insert("ndn:/fib1");
  forwarder.getPit().insert(*makeInterest("ndn:/pit1"));
  forwarder.getPit().insert(*makeInterest("ndn:/pit2"));
  forwarder.getPit().insert(*makeInterest("ndn:/pit3"));
  forwarder.getPit().insert(*makeInterest("ndn:/pit4"));
  forwarder.getMeasurements().get("ndn:/measurements1");
  forwarder.getMeasurements().get("ndn:/measurements2");
  forwarder.getMeasurements().get("ndn:/measurements3");
  BOOST_CHECK_GE(forwarder.getFib().size(), 1);
  BOOST_CHECK_GE(forwarder.getPit().size(), 4);
  BOOST_CHECK_GE(forwarder.getMeasurements().size(), 3);
  
  // request
  shared_ptr<Interest> request = makeInterest("ndn:/localhost/nfd/status");
  request->setMustBeFresh(true);
  request->setChildSelector(1);
  
  g_response.reset();
  ndn::nfd::Status::Timestamp t3 = now();
  internalFace->sendInterest(*request);
  ndn::nfd::Status::Timestamp t4 = now();
  BOOST_REQUIRE(static_cast<bool>(g_response));
  
  // verify
  ndn::nfd::Status status;
  BOOST_REQUIRE_NO_THROW(status.wireDecode(g_response->getContent()));
  
  BOOST_CHECK_EQUAL(status.getNfdVersion(), NFD_VERSION);
  BOOST_CHECK_GE(status.getStartTimestamp(), t1);
  BOOST_CHECK_LE(status.getStartTimestamp(), t2);
  BOOST_CHECK_GE(status.getCurrentTimestamp(), t3);
  BOOST_CHECK_LE(status.getCurrentTimestamp(), t4);
  
  // StatusServer under test isn't added to Forwarder,
  // so request and response won't affect table size
  BOOST_CHECK_EQUAL(status.getNNameTreeEntries(), forwarder.getNameTree().size());
  BOOST_CHECK_EQUAL(status.getNFibEntries(), forwarder.getFib().size());
  BOOST_CHECK_EQUAL(status.getNPitEntries(), forwarder.getPit().size());
  BOOST_CHECK_EQUAL(status.getNMeasurementsEntries(), forwarder.getMeasurements().size());
  BOOST_CHECK_EQUAL(status.getNCsEntries(), forwarder.getCs().size());
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace nfd
