| Index: net/dns/dns_config_service_posix_unittest.cc
|
| diff --git a/net/dns/dns_config_service_posix_unittest.cc b/net/dns/dns_config_service_posix_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..756a1ac5b50b635ca7542f015677e86e3c5d7d8e
|
| --- /dev/null
|
| +++ b/net/dns/dns_config_service_posix_unittest.cc
|
| @@ -0,0 +1,137 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <resolv.h> // POSIX only
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/message_loop_proxy.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| +#include "base/threading/thread.h"
|
| +#include "net/base/ip_endpoint.h"
|
| +#include "net/dns/dns_config_service.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +// strategy similar to testing FilePathWatcher
|
| +
|
| +// A mock DnsConfigService::Delegate for testing.
|
| +// This is RefCountedThreadSafe to make sure it's cleaned up.
|
| +struct TestDelegate : public DnsConfigService::Delegate,
|
| + public base::RefCountedThreadSafe<TestDelegate> {
|
| + explicit TestDelegate(base::WaitableEvent* completion)
|
| + : completion(completion) {}
|
| + virtual ~TestDelegate() {}
|
| +
|
| + void StartWatch() {
|
| + service.reset(DnsConfigService::CreateSystemService());
|
| + if (!service->Watch(this)) {
|
| + FAIL() << "Watch";
|
| + }
|
| + }
|
| +
|
| + virtual void OnConfigChanged(const DnsConfig& new_config) OVERRIDE {
|
| + config = new_config;
|
| + completion->Signal();
|
| + // we must destroy the service on the same thread that called Watch
|
| + delete service.release();
|
| + }
|
| +
|
| + virtual void OnConfigError() OVERRIDE {
|
| + // we must destroy the service on the same thread that called Watch
|
| + delete service.release();
|
| + FAIL() << "Error while reading config?";
|
| + }
|
| +
|
| + DnsConfig config;
|
| + scoped_ptr<DnsConfigService> service;
|
| + base::WaitableEvent* completion;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestDelegate);
|
| +};
|
| +
|
| +
|
| +// run DnsConfigService::Watch on the separate |service_thread_|
|
| +class DnsConfigServiceTest : public testing::Test {
|
| + public:
|
| + DnsConfigServiceTest()
|
| + : completion_(false, false),
|
| + delegate_(new TestDelegate(&completion_)),
|
| + service_thread_("DnsConfigServiceTest") {}
|
| +
|
| + virtual ~DnsConfigServiceTest() {}
|
| +
|
| + protected:
|
| + virtual void SetUp() OVERRIDE {
|
| + // Create a separate thread on which we call Watch and the Delegate methods
|
| + // TestDelegate will make it quit in OnConfigChanged
|
| + base::Thread::Options options(MessageLoop::TYPE_IO, 0);
|
| + ASSERT_TRUE(service_thread_.StartWithOptions(options));
|
| + }
|
| +
|
| + virtual void TearDown() OVERRIDE {
|
| + service_thread_.Stop();
|
| + }
|
| +
|
| + void StartWatch() {
|
| + completion_.Reset(); // is this needed?
|
| + service_thread_.message_loop()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&TestDelegate::StartWatch, delegate_.get()));
|
| + }
|
| +
|
| + void CheckConfig(const struct __res_state &res) {
|
| + const DnsConfig& config = delegate_->config;
|
| + EXPECT_EQ(config.domain, res.defdname);
|
| + EXPECT_EQ(config.ndots, static_cast<int>(res.ndots));
|
| + EXPECT_EQ(config.edns0, res.options & RES_USE_EDNS0);
|
| + EXPECT_EQ(config.rotate, res.options & RES_ROTATE);
|
| + EXPECT_EQ(config.timeout, res.retrans);
|
| + EXPECT_EQ(config.attempts, res.retry);
|
| + // compare nameservers
|
| + ASSERT_EQ(config.nameservers.size(), static_cast<size_t>(res.nscount));
|
| + for (int i = 0; i < res.nscount; ++i) {
|
| + IPEndPoint ipe;
|
| + ASSERT_TRUE(ipe.FromSockAddr(
|
| + reinterpret_cast<const struct sockaddr*>(&res.nsaddr_list[i]),
|
| + sizeof res.nsaddr_list[i]));
|
| + EXPECT_EQ(config.nameservers[i], ipe);
|
| + }
|
| + // compare search
|
| + ASSERT_TRUE(res.dnsrch[config.search.size()] == NULL);
|
| + for (unsigned i = 0; i < config.search.size(); ++i) {
|
| + EXPECT_EQ(config.search[i], res.dnsrch[i]);
|
| + }
|
| + }
|
| +
|
| + bool WaitForConfig() WARN_UNUSED_RESULT {
|
| + return completion_.Wait(); // TODO(szym): add timeout?
|
| + }
|
| +
|
| + private:
|
| + base::WaitableEvent completion_;
|
| + scoped_refptr<TestDelegate> delegate_;
|
| + base::Thread service_thread_;
|
| +};
|
| +
|
| +TEST_F(DnsConfigServiceTest, VerifyWithResInit) {
|
| + StartWatch();
|
| + // NOTE: res_init() initializes __res_state.retry (DnsConfig::attempts) to 4
|
| + // while res_ninit() initializes it to 2, so we can't mix them in this test.
|
| + struct __res_state res;
|
| + ASSERT_EQ(res_ninit(&res), 0);
|
| +
|
| + ASSERT_TRUE(res.options & RES_INIT);
|
| + ASSERT_TRUE(WaitForConfig());
|
| + CheckConfig(res);
|
| +}
|
| +
|
| +// TODO(szym) do the same but touch /etc/resolv.conf
|
| +}
|
| +
|
| +} // namespace net
|
| +
|
|
|