/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2024 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#define BOOST_TEST_MODULE ndn-cxx Integration (Face)
#include "tests/boost-test.hpp"

#include "ndn-cxx/face.hpp"
#include "ndn-cxx/transport/tcp-transport.hpp"
#include "ndn-cxx/transport/unix-transport.hpp"
#include "ndn-cxx/util/scheduler.hpp"

#include "tests/key-chain-fixture.hpp"
#include "tests/test-common.hpp"

#include <stdio.h>
#include <condition_variable>
#include <mutex>
#include <thread>

#include <boost/mp11/list.hpp>

namespace ndn::tests {

static Name
makeVeryLongName(Name prefix = Name())
{
  for (size_t i = 0; i <= MAX_NDN_PACKET_SIZE / 10; i++) {
    prefix.append("0123456789");
  }
  return prefix;
}

static std::string
executeCommand(const std::string& cmd)
{
  std::string output;
  char buf[256];
  FILE* pipe = popen(cmd.data(), "r");
  BOOST_REQUIRE_MESSAGE(pipe != nullptr, "popen(" << cmd << ")");
  while (fgets(buf, sizeof(buf), pipe) != nullptr) {
    output += buf;
  }
  pclose(pipe);
  return output;
}

template<typename TransportType>
class FaceFixture : public KeyChainFixture
{
protected:
  FaceFixture()
    : face(TransportType::create(""), m_keyChain)
    , sched(face.getIoContext())
  {
  }

  /** \brief Send an Interest from a secondary face
   *  \param delay scheduling delay before sending Interest
   *  \param interest the Interest
   *  \param[out] outcome the response, initially '?', 'D' for Data, 'N' for Nack, 'T' for timeout
   *  \return scheduled event id
   */
  scheduler::EventId
  sendInterest(time::nanoseconds delay, const Interest& interest, char& outcome)
  {
    if (face2 == nullptr) {
      face2 = make_unique<Face>(TransportType::create(""), face.getIoContext(), m_keyChain);
    }

    outcome = '?';
    return sched.schedule(delay, [this, interest, &outcome] {
      face2->expressInterest(interest,
        [&] (const Interest&, const Data&) { outcome = 'D'; },
        [&] (const Interest&, const lp::Nack&) { outcome = 'N'; },
        [&] (const Interest&) { outcome = 'T'; });
    });
  }

  scheduler::EventId
  sendInterest(time::nanoseconds delay, const Interest& interest)
  {
    static char ignoredOutcome;
    return sendInterest(delay, interest, ignoredOutcome);
  }

