/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2021,  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 "fw/multicast-strategy.hpp"
#include "common/global.hpp"

#include "tests/test-common.hpp"
#include "tests/daemon/face/dummy-face.hpp"
#include "choose-strategy.hpp"
#include "strategy-tester.hpp"
#include "topology-tester.hpp"

namespace nfd {
namespace fw {
namespace tests {

using MulticastStrategyTester = StrategyTester<MulticastStrategy>;
NFD_REGISTER_STRATEGY(MulticastStrategyTester);

class MulticastStrategyFixture : public GlobalIoTimeFixture
{
protected:
  MulticastStrategyFixture()
    : strategy(choose<MulticastStrategyTester>(forwarder))
    , face1(make_shared<DummyFace>())
    , face2(make_shared<DummyFace>())
    , face3(make_shared<DummyFace>())
  {
    faceTable.add(face1);
    faceTable.add(face2);
    faceTable.add(face3);
  }

protected:
  FaceTable faceTable;
  Forwarder forwarder{faceTable};
  MulticastStrategyTester& strategy;
  Fib& fib{forwarder.getFib()};
  Pit& pit{forwarder.getPit()};

  shared_ptr<DummyFace> face1;
  shared_ptr<DummyFace> face2;
  shared_ptr<DummyFace> face3;
};

BOOST_AUTO_TEST_SUITE(Fw)
BOOST_FIXTURE_TEST_SUITE(TestMulticastStrategy, MulticastStrategyFixture)

BOOST_AUTO_TEST_CASE(Bug5123)
{
  fib::Entry& fibEntry = *fib.insert(Name()).first;
  fib.addOrUpdateNextHop(fibEntry, *face2, 0);

  // Send an Interest from face 1 to face 2
  shared_ptr<Interest> interest = makeInterest("ndn:/H0D6i5fc");
  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest).first;
  pitEntry->insertOrUpdateInRecord(*face1, *interest);

  strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
  BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);

  // Advance more than default suppression
  this->advanceClocks(15_ms);

  // Get same interest from face 2 which does not have anywhere to go
  pitEntry = pit.insert(*interest).first;
  pitEntry->insertOrUpdateInRecord(*face2, *interest);

  strategy.afterReceiveInterest(FaceEndpoint(*face2, 0), *interest, pitEntry);
  // Since the interest is same as the one sent out by face 1 pit should not be rejected
  // as any data coming back should be able to satisfy original interest from face 1
  BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);

  /*
   *      +---------+            +---------+          +---------+
   *      |  nodeA  |------------|  nodeB  |----------|  nodeC  |
   *      +---------+    10ms    +---------+   100ms  +---------+
   */

  const Name PRODUCER_PREFIX = "/ndn/edu/nodeC/ping";

  TopologyTester topo;
  TopologyNode nodeA = topo.addForwarder("A"),
               nodeB = topo.addForwarder("B"),
               nodeC = topo.addForwarder("C");

  for (TopologyNode node : {nodeA, nodeB, nodeC}) {
    topo.setStrategy<MulticastStrategy>(node);
  }

  shared_ptr<TopologyLink> linkAB = topo.addLink("AB", 10_ms,  {nodeA, nodeB}),
                           linkBC = topo.addLink("BC", 100_ms, {nodeB, nodeC});

  shared_ptr<TopologyAppLink> appA = topo.addAppFace("cA", nodeA),
                              appB = topo.addAppFace("cB", nodeB),
                        pingServer = topo.addAppFace("p",  nodeC, PRODUCER_PREFIX);
  topo.addEchoProducer(pingServer->getClientFace());
  topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 10);
  topo.registerPrefix(nodeB, linkAB->getFace(nodeB), PRODUCER_PREFIX, 10);
  topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX, 100);

  Name name(PRODUCER_PREFIX);
  name.appendTimestamp();
  interest = makeInterest(name);
  appA->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);

  this->advanceClocks(10_ms, 20_ms);

  // AppB expresses the same interest
  interest->refreshNonce();
  appB->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
  this->advanceClocks(10_ms, 200_ms);

  // Data should have made to appB
  BOOST_CHECK_EQUAL(linkBC->getFace(nodeB).getCounters().nInData, 1);
  BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 0);

  this->advanceClocks(10_ms, 10_ms);
  // nodeA should have gotten the data successfully
  BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 1);
  BOOST_CHECK_EQUAL(topo.getForwarder(nodeA).getCounters().nUnsolicitedData, 0);
}

