util: Add BroadcastLink to DummyClientFace

Change-Id: I2bfe3156016a098b91ff375f2bb83b5e4351317c
Refs: #3913
diff --git a/tests/unit-tests/util/dummy-client-face.t.cpp b/tests/unit-tests/util/dummy-client-face.t.cpp
index 809034d..8469d59 100644
--- a/tests/unit-tests/util/dummy-client-face.t.cpp
+++ b/tests/unit-tests/util/dummy-client-face.t.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -23,15 +23,16 @@
 
 #include "boost-test.hpp"
 #include "../identity-management-time-fixture.hpp"
+#include "make-interest-data.hpp"
 
 namespace ndn {
 namespace util {
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(Util)
-BOOST_AUTO_TEST_SUITE(TestDummyClientFace)
+BOOST_FIXTURE_TEST_SUITE(TestDummyClientFace, ndn::tests::IdentityManagementTimeFixture)
 
-BOOST_FIXTURE_TEST_CASE(ProcessEventsOverride, ndn::tests::IdentityManagementTimeFixture)
+BOOST_AUTO_TEST_CASE(ProcessEventsOverride)
 {
   bool isOverrideInvoked = false;
   auto override = [&] (time::milliseconds timeout) {
@@ -44,6 +45,83 @@
   BOOST_CHECK(isOverrideInvoked);
 }
 
+BOOST_AUTO_TEST_CASE(BroadcastLink)
+{
+  DummyClientFace face1(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face2(io, m_keyChain, DummyClientFace::Options{true, true});
+  face1.linkTo(face2);
+
+  int nFace1Interest = 0;
+  int nFace2Interest = 0;
+  face1.setInterestFilter("/face1",
+                          [&] (const InterestFilter&, const Interest& interest) {
+                            BOOST_CHECK_EQUAL(interest.getName().toUri(), "/face1/data");
+                            nFace1Interest++;
+                            face1.put(ndn::tests::makeNack(interest, lp::NackReason::NO_ROUTE));
+                          }, nullptr, nullptr);
+  face2.setInterestFilter("/face2",
+                          [&] (const InterestFilter&, const Interest& interest) {
+                            BOOST_CHECK_EQUAL(interest.getName().toUri(), "/face2/data");
+                            nFace2Interest++;
+                            face2.put(*ndn::tests::makeData("/face2/data"));
+                            return;
+                          }, nullptr, nullptr);
+
+  advanceClocks(time::milliseconds(25), 4);
+
+  int nFace1Data = 0;
+  int nFace2Nack = 0;
+  face1.expressInterest(Interest("/face2/data"),
+                        [&] (const Interest& i, const Data& d) {
+                          BOOST_CHECK_EQUAL(d.getName().toUri(), "/face2/data");
+                          nFace1Data++;
+                        }, nullptr, nullptr);
+  face2.expressInterest(Interest("/face1/data"),
+                        [&] (const Interest& i, const Data& d) {
+                          BOOST_CHECK(false);
+                        },
+                        [&] (const Interest& i, const lp::Nack& n) {
+                          BOOST_CHECK_EQUAL(n.getInterest().getName().toUri(), "/face1/data");
+                          nFace2Nack++;
+                        }, nullptr);
+
+  advanceClocks(time::milliseconds(10), 100);
+
+  BOOST_CHECK_EQUAL(nFace1Data, 1);
+  BOOST_CHECK_EQUAL(nFace2Nack, 1);
+  BOOST_CHECK_EQUAL(nFace1Interest, 1);
+  BOOST_CHECK_EQUAL(nFace2Interest, 1);
+}
+
+BOOST_AUTO_TEST_CASE(BroadcastLinkDestroy)
+{
+  DummyClientFace face1(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face2(io, m_keyChain, DummyClientFace::Options{true, true});
+
+  face1.linkTo(face2);
+  face2.unlink();
+  BOOST_CHECK(face1.m_bcastLink == nullptr);
+
+  DummyClientFace face3(io, m_keyChain, DummyClientFace::Options{true, true});
+  face1.linkTo(face2);
+  face3.linkTo(face1);
+  face2.unlink();
+  BOOST_CHECK(face1.m_bcastLink != nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(AlreadyLinkException)
+{
+  DummyClientFace face1(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face2(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face3(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face4(io, m_keyChain, DummyClientFace::Options{true, true});
+
+  face1.linkTo(face2);
+  face3.linkTo(face4);
+
+  BOOST_CHECK_THROW(face2.linkTo(face3), DummyClientFace::AlreadyLinkedError);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestDummyClientFace
 BOOST_AUTO_TEST_SUITE_END() // Util