Home | History | Annotate | Download | only in dns
      1 // Copyright (c) 2012 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 "net/dns/dns_config_service.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/bind.h"
      9 #include "base/cancelable_callback.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/strings/string_split.h"
     13 #include "base/test/test_timeouts.h"
     14 #include "net/base/net_util.h"
     15 #include "net/dns/dns_protocol.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace net {
     19 
     20 namespace {
     21 
     22 const NameServerClassifier::NameServersType kNone =
     23     NameServerClassifier::NAME_SERVERS_TYPE_NONE;
     24 const NameServerClassifier::NameServersType kGoogle =
     25     NameServerClassifier::NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS;
     26 const NameServerClassifier::NameServersType kPrivate =
     27     NameServerClassifier::NAME_SERVERS_TYPE_PRIVATE;
     28 const NameServerClassifier::NameServersType kPublic =
     29     NameServerClassifier::NAME_SERVERS_TYPE_PUBLIC;
     30 const NameServerClassifier::NameServersType kMixed =
     31     NameServerClassifier::NAME_SERVERS_TYPE_MIXED;
     32 
     33 class NameServerClassifierTest : public testing::Test {
     34  protected:
     35   NameServerClassifier::NameServersType Classify(
     36       const std::string& servers_string) {
     37     std::vector<std::string> server_strings;
     38     base::SplitString(servers_string, ' ', &server_strings);
     39 
     40     std::vector<IPEndPoint> servers;
     41     for (std::vector<std::string>::const_iterator it = server_strings.begin();
     42          it != server_strings.end();
     43          ++it) {
     44       if (*it == "")
     45         continue;
     46 
     47       IPAddressNumber address;
     48       bool parsed = ParseIPLiteralToNumber(*it, &address);
     49       EXPECT_TRUE(parsed);
     50       servers.push_back(IPEndPoint(address, dns_protocol::kDefaultPort));
     51     }
     52 
     53     return classifier_.GetNameServersType(servers);
     54   }
     55 
     56  private:
     57   NameServerClassifier classifier_;
     58 };
     59 
     60 TEST_F(NameServerClassifierTest, None) {
     61   EXPECT_EQ(kNone, Classify(""));
     62 }
     63 
     64 TEST_F(NameServerClassifierTest, Google) {
     65   EXPECT_EQ(kGoogle, Classify("8.8.8.8"));
     66   EXPECT_EQ(kGoogle, Classify("8.8.8.8 8.8.4.4"));
     67   EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888"));
     68   EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 2001:4860:4860::8844"));
     69   EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 8.8.8.8"));
     70 
     71   // Make sure nobody took any shortcuts on the IP matching:
     72   EXPECT_EQ(kPublic, Classify("8.8.8.4"));
     73   EXPECT_EQ(kPublic, Classify("8.8.4.8"));
     74   EXPECT_EQ(kPublic, Classify("2001:4860:4860::8884"));
     75   EXPECT_EQ(kPublic, Classify("2001:4860:4860::8848"));
     76   EXPECT_EQ(kPublic, Classify("2001:4860:4860::1:8888"));
     77   EXPECT_EQ(kPublic, Classify("2001:4860:4860:1::8888"));
     78 }
     79 
     80 TEST_F(NameServerClassifierTest, PrivateLocalhost) {
     81   EXPECT_EQ(kPrivate, Classify("127.0.0.1"));
     82   EXPECT_EQ(kPrivate, Classify("::1"));
     83 }
     84 
     85 TEST_F(NameServerClassifierTest, PrivateRfc1918) {
     86   EXPECT_EQ(kPrivate, Classify("10.0.0.0 10.255.255.255"));
     87   EXPECT_EQ(kPrivate, Classify("172.16.0.0 172.31.255.255"));
     88   EXPECT_EQ(kPrivate, Classify("192.168.0.0 192.168.255.255"));
     89   EXPECT_EQ(kPrivate, Classify("10.1.1.1 172.16.1.1 192.168.1.1"));
     90 }
     91 
     92 TEST_F(NameServerClassifierTest, PrivateIPv4LinkLocal) {
     93   EXPECT_EQ(kPrivate, Classify("169.254.0.0 169.254.255.255"));
     94 }
     95 
     96 TEST_F(NameServerClassifierTest, PrivateIPv6LinkLocal) {
     97   EXPECT_EQ(kPrivate,
     98       Classify("fe80:: fe80:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
     99 }
    100 
    101 TEST_F(NameServerClassifierTest, Public) {
    102   EXPECT_EQ(kPublic, Classify("4.2.2.1"));
    103   EXPECT_EQ(kPublic, Classify("4.2.2.1 4.2.2.2"));
    104 }
    105 
    106 TEST_F(NameServerClassifierTest, Mixed) {
    107   EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1"));
    108   EXPECT_EQ(kMixed, Classify("8.8.8.8 4.2.2.1"));
    109   EXPECT_EQ(kMixed, Classify("192.168.1.1 4.2.2.1"));
    110   EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1 4.2.2.1"));
    111 }
    112 
    113 class DnsConfigServiceTest : public testing::Test {
    114  public:
    115   void OnConfigChanged(const DnsConfig& config) {
    116     last_config_ = config;
    117     if (quit_on_config_)
    118       base::MessageLoop::current()->Quit();
    119   }
    120 
    121  protected:
    122   class TestDnsConfigService : public DnsConfigService {
    123    public:
    124     virtual void ReadNow() OVERRIDE {}
    125     virtual bool StartWatching() OVERRIDE { return true; }
    126 
    127     // Expose the protected methods to this test suite.
    128     void InvalidateConfig() {
    129       DnsConfigService::InvalidateConfig();
    130     }
    131 
    132     void InvalidateHosts() {
    133       DnsConfigService::InvalidateHosts();
    134     }
    135 
    136     void OnConfigRead(const DnsConfig& config) {
    137       DnsConfigService::OnConfigRead(config);
    138     }
    139 
    140     void OnHostsRead(const DnsHosts& hosts) {
    141       DnsConfigService::OnHostsRead(hosts);
    142     }
    143 
    144     void set_watch_failed(bool value) {
    145       DnsConfigService::set_watch_failed(value);
    146     }
    147   };
    148 
    149   void WaitForConfig(base::TimeDelta timeout) {
    150     base::CancelableClosure closure(base::MessageLoop::QuitClosure());
    151     base::MessageLoop::current()->PostDelayedTask(
    152         FROM_HERE, closure.callback(), timeout);
    153     quit_on_config_ = true;
    154     base::MessageLoop::current()->Run();
    155     quit_on_config_ = false;
    156     closure.Cancel();
    157   }
    158 
    159   // Generate a config using the given seed..
    160   DnsConfig MakeConfig(unsigned seed) {
    161     DnsConfig config;
    162     IPAddressNumber ip;
    163     CHECK(ParseIPLiteralToNumber("1.2.3.4", &ip));
    164     config.nameservers.push_back(IPEndPoint(ip, seed & 0xFFFF));
    165     EXPECT_TRUE(config.IsValid());
    166     return config;
    167   }
    168 
    169   // Generate hosts using the given seed.
    170   DnsHosts MakeHosts(unsigned seed) {
    171     DnsHosts hosts;
    172     std::string hosts_content = "127.0.0.1 localhost";
    173     hosts_content.append(seed, '1');
    174     ParseHosts(hosts_content, &hosts);
    175     EXPECT_FALSE(hosts.empty());
    176     return hosts;
    177   }
    178 
    179   virtual void SetUp() OVERRIDE {
    180     quit_on_config_ = false;
    181 
    182     service_.reset(new TestDnsConfigService());
    183     service_->WatchConfig(base::Bind(&DnsConfigServiceTest::OnConfigChanged,
    184                                      base::Unretained(this)));
    185     EXPECT_FALSE(last_config_.IsValid());
    186   }
    187 
    188   DnsConfig last_config_;
    189   bool quit_on_config_;
    190 
    191   // Service under test.
    192   scoped_ptr<TestDnsConfigService> service_;
    193 };
    194 
    195 }  // namespace
    196 
    197 TEST_F(DnsConfigServiceTest, FirstConfig) {
    198   DnsConfig config = MakeConfig(1);
    199 
    200   service_->OnConfigRead(config);
    201   // No hosts yet, so no config.
    202   EXPECT_TRUE(last_config_.Equals(DnsConfig()));
    203 
    204   service_->OnHostsRead(config.hosts);
    205   EXPECT_TRUE(last_config_.Equals(config));
    206 }
    207 
    208 TEST_F(DnsConfigServiceTest, Timeout) {
    209   DnsConfig config = MakeConfig(1);
    210   config.hosts = MakeHosts(1);
    211   ASSERT_TRUE(config.IsValid());
    212 
    213   service_->OnConfigRead(config);
    214   service_->OnHostsRead(config.hosts);
    215   EXPECT_FALSE(last_config_.Equals(DnsConfig()));
    216   EXPECT_TRUE(last_config_.Equals(config));
    217 
    218   service_->InvalidateConfig();
    219   WaitForConfig(TestTimeouts::action_timeout());
    220   EXPECT_FALSE(last_config_.Equals(config));
    221   EXPECT_TRUE(last_config_.Equals(DnsConfig()));
    222 
    223   service_->OnConfigRead(config);
    224   EXPECT_FALSE(last_config_.Equals(DnsConfig()));
    225   EXPECT_TRUE(last_config_.Equals(config));
    226 
    227   service_->InvalidateHosts();
    228   WaitForConfig(TestTimeouts::action_timeout());
    229   EXPECT_FALSE(last_config_.Equals(config));
    230   EXPECT_TRUE(last_config_.Equals(DnsConfig()));
    231 
    232   DnsConfig bad_config = last_config_ = MakeConfig(0xBAD);
    233   service_->InvalidateConfig();
    234   // We don't expect an update. This should time out.
    235   WaitForConfig(base::TimeDelta::FromMilliseconds(100) +
    236                 TestTimeouts::tiny_timeout());
    237   EXPECT_TRUE(last_config_.Equals(bad_config)) << "Unexpected change";
    238 
    239   last_config_ = DnsConfig();
    240   service_->OnConfigRead(config);
    241   service_->OnHostsRead(config.hosts);
    242   EXPECT_FALSE(last_config_.Equals(DnsConfig()));
    243   EXPECT_TRUE(last_config_.Equals(config));
    244 }
    245 
    246 TEST_F(DnsConfigServiceTest, SameConfig) {
    247   DnsConfig config = MakeConfig(1);
    248   config.hosts = MakeHosts(1);
    249 
    250   service_->OnConfigRead(config);
    251   service_->OnHostsRead(config.hosts);
    252   EXPECT_FALSE(last_config_.Equals(DnsConfig()));
    253   EXPECT_TRUE(last_config_.Equals(config));
    254 
    255   last_config_ = DnsConfig();
    256   service_->OnConfigRead(config);
    257   EXPECT_TRUE(last_config_.Equals(DnsConfig())) << "Unexpected change";
    258 
    259   service_->OnHostsRead(config.hosts);
    260   EXPECT_TRUE(last_config_.Equals(DnsConfig())) << "Unexpected change";
    261 }
    262 
    263 TEST_F(DnsConfigServiceTest, DifferentConfig) {
    264   DnsConfig config1 = MakeConfig(1);
    265   DnsConfig config2 = MakeConfig(2);
    266   DnsConfig config3 = MakeConfig(1);
    267   config1.hosts = MakeHosts(1);
    268   config2.hosts = MakeHosts(1);
    269   config3.hosts = MakeHosts(2);
    270   ASSERT_TRUE(config1.EqualsIgnoreHosts(config3));
    271   ASSERT_FALSE(config1.Equals(config2));
    272   ASSERT_FALSE(config1.Equals(config3));
    273   ASSERT_FALSE(config2.Equals(config3));
    274 
    275   service_->OnConfigRead(config1);
    276   service_->OnHostsRead(config1.hosts);
    277   EXPECT_FALSE(last_config_.Equals(DnsConfig()));
    278   EXPECT_TRUE(last_config_.Equals(config1));
    279 
    280   // It doesn't matter for this tests, but increases coverage.
    281   service_->InvalidateConfig();
    282   service_->InvalidateHosts();
    283 
    284   service_->OnConfigRead(config2);
    285   EXPECT_TRUE(last_config_.Equals(config1)) << "Unexpected change";
    286   service_->OnHostsRead(config2.hosts);  // Not an actual change.
    287   EXPECT_FALSE(last_config_.Equals(config1));
    288   EXPECT_TRUE(last_config_.Equals(config2));
    289 
    290   service_->OnConfigRead(config3);
    291   EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config3));
    292   service_->OnHostsRead(config3.hosts);
    293   EXPECT_FALSE(last_config_.Equals(config2));
    294   EXPECT_TRUE(last_config_.Equals(config3));
    295 }
    296 
    297 TEST_F(DnsConfigServiceTest, WatchFailure) {
    298   DnsConfig config1 = MakeConfig(1);
    299   DnsConfig config2 = MakeConfig(2);
    300   config1.hosts = MakeHosts(1);
    301   config2.hosts = MakeHosts(2);
    302 
    303   service_->OnConfigRead(config1);
    304   service_->OnHostsRead(config1.hosts);
    305   EXPECT_FALSE(last_config_.Equals(DnsConfig()));
    306   EXPECT_TRUE(last_config_.Equals(config1));
    307 
    308   // Simulate watch failure.
    309   service_->set_watch_failed(true);
    310   service_->InvalidateConfig();
    311   WaitForConfig(TestTimeouts::action_timeout());
    312   EXPECT_FALSE(last_config_.Equals(config1));
    313   EXPECT_TRUE(last_config_.Equals(DnsConfig()));
    314 
    315   DnsConfig bad_config = last_config_ = MakeConfig(0xBAD);
    316   // Actual change in config, so expect an update, but it should be empty.
    317   service_->OnConfigRead(config1);
    318   EXPECT_FALSE(last_config_.Equals(bad_config));
    319   EXPECT_TRUE(last_config_.Equals(DnsConfig()));
    320 
    321   last_config_ = bad_config;
    322   // Actual change in config, so expect an update, but it should be empty.
    323   service_->InvalidateConfig();
    324   service_->OnConfigRead(config2);
    325   EXPECT_FALSE(last_config_.Equals(bad_config));
    326   EXPECT_TRUE(last_config_.Equals(DnsConfig()));
    327 
    328   last_config_ = bad_config;
    329   // No change, so no update.
    330   service_->InvalidateConfig();
    331   service_->OnConfigRead(config2);
    332   EXPECT_TRUE(last_config_.Equals(bad_config));
    333 }
    334 
    335 #if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_WIN)
    336 // TODO(szym): This is really an integration test and can time out if HOSTS is
    337 // huge. http://crbug.com/107810
    338 TEST_F(DnsConfigServiceTest, DISABLED_GetSystemConfig) {
    339   service_.reset();
    340   scoped_ptr<DnsConfigService> service(DnsConfigService::CreateSystemService());
    341 
    342   service->ReadConfig(base::Bind(&DnsConfigServiceTest::OnConfigChanged,
    343                                  base::Unretained(this)));
    344   base::TimeDelta kTimeout = TestTimeouts::action_max_timeout();
    345   WaitForConfig(kTimeout);
    346   ASSERT_TRUE(last_config_.IsValid()) << "Did not receive DnsConfig in " <<
    347       kTimeout.InSecondsF() << "s";
    348 }
    349 #endif  // OS_POSIX || OS_WIN
    350 
    351 }  // namespace net
    352 
    353