BOOST_AUTO_TEST_CASE(Forward2)
{
  fib::Entry& fibEntry = *fib.insert(Name()).first;
  fib.addOrUpdateNextHop(fibEntry, *face1, 0);
  fib.addOrUpdateNextHop(fibEntry, *face2, 0);
  fib.addOrUpdateNextHop(fibEntry, *face3, 0);

  shared_ptr<Interest> interest = makeInterest("ndn:/H0D6i5fc");
  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest).first;
  pitEntry->insertOrUpdateInRecord(*face3, *interest);

  strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest, pitEntry);
  BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
  BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
  std::set<FaceId> sentInterestFaceIds;
  std::transform(strategy.sendInterestHistory.begin(), strategy.sendInterestHistory.end(),
                 std::inserter(sentInterestFaceIds, sentInterestFaceIds.end()),
                 [] (const MulticastStrategyTester::SendInterestArgs& args) {
                   return args.outFaceId;
                 });
  std::set<FaceId> expectedInterestFaceIds{face1->getId(), face2->getId()};
  BOOST_CHECK_EQUAL_COLLECTIONS(sentInterestFaceIds.begin(), sentInterestFaceIds.end(),
                                expectedInterestFaceIds.begin(), expectedInterestFaceIds.end());

  const time::nanoseconds TICK = time::duration_cast<time::nanoseconds>(
                                 MulticastStrategy::RETX_SUPPRESSION_INITIAL * 0.1);

  // downstream retransmits frequently, but the strategy should not send Interests
  // more often than DEFAULT_MIN_RETX_INTERVAL
  scheduler::EventId retxFrom4Evt;
  size_t nSentLast = strategy.sendInterestHistory.size();
  time::steady_clock::TimePoint timeSentLast = time::steady_clock::now();
  std::function<void()> periodicalRetxFrom4; // let periodicalRetxFrom4 lambda capture itself
  periodicalRetxFrom4 = [&] {
    pitEntry->insertOrUpdateInRecord(*face3, *interest);
    strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest, pitEntry);

    size_t nSent = strategy.sendInterestHistory.size();
    if (nSent > nSentLast) {
      // Multicast strategy should multicast the interest to other two faces
      BOOST_CHECK_EQUAL(nSent - nSentLast, 2);
      auto timeSent = time::steady_clock::now();
      BOOST_CHECK_GE(timeSent - timeSentLast, TICK * 8);
      nSentLast = nSent;
      timeSentLast = timeSent;
    }

    retxFrom4Evt = getScheduler().schedule(TICK * 5, periodicalRetxFrom4);
  };
  periodicalRetxFrom4();
  this->advanceClocks(TICK, MulticastStrategy::RETX_SUPPRESSION_MAX * 16);
  retxFrom4Evt.cancel();
}

BOOST_AUTO_TEST_CASE(LoopingInterest)
{
  fib::Entry& fibEntry = *fib.insert(Name()).first;
  fib.addOrUpdateNextHop(fibEntry, *face1, 0);

  shared_ptr<Interest> interest = makeInterest("ndn:/H0D6i5fc");
  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest).first;
  pitEntry->insertOrUpdateInRecord(*face1, *interest);

  strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
  BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
  BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 0);
}

BOOST_AUTO_TEST_CASE(ForwardAsync)
{
  fib::Entry& fibEntry = *fib.insert(Name()).first;
  fib.addOrUpdateNextHop(fibEntry, *face1, 0);
  fib.addOrUpdateNextHop(fibEntry, *face2, 0);

  shared_ptr<Interest> interest = makeInterest("ndn:/H0D6i5fc");
  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest).first;
  pitEntry->insertOrUpdateInRecord(*face1, *interest);

  strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
  BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
  BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 1);

  fib.addOrUpdateNextHop(fibEntry, *face3, 0);
  BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
  BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
}

BOOST_AUTO_TEST_SUITE(LocalhopScope)

class ForwardAsyncFixture : public MulticastStrategyFixture
{
protected:
  shared_ptr<Face> inFace1;
  shared_ptr<Face> inFace2;
  shared_ptr<Face> fibFace1;
  shared_ptr<Face> fibFace2;
  shared_ptr<Face> newFibFace;

  size_t expectedInterests = 0;
};

