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..262db5a404c9bef4209dbaabc59dd603de400de3 |
--- /dev/null |
+++ b/net/dns/dns_config_service_posix_unittest.cc |
@@ -0,0 +1,128 @@ |
+// 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 TestObserver : public DnsConfigService::Observer, |
+ public base::RefCountedThreadSafe<TestObserver> { |
+ explicit TestObserver(base::WaitableEvent* completion) |
+ : completion(completion) {} |
+ virtual ~TestObserver() {} |
+ |
+ void StartWatch() { |
+ service.reset(DnsConfigService::CreateSystemService()); |
+ service->AddObserver(this); |
+ } |
+ |
+ 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(); |
+ } |
+ |
+ DnsConfig config; |
+ scoped_ptr<DnsConfigService> service; |
+ base::WaitableEvent* completion; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestObserver); |
+}; |
+ |
+ |
+// run DnsConfigService::Watch on the separate |service_thread_| |
+class DnsConfigServiceTest : public testing::Test { |
+ public: |
+ DnsConfigServiceTest() |
+ : completion_(false, false), |
+ delegate_(new TestObserver(&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(&TestObserver::StartWatch, delegate_.get())); |
+ } |
+ |
+ void CheckConfig(const struct __res_state &res) { |
+ const DnsConfig& config = delegate_->config; |
+ 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<TestObserver> 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); |
cbentzel
2011/08/05 19:11:39
This seems flaky and won't get code coverage of re
szym
2011/08/15 14:27:42
Done.
|
+ |
+ ASSERT_TRUE(res.options & RES_INIT); |
+ ASSERT_TRUE(WaitForConfig()); |
+ CheckConfig(res); |
+} |
+ |
+// TODO(szym) do the same but touch /etc/resolv.conf |
+} |
+ |
+} // namespace net |
+ |