blob: b1edd9e21b2911f207cc27c294ba0ec0d641dc5f [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_TEST_AGENT_TEST_H_
#define SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_TEST_AGENT_TEST_H_
#include <lib/zx/time.h>
#include <queue>
#include <unordered_map>
#include <gtest/gtest.h>
#include "src/connectivity/network/mdns/service/mdns_agent.h"
namespace mdns {
namespace test {
class AgentTest : public ::testing::Test, public MdnsAgent::Host {
public:
AgentTest() {}
protected:
static constexpr zx::time kInitialTime = zx::time(1000);
static const std::string kHostFullName;
// Sets the agent under test. This must be called before the test gets underway, and the agent
// must survive until the end of the test.
void SetAgent(const MdnsAgent& agent) { agent_ = &agent; }
// An instance of |MdnsAddresses| for lookup.
const MdnsAddresses& addresses() const { return addresses_; }
// Advances the current time (as returned by |now()|) to |time|. |time| must be greater than
// or equal to the time currently returned by |now()|.
void AdvanceTo(zx::time time);
// Expects that the agent hasn't posted any new tasks.
void ExpectNoPostTaskForTime() { EXPECT_TRUE(post_task_for_time_calls_.empty()); }
// Expects that the agent has posted a task for a time in the given range. Returns the task
// closure and the actual scheduled time.
std::pair<fit::closure, zx::time> ExpectPostTaskForTime(zx::duration earliest,
zx::duration latest);
// Calls |ExpectNoPostTaskForTime|, advances the time to the scheduled time of the task, and
// invokes the task.
void ExpectPostTaskForTimeAndInvoke(zx::duration earliest, zx::duration latest);
// Expects that there is no outbond message.
void ExpectNoOutboundMessage() { EXPECT_TRUE(outbound_messages_by_reply_address_.empty()); }
// Expects that there is an outbound message targeted at |reply_address| and returns it.
std::unique_ptr<DnsMessage> ExpectOutboundMessage(ReplyAddress reply_address);
// Expects that the agent has not called |Renew|.
void ExpectNoRenewCalls() { EXPECT_TRUE(renew_calls_.empty()); }
// Expects that the agent has not called |RemoveAgent|.
void ExpectNoRemoveAgentCall() { EXPECT_FALSE(remove_agent_called_); }
// Expects that the agent has called |RemoveAgent| to remove itself.
void ExpectRemoveAgentCall() { EXPECT_TRUE(remove_agent_called_); }
// Expects that nothing else has happened. Subclasses can override this to ensure that nothing
// specific to a particular agent type has happened. Overrides should call this implementation.
virtual void ExpectNoOther();
// Expects that |message| contains a question with the given parameters.
void ExpectQuestion(DnsMessage* message, const std::string& name, DnsType type,
DnsClass dns_class = DnsClass::kIn, bool unicast_response = false);
// Expects that |message| contains a resource in |section| with the given parameters and returns
// it.
std::shared_ptr<DnsResource> ExpectResource(DnsMessage* message, MdnsResourceSection section,
const std::string& name, DnsType type,
DnsClass dns_class = DnsClass::kIn,
bool cache_flush = true);
// Expects that |message| contains an address placeholder resource in |section|.
void ExpectAddressPlaceholder(DnsMessage* message, MdnsResourceSection section);
// Expects that |message| contains no questions or resources.
void ExpectNoOtherQuestionOrResource(DnsMessage* message);
private:
struct PostTaskForTimeCall {
fit::closure task_;
zx::time target_time_;
};
struct RenewCall {
DnsResource resource_;
};
struct ReplyAddressHash {
std::size_t operator()(const ReplyAddress& reply_address) const noexcept {
return std::hash<inet::SocketAddress>{}(reply_address.socket_address()) ^
(std::hash<inet::IpAddress>{}(reply_address.interface_address()) << 1);
}
};
// |MdnsAgent::Host| implementation.
protected:
zx::time now() override { return now_; }
private:
void PostTaskForTime(MdnsAgent* agent, fit::closure task, zx::time target_time) override;
void SendQuestion(std::shared_ptr<DnsQuestion> question) override;
void SendResource(std::shared_ptr<DnsResource> resource, MdnsResourceSection section,
const ReplyAddress& reply_address) override;
void SendAddresses(MdnsResourceSection section, const ReplyAddress& reply_address) override;
void Renew(const DnsResource& resource) override;
void RemoveAgent(const MdnsAgent* agent,
const std::string& published_instance_full_name) override;
const MdnsAgent* agent_;
std::shared_ptr<DnsResource> address_placeholder_ =
std::make_shared<DnsResource>(kHostFullName, DnsType::kA);
MdnsAddresses addresses_;
zx::time now_ = kInitialTime;
std::queue<PostTaskForTimeCall> post_task_for_time_calls_;
std::unordered_map<ReplyAddress, std::unique_ptr<DnsMessage>, ReplyAddressHash>
outbound_messages_by_reply_address_;
std::queue<RenewCall> renew_calls_;
bool remove_agent_called_ = false;
};
} // namespace test
} // namespace mdns
#endif // SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_TEST_AGENT_TEST_H_