1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
// Copyright (c) 2009 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 "base/scoped_ptr.h"
#include "net/base/address_list.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/base/sys_addrinfo.h"
#include "net/proxy/proxy_resolver_js_bindings.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
// This is a HostResolver that synchronously resolves all hosts to the
// following address list of length 3:
// 192.168.1.1
// 172.22.34.1
// 200.100.1.2
class MockHostResolverWithMultipleResults : public HostResolver {
public:
// HostResolver methods:
virtual int Resolve(const RequestInfo& info,
AddressList* addresses,
CompletionCallback* callback,
RequestHandle* out_req,
LoadLog* load_log) {
// Build up the result list (in reverse).
AddressList temp_list = ResolveIPLiteral("200.100.1.2");
temp_list = PrependAddressToList("172.22.34.1", temp_list);
temp_list = PrependAddressToList("192.168.1.1", temp_list);
*addresses = temp_list;
return OK;
}
virtual void CancelRequest(RequestHandle req) {}
virtual void AddObserver(Observer* observer) {}
virtual void RemoveObserver(Observer* observer) {}
virtual HostCache* GetHostCache() { return NULL; }
virtual void Shutdown() {}
private:
~MockHostResolverWithMultipleResults() {}
// Resolves an IP literal to an address list.
AddressList ResolveIPLiteral(const char* ip_literal) {
AddressList result;
int rv = SystemHostResolverProc(ip_literal,
ADDRESS_FAMILY_UNSPECIFIED,
&result);
EXPECT_EQ(OK, rv);
EXPECT_EQ(NULL, result.head()->ai_next);
return result;
}
// Builds an AddressList that is |ip_literal| + |address_list|.
// |orig_list| must not be empty.
AddressList PrependAddressToList(const char* ip_literal,
const AddressList& orig_list) {
// Build an addrinfo for |ip_literal|.
AddressList result = ResolveIPLiteral(ip_literal);
struct addrinfo* result_head = const_cast<struct addrinfo*>(result.head());
// Temporarily append |orig_list| to |result|.
result_head->ai_next = const_cast<struct addrinfo*>(orig_list.head());
// Make a copy of the concatenated list.
AddressList concatenated;
concatenated.Copy(result.head());
// Restore |result| (so it is freed properly).
result_head->ai_next = NULL;
return concatenated;
}
};
TEST(ProxyResolverJSBindingsTest, DnsResolve) {
scoped_refptr<MockHostResolver> host_resolver(new MockHostResolver);
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
scoped_ptr<ProxyResolverJSBindings> bindings(
ProxyResolverJSBindings::CreateDefault(host_resolver, NULL));
// Empty string is not considered a valid host (even though on some systems
// requesting this will resolve to localhost).
host_resolver->rules()->AddSimulatedFailure("");
EXPECT_EQ("", bindings->DnsResolve(""));
// Should call through to the HostResolver.
host_resolver->rules()->AddRule("google.com", "192.168.1.1");
EXPECT_EQ("192.168.1.1", bindings->DnsResolve("google.com"));
// Resolve failures should give empty string.
host_resolver->rules()->AddSimulatedFailure("fail");
EXPECT_EQ("", bindings->DnsResolve("fail"));
// TODO(eroman): would be nice to have an IPV6 test here too, but that
// won't work on all systems.
}
TEST(ProxyResolverJSBindingsTest, MyIpAddress) {
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
scoped_ptr<ProxyResolverJSBindings> bindings(
ProxyResolverJSBindings::CreateDefault(
new MockHostResolver, NULL));
// Our IP address is always going to be 127.0.0.1, since we are using a
// mock host resolver.
std::string my_ip_address = bindings->MyIpAddress();
EXPECT_EQ("127.0.0.1", my_ip_address);
}
// Tests that the regular PAC functions restrict results to IPv4,
// but that the Microsoft extensions to PAC do not. We test this
// by seeing whether ADDRESS_FAMILY_IPV4 or ADDRESS_FAMILY_UNSPECIFIED
// was passed into to the host resolver.
//
// Restricted to IPv4 address family:
// myIpAddress()
// dnsResolve()
//
// Unrestricted address family:
// myIpAddressEx()
// dnsResolveEx()
TEST(ProxyResolverJSBindingsTest, RestrictAddressFamily) {
scoped_refptr<MockHostResolver> host_resolver(new MockHostResolver);
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
scoped_ptr<ProxyResolverJSBindings> bindings(
ProxyResolverJSBindings::CreateDefault(
host_resolver, NULL));
// Make it so requests resolve to particular address patterns based on family:
// IPV4_ONLY --> 192.168.1.*
// UNSPECIFIED --> 192.168.2.1
host_resolver->rules()->AddRuleForAddressFamily(
"foo", ADDRESS_FAMILY_IPV4, "192.168.1.1");
host_resolver->rules()->AddRuleForAddressFamily(
"*", ADDRESS_FAMILY_IPV4, "192.168.1.2");
host_resolver->rules()->AddRuleForAddressFamily(
"foo", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.1");
host_resolver->rules()->AddRuleForAddressFamily(
"*", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.2");
// Verify that our mock setups works as expected, and we get different results
// depending if the address family was IPV4_ONLY or not.
HostResolver::RequestInfo info("foo", 80);
AddressList address_list;
EXPECT_EQ(OK, host_resolver->Resolve(info, &address_list, NULL, NULL, NULL));
EXPECT_EQ("192.168.2.1", NetAddressToString(address_list.head()));
info.set_address_family(ADDRESS_FAMILY_IPV4);
EXPECT_EQ(OK, host_resolver->Resolve(info, &address_list, NULL, NULL, NULL));
EXPECT_EQ("192.168.1.1", NetAddressToString(address_list.head()));
// Now the actual test.
EXPECT_EQ("192.168.1.2", bindings->MyIpAddress()); // IPv4 restricted.
EXPECT_EQ("192.168.1.1", bindings->DnsResolve("foo")); // IPv4 restricted.
EXPECT_EQ("192.168.1.2", bindings->DnsResolve("foo2")); // IPv4 restricted.
EXPECT_EQ("192.168.2.2", bindings->MyIpAddressEx()); // Unrestricted.
EXPECT_EQ("192.168.2.1", bindings->DnsResolveEx("foo")); // Unrestricted.
EXPECT_EQ("192.168.2.2", bindings->DnsResolveEx("foo2")); // Unrestricted.
}
// Test that myIpAddressEx() and dnsResolveEx() both return a semi-colon
// separated list of addresses (as opposed to the non-Ex versions which
// just return the first result).
TEST(ProxyResolverJSBindingsTest, ExFunctionsReturnList) {
scoped_refptr<HostResolver> host_resolver(
new MockHostResolverWithMultipleResults);
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
scoped_ptr<ProxyResolverJSBindings> bindings(
ProxyResolverJSBindings::CreateDefault(host_resolver, NULL));
EXPECT_EQ("192.168.1.1;172.22.34.1;200.100.1.2",
bindings->MyIpAddressEx());
EXPECT_EQ("192.168.1.1;172.22.34.1;200.100.1.2",
bindings->DnsResolveEx("FOO"));
}
} // namespace
} // namespace net
|