1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_probe.h"
5*3f982cf4SFabien Sanglard
6*3f982cf4SFabien Sanglard #include <memory>
7*3f982cf4SFabien Sanglard #include <utility>
8*3f982cf4SFabien Sanglard
9*3f982cf4SFabien Sanglard #include "discovery/common/config.h"
10*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_probe_manager.h"
11*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_querier.h"
12*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_random.h"
13*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_receiver.h"
14*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_sender.h"
15*3f982cf4SFabien Sanglard #include "gmock/gmock.h"
16*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
17*3f982cf4SFabien Sanglard #include "platform/test/fake_clock.h"
18*3f982cf4SFabien Sanglard #include "platform/test/fake_task_runner.h"
19*3f982cf4SFabien Sanglard #include "platform/test/fake_udp_socket.h"
20*3f982cf4SFabien Sanglard
21*3f982cf4SFabien Sanglard using testing::_;
22*3f982cf4SFabien Sanglard using testing::Invoke;
23*3f982cf4SFabien Sanglard using testing::Return;
24*3f982cf4SFabien Sanglard using testing::StrictMock;
25*3f982cf4SFabien Sanglard
26*3f982cf4SFabien Sanglard namespace openscreen {
27*3f982cf4SFabien Sanglard namespace discovery {
28*3f982cf4SFabien Sanglard
29*3f982cf4SFabien Sanglard class MockMdnsSender : public MdnsSender {
30*3f982cf4SFabien Sanglard public:
MockMdnsSender(UdpSocket * socket)31*3f982cf4SFabien Sanglard explicit MockMdnsSender(UdpSocket* socket) : MdnsSender(socket) {}
32*3f982cf4SFabien Sanglard MOCK_METHOD1(SendMulticast, Error(const MdnsMessage& message));
33*3f982cf4SFabien Sanglard MOCK_METHOD2(SendMessage,
34*3f982cf4SFabien Sanglard Error(const MdnsMessage& message, const IPEndpoint& endpoint));
35*3f982cf4SFabien Sanglard };
36*3f982cf4SFabien Sanglard
37*3f982cf4SFabien Sanglard class MockObserver : public MdnsProbeImpl::Observer {
38*3f982cf4SFabien Sanglard public:
39*3f982cf4SFabien Sanglard MOCK_METHOD1(OnProbeSuccess, void(MdnsProbe*));
40*3f982cf4SFabien Sanglard MOCK_METHOD1(OnProbeFailure, void(MdnsProbe*));
41*3f982cf4SFabien Sanglard };
42*3f982cf4SFabien Sanglard
43*3f982cf4SFabien Sanglard class MdnsProbeTests : public testing::Test {
44*3f982cf4SFabien Sanglard public:
MdnsProbeTests()45*3f982cf4SFabien Sanglard MdnsProbeTests()
46*3f982cf4SFabien Sanglard : clock_(Clock::now()),
47*3f982cf4SFabien Sanglard task_runner_(&clock_),
48*3f982cf4SFabien Sanglard socket_(&task_runner_),
49*3f982cf4SFabien Sanglard sender_(&socket_),
50*3f982cf4SFabien Sanglard receiver_(config_) {
51*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 0);
52*3f982cf4SFabien Sanglard probe_ = CreateProbe();
53*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 1);
54*3f982cf4SFabien Sanglard }
55*3f982cf4SFabien Sanglard
56*3f982cf4SFabien Sanglard protected:
CreateProbe()57*3f982cf4SFabien Sanglard std::unique_ptr<MdnsProbeImpl> CreateProbe() {
58*3f982cf4SFabien Sanglard return std::make_unique<MdnsProbeImpl>(&sender_, &receiver_, &random_,
59*3f982cf4SFabien Sanglard &task_runner_, FakeClock::now,
60*3f982cf4SFabien Sanglard &observer_, name_, address_v4_);
61*3f982cf4SFabien Sanglard }
62*3f982cf4SFabien Sanglard
CreateMessage(const DomainName & domain)63*3f982cf4SFabien Sanglard MdnsMessage CreateMessage(const DomainName& domain) {
64*3f982cf4SFabien Sanglard MdnsMessage message(0, MessageType::Response);
65*3f982cf4SFabien Sanglard SrvRecordRdata rdata(0, 0, 80, domain);
66*3f982cf4SFabien Sanglard MdnsRecord record(std::move(domain), DnsType::kSRV, DnsClass::kIN,
67*3f982cf4SFabien Sanglard RecordType::kUnique, std::chrono::seconds(1),
68*3f982cf4SFabien Sanglard std::move(rdata));
69*3f982cf4SFabien Sanglard message.AddAnswer(record);
70*3f982cf4SFabien Sanglard return message;
71*3f982cf4SFabien Sanglard }
72*3f982cf4SFabien Sanglard
OnMessageReceived(const MdnsMessage & message)73*3f982cf4SFabien Sanglard void OnMessageReceived(const MdnsMessage& message) {
74*3f982cf4SFabien Sanglard probe_->OnMessageReceived(message);
75*3f982cf4SFabien Sanglard }
76*3f982cf4SFabien Sanglard
77*3f982cf4SFabien Sanglard Config config_;
78*3f982cf4SFabien Sanglard FakeClock clock_;
79*3f982cf4SFabien Sanglard FakeTaskRunner task_runner_;
80*3f982cf4SFabien Sanglard FakeUdpSocket socket_;
81*3f982cf4SFabien Sanglard StrictMock<MockMdnsSender> sender_;
82*3f982cf4SFabien Sanglard MdnsReceiver receiver_;
83*3f982cf4SFabien Sanglard MdnsRandom random_;
84*3f982cf4SFabien Sanglard StrictMock<MockObserver> observer_;
85*3f982cf4SFabien Sanglard
86*3f982cf4SFabien Sanglard std::unique_ptr<MdnsProbeImpl> probe_;
87*3f982cf4SFabien Sanglard
88*3f982cf4SFabien Sanglard const DomainName name_{"test", "_googlecast", "_tcp", "local"};
89*3f982cf4SFabien Sanglard const DomainName name2_{"test2", "_googlecast", "_tcp", "local"};
90*3f982cf4SFabien Sanglard
91*3f982cf4SFabien Sanglard const IPAddress address_v4_{192, 168, 0, 0};
92*3f982cf4SFabien Sanglard const IPEndpoint endpoint_v4_{address_v4_, 80};
93*3f982cf4SFabien Sanglard };
94*3f982cf4SFabien Sanglard
TEST_F(MdnsProbeTests,TestNoCancelationFlow)95*3f982cf4SFabien Sanglard TEST_F(MdnsProbeTests, TestNoCancelationFlow) {
96*3f982cf4SFabien Sanglard EXPECT_CALL(sender_, SendMulticast(_));
97*3f982cf4SFabien Sanglard clock_.Advance(kDelayBetweenProbeQueries);
98*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 1);
99*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&sender_);
100*3f982cf4SFabien Sanglard
101*3f982cf4SFabien Sanglard EXPECT_CALL(sender_, SendMulticast(_));
102*3f982cf4SFabien Sanglard clock_.Advance(kDelayBetweenProbeQueries);
103*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 1);
104*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&sender_);
105*3f982cf4SFabien Sanglard
106*3f982cf4SFabien Sanglard EXPECT_CALL(sender_, SendMulticast(_));
107*3f982cf4SFabien Sanglard clock_.Advance(kDelayBetweenProbeQueries);
108*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 1);
109*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&sender_);
110*3f982cf4SFabien Sanglard
111*3f982cf4SFabien Sanglard EXPECT_CALL(observer_, OnProbeSuccess(probe_.get())).Times(1);
112*3f982cf4SFabien Sanglard clock_.Advance(kDelayBetweenProbeQueries);
113*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 0);
114*3f982cf4SFabien Sanglard }
115*3f982cf4SFabien Sanglard
TEST_F(MdnsProbeTests,CancelationWhenMatchingMessageReceived)116*3f982cf4SFabien Sanglard TEST_F(MdnsProbeTests, CancelationWhenMatchingMessageReceived) {
117*3f982cf4SFabien Sanglard EXPECT_CALL(observer_, OnProbeFailure(probe_.get())).Times(1);
118*3f982cf4SFabien Sanglard OnMessageReceived(CreateMessage(name_));
119*3f982cf4SFabien Sanglard }
120*3f982cf4SFabien Sanglard
TEST_F(MdnsProbeTests,TestNoCancelationOnUnrelatedMessages)121*3f982cf4SFabien Sanglard TEST_F(MdnsProbeTests, TestNoCancelationOnUnrelatedMessages) {
122*3f982cf4SFabien Sanglard OnMessageReceived(CreateMessage(name2_));
123*3f982cf4SFabien Sanglard
124*3f982cf4SFabien Sanglard EXPECT_CALL(sender_, SendMulticast(_));
125*3f982cf4SFabien Sanglard clock_.Advance(kDelayBetweenProbeQueries);
126*3f982cf4SFabien Sanglard EXPECT_EQ(task_runner_.delayed_task_count(), 1);
127*3f982cf4SFabien Sanglard testing::Mock::VerifyAndClearExpectations(&sender_);
128*3f982cf4SFabien Sanglard }
129*3f982cf4SFabien Sanglard
130*3f982cf4SFabien Sanglard } // namespace discovery
131*3f982cf4SFabien Sanglard } // namespace openscreen
132