  /** \brief Stop io_context after a delay
   *  \return scheduled event id
   */
  scheduler::EventId
  terminateAfter(time::nanoseconds delay)
  {
    return sched.schedule(delay, [this] { face.getIoContext().stop(); });
  }

protected:
  Face face;
  unique_ptr<Face> face2;
  Scheduler sched;
};

using Transports = boost::mp11::mp_list<UnixTransport, TcpTransport>;

BOOST_AUTO_TEST_SUITE(Consumer)

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExpressInterestData, TransportType, Transports, FaceFixture<TransportType>)
{
  int nData = 0;
  this->face.expressInterest(*makeInterest("/localhost", true),
    [&] (const Interest&, const Data&) { ++nData; },
    [] (const Interest&, const lp::Nack&) { BOOST_ERROR("unexpected Nack"); },
    [] (const Interest&) { BOOST_ERROR("unexpected timeout"); });

  this->face.processEvents();
  BOOST_CHECK_EQUAL(nData, 1);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExpressInterestNack, TransportType, Transports, FaceFixture<TransportType>)
{
  int nNacks = 0;
  this->face.expressInterest(*makeInterest("/localhost/non-existent-should-nack"),
    [] (const Interest&, const Data&) { BOOST_ERROR("unexpected Data"); },
    [&] (const Interest&, const lp::Nack&) { ++nNacks; },
    [] (const Interest&) { BOOST_ERROR("unexpected timeout"); });

  this->face.processEvents();
  BOOST_CHECK_EQUAL(nNacks, 1);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ExpressInterestTimeout, TransportType, Transports, FaceFixture<TransportType>)
{
  // add route toward null face so Interest would timeout instead of getting Nacked
  executeCommand("nfdc route add /localhost/non-existent-should-timeout null://");
  std::this_thread::sleep_for(std::chrono::milliseconds(200)); // wait for FIB update to take effect

  int nTimeouts = 0;
  this->face.expressInterest(*makeInterest("/localhost/non-existent-should-timeout", false, 1_s),
    [] (const Interest&, const Data&) { BOOST_ERROR("unexpected Data"); },
    [] (const Interest&, const lp::Nack&) { BOOST_ERROR("unexpected Nack"); },
    [&] (const Interest&) { ++nTimeouts; });

  this->face.processEvents();
  BOOST_CHECK_EQUAL(nTimeouts, 1);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(OversizedInterest, TransportType, Transports, FaceFixture<TransportType>)
{
  BOOST_CHECK_THROW(do {
    this->face.expressInterest(*makeInterest(makeVeryLongName()), nullptr, nullptr, nullptr);
    this->face.processEvents();
  } while (false), Face::OversizedPacketError);
}

BOOST_AUTO_TEST_SUITE_END() // Consumer

BOOST_AUTO_TEST_SUITE(Producer)

BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegisterUnregisterPrefix, TransportType, Transports, FaceFixture<TransportType>)
{
  this->terminateAfter(4_s);

  int nRegSuccess = 0, nUnregSuccess = 0;
  auto handle = this->face.registerPrefix("/Hello/World",
    [&] (const Name&) { ++nRegSuccess; },
    [] (const Name&, const auto& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });

  this->sched.schedule(1_s, [&nRegSuccess] {
    BOOST_CHECK_EQUAL(nRegSuccess, 1);
    std::string output = executeCommand("nfdc route list | grep /Hello/World");
    BOOST_CHECK(!output.empty());
  });

  this->sched.schedule(2_s, [&] {
    handle.unregister(
      [&] { ++nUnregSuccess; },
      [] (const auto& msg) { BOOST_ERROR("unexpected unregister prefix failure: " << msg); });
  });

  this->sched.schedule(3_s, [&nUnregSuccess] {
    BOOST_CHECK_EQUAL(nUnregSuccess, 1);

    // Boost.Test would fail if a child process exits with non-zero. http://stackoverflow.com/q/5325202
    std::string output = executeCommand("nfdc route list | grep /Hello/World || true");
    BOOST_CHECK(output.empty());
  });

  this->face.processEvents();
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegularFilter, TransportType, Transports, FaceFixture<TransportType>)
{
  this->terminateAfter(2_s);

  int nInterests1 = 0, nRegSuccess1 = 0, nRegSuccess2 = 0;
  this->face.setInterestFilter("/Hello/World",
    [&] (const InterestFilter&, const Interest&) { ++nInterests1; },
    [&] (const Name&) { ++nRegSuccess1; },
    [] (const Name&, const auto& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });
  this->face.setInterestFilter("/Los/Angeles/Lakers",
    [&] (const InterestFilter&, const Interest&) { BOOST_ERROR("unexpected Interest"); },
    [&] (const Name&) { ++nRegSuccess2; },
    [] (const Name&, const auto& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });

  this->sched.schedule(500_ms, [] {
    std::string output = executeCommand("nfdc route list | grep /Hello/World");
    BOOST_CHECK(!output.empty());
  });

  char interestOutcome;
  this->sendInterest(1_s, *makeInterest("/Hello/World/regular", false, 50_ms), interestOutcome);

  this->face.processEvents();
  BOOST_CHECK_EQUAL(interestOutcome, 'T');
  BOOST_CHECK_EQUAL(nInterests1, 1);
  BOOST_CHECK_EQUAL(nRegSuccess1, 1);
  BOOST_CHECK_EQUAL(nRegSuccess2, 1);
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegexFilter, TransportType, Transports, FaceFixture<TransportType>)
{
  this->terminateAfter(2_s);

  int nRegSuccess = 0;
  std::set<Name> receivedInterests;
  this->face.setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
    [&] (auto&&, const auto& interest) { receivedInterests.insert(interest.getName()); },
    [&] (auto&&) { ++nRegSuccess; },
    [] (auto&&, const auto& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });

  this->sched.schedule(700_ms, [] {
    std::string output = executeCommand("nfdc route list | grep /Hello/World");
    BOOST_CHECK(!output.empty());
  });

  this->sendInterest(200_ms, *makeInterest("/Hello/World/a", false, 50_ms));
  this->sendInterest(300_ms, *makeInterest("/Hello/World/a/b", false, 50_ms));
  this->sendInterest(400_ms, *makeInterest("/Hello/World/a/b/c", false, 50_ms));
  this->sendInterest(500_ms, *makeInterest("/Hello/World/a/b/d", false, 50_ms));

  this->face.processEvents();
  BOOST_CHECK_EQUAL(nRegSuccess, 1);
  std::set<Name> expectedInterests{"/Hello/World/a/b", "/Hello/World/a/b/c"};
  BOOST_TEST(receivedInterests == expectedInterests, boost::test_tools::per_element());
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(RegexFilterNoRegister, TransportType, Transports, FaceFixture<TransportType>)
{
  this->terminateAfter(2_s);

  // no Interest shall arrive because prefix isn't registered in forwarder
  this->face.setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
    [&] (const InterestFilter&, const Interest&) { BOOST_ERROR("unexpected Interest"); });

  this->sched.schedule(700_ms, [] {
    // Boost.Test would fail if a child process exits with non-zero. http://stackoverflow.com/q/5325202
    std::string output = executeCommand("nfdc route list | grep /Hello/World || true");
    BOOST_CHECK(output.empty());
  });

  this->sendInterest(200_ms, *makeInterest("/Hello/World/a", false, 50_ms));
  this->sendInterest(300_ms, *makeInterest("/Hello/World/a/b", false, 50_ms));
  this->sendInterest(400_ms, *makeInterest("/Hello/World/a/b/c", false, 50_ms));
  this->sendInterest(500_ms, *makeInterest("/Hello/World/a/b/d", false, 50_ms));

  this->face.processEvents();
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(PutDataNack, TransportType, Transports, FaceFixture<TransportType>)
{
  this->terminateAfter(2_s);

  this->face.setInterestFilter("/Hello/World",
    [&] (const InterestFilter&, const Interest& interest) {
      if (interest.getName().at(2) == name::Component("nack")) {
        this->face.put(makeNack(interest, lp::NackReason::NO_ROUTE));
      }
      else {
        this->face.put(*makeData(interest.getName()));
      }
    },
    nullptr,
    [] (const Name&, const auto& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });

  char outcome1, outcome2;
  this->sendInterest(700_ms, *makeInterest("/Hello/World/data", false, 50_ms), outcome1);
  this->sendInterest(800_ms, *makeInterest("/Hello/World/nack", false, 50_ms), outcome2);

  this->face.processEvents();
  BOOST_CHECK_EQUAL(outcome1, 'D');
  BOOST_CHECK_EQUAL(outcome2, 'N');
}