class BasicNonLocal : public ForwardAsyncFixture
{
protected:
  BasicNonLocal()
  {
    inFace1 = face1;
    // inFace2 = nullptr;
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = face3;
    expectedInterests = 0; // anything received on non-local face can only be sent to local face
  }
};

class NewFibLocal : public ForwardAsyncFixture
{
protected:
  NewFibLocal()
  {
    inFace1 = face1;
    // inFace2 = nullptr;
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
    expectedInterests = 1;

    faceTable.add(newFibFace);
  }
};

class InFaceLocal : public ForwardAsyncFixture
{
protected:
  InFaceLocal()
  {
    inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
    // inFace2 = nullptr;
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = face3;
    expectedInterests = 1;

    faceTable.add(inFace1);
  }
};

class InFaceLocalSameNewFace : public ForwardAsyncFixture
{
protected:
  InFaceLocalSameNewFace()
  {
    inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
    // inFace2 = nullptr;
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = inFace1;
    expectedInterests = 0;

    faceTable.add(inFace1);
  }
};

class InFaceLocalAdHocSameNewFace : public ForwardAsyncFixture
{
protected:
  InFaceLocalAdHocSameNewFace()
  {
    inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL,
                                     ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
                                     ndn::nfd::LINK_TYPE_AD_HOC);
    // inFace2 = nullptr;
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = inFace1;
    expectedInterests = 1;

    faceTable.add(inFace1);
  }
};

class InFaceLocalAndNonLocal1 : public ForwardAsyncFixture
{
protected:
  InFaceLocalAndNonLocal1()
  {
    inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
    inFace2 = face1;
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = face3;
    expectedInterests = 1;

    faceTable.add(inFace1);
  }
};

class InFaceLocalAndNonLocal2 : public ForwardAsyncFixture
{
protected:
  InFaceLocalAndNonLocal2()
  {
    inFace1 = face1;
    inFace2 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
    fibFace1 = face1;
    fibFace2 = face2;
    newFibFace = face3;
    expectedInterests = 1;

    faceTable.add(inFace2);
  }
};

class InFaceSelection1 : public ForwardAsyncFixture
{
protected:
  InFaceSelection1()
  {
    inFace1 = face1;
    // inFace2 = nullptr;
    fibFace1 = face3;
    fibFace2 = face2;
    newFibFace = face1;

    expectedInterests = 0;
  }
};

class InFaceSelection2 : public ForwardAsyncFixture
{
protected:
  InFaceSelection2()
  {
    inFace1 = face2;
    inFace2 = face1;
    fibFace1 = face2;
    fibFace2 = face3;
    newFibFace = face1;

    // this test will trigger the check for additional branch, but it
    // still is not going to pass the localhop check
    expectedInterests = 0;
  }
};

using Tests = boost::mpl::vector<
  BasicNonLocal,
  NewFibLocal,
  InFaceLocal,
  InFaceLocalSameNewFace,
  InFaceLocalAdHocSameNewFace,
  InFaceLocalAndNonLocal1,
  InFaceLocalAndNonLocal2,
  InFaceSelection1,
  InFaceSelection2
>;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(ForwardAsync, T, Tests, T)
{
  fib::Entry& fibEntry = *this->fib.insert(Name("/localhop")).first;
  this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace1, 0);
  this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace2, 0);

  shared_ptr<Interest> interest = makeInterest("ndn:/localhop/H0D6i5fc");
  shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
  pitEntry->insertOrUpdateInRecord(*this->inFace1, *interest);
  this->strategy.afterReceiveInterest(FaceEndpoint(*this->inFace1, 0), *interest, pitEntry);

  if (this->inFace2 != nullptr) {
    shared_ptr<Interest> interest2 = makeInterest("ndn:/localhop/H0D6i5fc");
    pitEntry->insertOrUpdateInRecord(*this->inFace2, *interest2);
    this->strategy.afterReceiveInterest(FaceEndpoint(*this->inFace2, 0), *interest2, pitEntry);
  }

  this->strategy.sendInterestHistory.clear();
  this->fib.addOrUpdateNextHop(fibEntry, *this->newFibFace, 0);
  BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), this->expectedInterests);
}

BOOST_AUTO_TEST_SUITE_END() // LocalhopScope
BOOST_AUTO_TEST_SUITE_END() // TestMulticastStrategy
BOOST_AUTO_TEST_SUITE_END() // Fw

} // namespace tests
} // namespace fw
} // namespace nfd
