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/mapped_host_resolver.h" 6 7 #include "net/base/address_list.h" 8 #include "net/base/net_errors.h" 9 #include "net/base/net_log.h" 10 #include "net/base/net_util.h" 11 #include "net/base/test_completion_callback.h" 12 #include "net/dns/mock_host_resolver.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace net { 16 17 namespace { 18 19 std::string FirstAddress(const AddressList& address_list) { 20 if (address_list.empty()) 21 return std::string(); 22 return address_list.front().ToString(); 23 } 24 25 TEST(MappedHostResolverTest, Inclusion) { 26 // Create a mock host resolver, with specific hostname to IP mappings. 27 scoped_ptr<MockHostResolver> resolver_impl(new MockHostResolver()); 28 resolver_impl->rules()->AddSimulatedFailure("*google.com"); 29 resolver_impl->rules()->AddRule("baz.com", "192.168.1.5"); 30 resolver_impl->rules()->AddRule("foo.com", "192.168.1.8"); 31 resolver_impl->rules()->AddRule("proxy", "192.168.1.11"); 32 33 // Create a remapped resolver that uses |resolver_impl|. 34 scoped_ptr<MappedHostResolver> resolver( 35 new MappedHostResolver(resolver_impl.PassAs<HostResolver>())); 36 37 int rv; 38 AddressList address_list; 39 40 // Try resolving "www.google.com:80". There are no mappings yet, so this 41 // hits |resolver_impl| and fails. 42 TestCompletionCallback callback; 43 rv = resolver->Resolve( 44 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 45 DEFAULT_PRIORITY, 46 &address_list, 47 callback.callback(), 48 NULL, 49 BoundNetLog()); 50 EXPECT_EQ(ERR_IO_PENDING, rv); 51 rv = callback.WaitForResult(); 52 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); 53 54 // Remap *.google.com to baz.com. 55 EXPECT_TRUE(resolver->AddRuleFromString("map *.google.com baz.com")); 56 57 // Try resolving "www.google.com:80". Should be remapped to "baz.com:80". 58 rv = resolver->Resolve( 59 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 60 DEFAULT_PRIORITY, 61 &address_list, 62 callback.callback(), 63 NULL, 64 BoundNetLog()); 65 EXPECT_EQ(ERR_IO_PENDING, rv); 66 rv = callback.WaitForResult(); 67 EXPECT_EQ(OK, rv); 68 EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); 69 70 // Try resolving "foo.com:77". This will NOT be remapped, so result 71 // is "foo.com:77". 72 rv = resolver->Resolve(HostResolver::RequestInfo(HostPortPair("foo.com", 77)), 73 DEFAULT_PRIORITY, 74 &address_list, 75 callback.callback(), 76 NULL, 77 BoundNetLog()); 78 EXPECT_EQ(ERR_IO_PENDING, rv); 79 rv = callback.WaitForResult(); 80 EXPECT_EQ(OK, rv); 81 EXPECT_EQ("192.168.1.8:77", FirstAddress(address_list)); 82 83 // Remap "*.org" to "proxy:99". 84 EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99")); 85 86 // Try resolving "chromium.org:61". Should be remapped to "proxy:99". 87 rv = resolver->Resolve( 88 HostResolver::RequestInfo(HostPortPair("chromium.org", 61)), 89 DEFAULT_PRIORITY, 90 &address_list, 91 callback.callback(), 92 NULL, 93 BoundNetLog()); 94 EXPECT_EQ(ERR_IO_PENDING, rv); 95 rv = callback.WaitForResult(); 96 EXPECT_EQ(OK, rv); 97 EXPECT_EQ("192.168.1.11:99", FirstAddress(address_list)); 98 } 99 100 // Tests that exclusions are respected. 101 TEST(MappedHostResolverTest, Exclusion) { 102 // Create a mock host resolver, with specific hostname to IP mappings. 103 scoped_ptr<MockHostResolver> resolver_impl(new MockHostResolver()); 104 resolver_impl->rules()->AddRule("baz", "192.168.1.5"); 105 resolver_impl->rules()->AddRule("www.google.com", "192.168.1.3"); 106 107 // Create a remapped resolver that uses |resolver_impl|. 108 scoped_ptr<MappedHostResolver> resolver( 109 new MappedHostResolver(resolver_impl.PassAs<HostResolver>())); 110 111 int rv; 112 AddressList address_list; 113 TestCompletionCallback callback; 114 115 // Remap "*.com" to "baz". 116 EXPECT_TRUE(resolver->AddRuleFromString("map *.com baz")); 117 118 // Add an exclusion for "*.google.com". 119 EXPECT_TRUE(resolver->AddRuleFromString("EXCLUDE *.google.com")); 120 121 // Try resolving "www.google.com". Should not be remapped due to exclusion). 122 rv = resolver->Resolve( 123 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 124 DEFAULT_PRIORITY, 125 &address_list, 126 callback.callback(), 127 NULL, 128 BoundNetLog()); 129 EXPECT_EQ(ERR_IO_PENDING, rv); 130 rv = callback.WaitForResult(); 131 EXPECT_EQ(OK, rv); 132 EXPECT_EQ("192.168.1.3:80", FirstAddress(address_list)); 133 134 // Try resolving "chrome.com:80". Should be remapped to "baz:80". 135 rv = resolver->Resolve( 136 HostResolver::RequestInfo(HostPortPair("chrome.com", 80)), 137 DEFAULT_PRIORITY, 138 &address_list, 139 callback.callback(), 140 NULL, 141 BoundNetLog()); 142 EXPECT_EQ(ERR_IO_PENDING, rv); 143 rv = callback.WaitForResult(); 144 EXPECT_EQ(OK, rv); 145 EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); 146 } 147 148 TEST(MappedHostResolverTest, SetRulesFromString) { 149 // Create a mock host resolver, with specific hostname to IP mappings. 150 scoped_ptr<MockHostResolver> resolver_impl(new MockHostResolver()); 151 resolver_impl->rules()->AddRule("baz", "192.168.1.7"); 152 resolver_impl->rules()->AddRule("bar", "192.168.1.9"); 153 154 // Create a remapped resolver that uses |resolver_impl|. 155 scoped_ptr<MappedHostResolver> resolver( 156 new MappedHostResolver(resolver_impl.PassAs<HostResolver>())); 157 158 int rv; 159 AddressList address_list; 160 TestCompletionCallback callback; 161 162 // Remap "*.com" to "baz", and *.net to "bar:60". 163 resolver->SetRulesFromString("map *.com baz , map *.net bar:60"); 164 165 // Try resolving "www.google.com". Should be remapped to "baz". 166 rv = resolver->Resolve( 167 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 168 DEFAULT_PRIORITY, 169 &address_list, 170 callback.callback(), 171 NULL, 172 BoundNetLog()); 173 EXPECT_EQ(ERR_IO_PENDING, rv); 174 rv = callback.WaitForResult(); 175 EXPECT_EQ(OK, rv); 176 EXPECT_EQ("192.168.1.7:80", FirstAddress(address_list)); 177 178 // Try resolving "chrome.net:80". Should be remapped to "bar:60". 179 rv = resolver->Resolve( 180 HostResolver::RequestInfo(HostPortPair("chrome.net", 80)), 181 DEFAULT_PRIORITY, 182 &address_list, 183 callback.callback(), 184 NULL, 185 BoundNetLog()); 186 EXPECT_EQ(ERR_IO_PENDING, rv); 187 rv = callback.WaitForResult(); 188 EXPECT_EQ(OK, rv); 189 EXPECT_EQ("192.168.1.9:60", FirstAddress(address_list)); 190 } 191 192 // Parsing bad rules should silently discard the rule (and never crash). 193 TEST(MappedHostResolverTest, ParseInvalidRules) { 194 scoped_ptr<MappedHostResolver> resolver( 195 new MappedHostResolver(scoped_ptr<HostResolver>())); 196 197 EXPECT_FALSE(resolver->AddRuleFromString("xyz")); 198 EXPECT_FALSE(resolver->AddRuleFromString(std::string())); 199 EXPECT_FALSE(resolver->AddRuleFromString(" ")); 200 EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE")); 201 EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE foo bar")); 202 EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE")); 203 EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x")); 204 EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x :10")); 205 } 206 207 // Test mapping hostnames to resolving failures. 208 TEST(MappedHostResolverTest, MapToError) { 209 scoped_ptr<MockHostResolver> resolver_impl(new MockHostResolver()); 210 resolver_impl->rules()->AddRule("*", "192.168.1.5"); 211 212 scoped_ptr<MappedHostResolver> resolver( 213 new MappedHostResolver(resolver_impl.PassAs<HostResolver>())); 214 215 int rv; 216 AddressList address_list; 217 218 // Remap *.google.com to resolving failures. 219 EXPECT_TRUE(resolver->AddRuleFromString("MAP *.google.com ~NOTFOUND")); 220 221 // Try resolving www.google.com --> Should give an error. 222 TestCompletionCallback callback1; 223 rv = resolver->Resolve( 224 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 225 DEFAULT_PRIORITY, 226 &address_list, 227 callback1.callback(), 228 NULL, 229 BoundNetLog()); 230 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); 231 232 // Try resolving www.foo.com --> Should succeed. 233 TestCompletionCallback callback2; 234 rv = resolver->Resolve( 235 HostResolver::RequestInfo(HostPortPair("www.foo.com", 80)), 236 DEFAULT_PRIORITY, 237 &address_list, 238 callback2.callback(), 239 NULL, 240 BoundNetLog()); 241 EXPECT_EQ(ERR_IO_PENDING, rv); 242 rv = callback2.WaitForResult(); 243 EXPECT_EQ(OK, rv); 244 EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); 245 } 246 247 } // namespace 248 249 } // namespace net 250