OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <resolv.h> // POSIX only |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/message_loop.h" |
| 9 #include "base/message_loop_proxy.h" |
| 10 #include "base/synchronization/waitable_event.h" |
| 11 #include "base/threading/thread.h" |
| 12 #include "net/base/ip_endpoint.h" |
| 13 #include "net/dns/dns_config_service.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 namespace net { |
| 17 |
| 18 namespace { |
| 19 |
| 20 // strategy similar to testing FilePathWatcher |
| 21 |
| 22 // A mock DnsConfigService::Delegate for testing. |
| 23 // This is RefCountedThreadSafe to make sure it's cleaned up. |
| 24 struct TestDelegate : public DnsConfigService::Delegate, |
| 25 public base::RefCountedThreadSafe<TestDelegate> { |
| 26 explicit TestDelegate(base::WaitableEvent* completion) |
| 27 : completion(completion) {} |
| 28 virtual ~TestDelegate() {} |
| 29 |
| 30 void StartWatch() { |
| 31 service.reset(DnsConfigService::CreateSystemService()); |
| 32 if (!service->Watch(this)) { |
| 33 FAIL() << "Watch"; |
| 34 } |
| 35 } |
| 36 |
| 37 virtual void OnConfigChanged(const DnsConfig& new_config) OVERRIDE { |
| 38 config = new_config; |
| 39 completion->Signal(); |
| 40 // we must destroy the service on the same thread that called Watch |
| 41 delete service.release(); |
| 42 } |
| 43 |
| 44 virtual void OnConfigError() OVERRIDE { |
| 45 // we must destroy the service on the same thread that called Watch |
| 46 delete service.release(); |
| 47 FAIL() << "Error while reading config?"; |
| 48 } |
| 49 |
| 50 DnsConfig config; |
| 51 scoped_ptr<DnsConfigService> service; |
| 52 base::WaitableEvent* completion; |
| 53 |
| 54 DISALLOW_COPY_AND_ASSIGN(TestDelegate); |
| 55 }; |
| 56 |
| 57 |
| 58 // run DnsConfigService::Watch on the separate |service_thread_| |
| 59 class DnsConfigServiceTest : public testing::Test { |
| 60 public: |
| 61 DnsConfigServiceTest() |
| 62 : completion_(false, false), |
| 63 delegate_(new TestDelegate(&completion_)), |
| 64 service_thread_("DnsConfigServiceTest") {} |
| 65 |
| 66 virtual ~DnsConfigServiceTest() {} |
| 67 |
| 68 protected: |
| 69 virtual void SetUp() OVERRIDE { |
| 70 // Create a separate thread on which we call Watch and the Delegate methods |
| 71 // TestDelegate will make it quit in OnConfigChanged |
| 72 base::Thread::Options options(MessageLoop::TYPE_IO, 0); |
| 73 ASSERT_TRUE(service_thread_.StartWithOptions(options)); |
| 74 } |
| 75 |
| 76 virtual void TearDown() OVERRIDE { |
| 77 service_thread_.Stop(); |
| 78 } |
| 79 |
| 80 void StartWatch() { |
| 81 completion_.Reset(); // is this needed? |
| 82 service_thread_.message_loop()->PostTask( |
| 83 FROM_HERE, |
| 84 base::Bind(&TestDelegate::StartWatch, delegate_.get())); |
| 85 } |
| 86 |
| 87 void CheckConfig(const struct __res_state &res) { |
| 88 const DnsConfig& config = delegate_->config; |
| 89 EXPECT_EQ(config.domain, res.defdname); |
| 90 EXPECT_EQ(config.ndots, static_cast<int>(res.ndots)); |
| 91 EXPECT_EQ(config.edns0, res.options & RES_USE_EDNS0); |
| 92 EXPECT_EQ(config.rotate, res.options & RES_ROTATE); |
| 93 EXPECT_EQ(config.timeout, res.retrans); |
| 94 EXPECT_EQ(config.attempts, res.retry); |
| 95 // compare nameservers |
| 96 ASSERT_EQ(config.nameservers.size(), static_cast<size_t>(res.nscount)); |
| 97 for (int i = 0; i < res.nscount; ++i) { |
| 98 IPEndPoint ipe; |
| 99 ASSERT_TRUE(ipe.FromSockAddr( |
| 100 reinterpret_cast<const struct sockaddr*>(&res.nsaddr_list[i]), |
| 101 sizeof res.nsaddr_list[i])); |
| 102 EXPECT_EQ(config.nameservers[i], ipe); |
| 103 } |
| 104 // compare search |
| 105 ASSERT_TRUE(res.dnsrch[config.search.size()] == NULL); |
| 106 for (unsigned i = 0; i < config.search.size(); ++i) { |
| 107 EXPECT_EQ(config.search[i], res.dnsrch[i]); |
| 108 } |
| 109 } |
| 110 |
| 111 bool WaitForConfig() WARN_UNUSED_RESULT { |
| 112 return completion_.Wait(); // TODO(szym): add timeout? |
| 113 } |
| 114 |
| 115 private: |
| 116 base::WaitableEvent completion_; |
| 117 scoped_refptr<TestDelegate> delegate_; |
| 118 base::Thread service_thread_; |
| 119 }; |
| 120 |
| 121 TEST_F(DnsConfigServiceTest, VerifyWithResInit) { |
| 122 StartWatch(); |
| 123 // NOTE: res_init() initializes __res_state.retry (DnsConfig::attempts) to 4 |
| 124 // while res_ninit() initializes it to 2, so we can't mix them in this test. |
| 125 struct __res_state res; |
| 126 ASSERT_EQ(res_ninit(&res), 0); |
| 127 |
| 128 ASSERT_TRUE(res.options & RES_INIT); |
| 129 ASSERT_TRUE(WaitForConfig()); |
| 130 CheckConfig(res); |
| 131 } |
| 132 |
| 133 // TODO(szym) do the same but touch /etc/resolv.conf |
| 134 } |
| 135 |
| 136 } // namespace net |
| 137 |
OLD | NEW |