BOOST_FIXTURE_TEST_CASE_TEMPLATE(OversizedData, TransportType, Transports, FaceFixture<TransportType>)
{
  this->terminateAfter(2_s);

  this->face.setInterestFilter("/Hello/World",
    [&] (const InterestFilter&, const Interest& interest) {
      this->face.put(*makeData(makeVeryLongName(interest.getName())));
    },
    nullptr,
    [] (const Name&, const auto& msg) { BOOST_ERROR("unexpected register prefix failure: " << msg); });

  this->sendInterest(1_s, *makeInterest("/Hello/World/oversized", true, 50_ms));

  BOOST_CHECK_THROW(this->face.processEvents(), Face::OversizedPacketError);
}

BOOST_AUTO_TEST_SUITE_END() // Producer

BOOST_FIXTURE_TEST_SUITE(IoRoutine, FaceFixture<UnixTransport>)

BOOST_AUTO_TEST_CASE(ShutdownWhileSendInProgress,
  * ut::description("test for bug #3136"))
{
  this->face.expressInterest(*makeInterest("/Hello/World"), nullptr, nullptr, nullptr);
  this->face.processEvents(1_s);

  this->face.expressInterest(*makeInterest("/Bye/World/1"), nullptr, nullptr, nullptr);
  this->face.expressInterest(*makeInterest("/Bye/World/2"), nullptr, nullptr, nullptr);
  this->face.expressInterest(*makeInterest("/Bye/World/3"), nullptr, nullptr, nullptr);
  this->face.shutdown();

  this->face.processEvents(1_s); // should not segfault
  BOOST_CHECK(true);
}

BOOST_AUTO_TEST_CASE(LargeDelayBetweenFaceConstructorAndProcessEvents,
  * ut::description("test for bug #2742"))
{
  std::this_thread::sleep_for(std::chrono::seconds(5)); // simulate setup workload
  this->face.processEvents(1_s); // should not throw
  BOOST_CHECK(true);
}

BOOST_AUTO_TEST_CASE(ProcessEventsBlocksForeverWhenNothingScheduled,
  * ut::description("test for bug #3957"))
{
  std::mutex m;
  std::condition_variable cv;
  bool processEventsFinished = false;

  std::thread faceThread([&] {
    this->face.processEvents();

    processEventsFinished = true;
    std::lock_guard<std::mutex> lk(m);
    cv.notify_one();
  });

  {
    std::unique_lock<std::mutex> lk(m);
    cv.wait_for(lk, std::chrono::seconds(5), [&] { return processEventsFinished; });
  }

  BOOST_CHECK_EQUAL(processEventsFinished, true);
  if (!processEventsFinished) {
    this->face.shutdown();
  }
  faceThread.join();
}

BOOST_AUTO_TEST_SUITE_END() // IoRoutine

} // namespace ndn::tests
