OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <string.h> | 5 #include <string.h> |
6 #include <algorithm> | 6 #include <algorithm> |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "googleurl/src/gurl.h" | 10 #include "googleurl/src/gurl.h" |
11 #include "net/base/filter.h" | 11 #include "net/base/filter.h" |
12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
13 #include "net/url_request/url_request.h" | 13 #include "net/url_request/url_request.h" |
14 #include "net/url_request/url_request_job.h" | 14 #include "net/url_request/url_request_job.h" |
15 #include "net/url_request/url_request_job_tracker.h" | 15 #include "net/url_request/url_request_job_tracker.h" |
16 #include "net/url_request/url_request_status.h" | 16 #include "net/url_request/url_request_status.h" |
17 #include "net/url_request/url_request_test_util.h" | 17 #include "net/url_request/url_request_test_util.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "testing/platform_test.h" | 20 #include "testing/platform_test.h" |
21 | 21 |
22 using testing::Eq; | 22 using testing::Eq; |
23 using testing::InSequence; | 23 using testing::InSequence; |
24 using testing::NotNull; | 24 using testing::NotNull; |
25 using testing::StrictMock; | 25 using testing::StrictMock; |
26 | 26 |
27 namespace net { | |
27 namespace { | 28 namespace { |
tfarina
2011/03/08 21:41:05
You can get rid of the anonymous namespace (that w
adamk
2011/03/08 21:53:10
Mind if I keep it? It's nicely hiding GetResponse
| |
28 | 29 |
29 const char kBasic[] = "Hello\n"; | 30 const char kBasic[] = "Hello\n"; |
30 | 31 |
31 // The above string "Hello\n", gzip compressed. | 32 // The above string "Hello\n", gzip compressed. |
32 const unsigned char kCompressed[] = { | 33 const unsigned char kCompressed[] = { |
33 0x1f, 0x8b, 0x08, 0x08, 0x38, 0x18, 0x2e, 0x4c, 0x00, 0x03, 0x63, | 34 0x1f, 0x8b, 0x08, 0x08, 0x38, 0x18, 0x2e, 0x4c, 0x00, 0x03, 0x63, |
34 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2e, 0x68, | 35 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2e, 0x68, |
35 0x74, 0x6d, 0x6c, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, | 36 0x74, 0x6d, 0x6c, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, |
36 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 | 37 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 |
37 }; | 38 }; |
38 | 39 |
39 bool GetResponseBody(const GURL& url, std::string* out_body) { | 40 bool GetResponseBody(const GURL& url, std::string* out_body) { |
40 if (url.spec() == "test:basic") { | 41 if (url.spec() == "test:basic") { |
41 *out_body = kBasic; | 42 *out_body = kBasic; |
42 } else if (url.spec() == "test:compressed") { | 43 } else if (url.spec() == "test:compressed") { |
43 out_body->assign(reinterpret_cast<const char*>(kCompressed), | 44 out_body->assign(reinterpret_cast<const char*>(kCompressed), |
44 sizeof(kCompressed)); | 45 sizeof(kCompressed)); |
45 } else { | 46 } else { |
46 return false; | 47 return false; |
47 } | 48 } |
48 | 49 |
49 return true; | 50 return true; |
50 } | 51 } |
51 | 52 |
52 class MockJobObserver : public net::URLRequestJobTracker::JobObserver { | 53 class MockJobObserver : public URLRequestJobTracker::JobObserver { |
53 public: | 54 public: |
54 MOCK_METHOD1(OnJobAdded, void(net::URLRequestJob* job)); | 55 MOCK_METHOD1(OnJobAdded, void(URLRequestJob* job)); |
55 MOCK_METHOD1(OnJobRemoved, void(net::URLRequestJob* job)); | 56 MOCK_METHOD1(OnJobRemoved, void(URLRequestJob* job)); |
56 MOCK_METHOD2(OnJobDone, void(net::URLRequestJob* job, | 57 MOCK_METHOD2(OnJobDone, void(URLRequestJob* job, |
57 const net::URLRequestStatus& status)); | 58 const URLRequestStatus& status)); |
58 MOCK_METHOD3(OnJobRedirect, void(net::URLRequestJob* job, | 59 MOCK_METHOD3(OnJobRedirect, void(URLRequestJob* job, |
59 const GURL& location, | 60 const GURL& location, |
60 int status_code)); | 61 int status_code)); |
61 MOCK_METHOD3(OnBytesRead, void(net::URLRequestJob* job, | 62 MOCK_METHOD3(OnBytesRead, void(URLRequestJob* job, |
62 const char* buf, | 63 const char* buf, |
63 int byte_count)); | 64 int byte_count)); |
64 }; | 65 }; |
65 | 66 |
66 // A net::URLRequestJob that returns static content for given URLs. We do | 67 // A URLRequestJob that returns static content for given URLs. We do |
67 // not use net::URLRequestTestJob here because net::URLRequestTestJob fakes | 68 // not use URLRequestTestJob here because URLRequestTestJob fakes |
68 // async operations by calling ReadRawData synchronously in an async | 69 // async operations by calling ReadRawData synchronously in an async |
69 // callback. This test requires a net::URLRequestJob that returns false for | 70 // callback. This test requires a URLRequestJob that returns false for |
70 // async reads, in order to exercise the real async read codepath. | 71 // async reads, in order to exercise the real async read codepath. |
71 class URLRequestJobTrackerTestJob : public net::URLRequestJob { | 72 class URLRequestJobTrackerTestJob : public URLRequestJob { |
72 public: | 73 public: |
73 URLRequestJobTrackerTestJob(net::URLRequest* request, bool async_reads) | 74 URLRequestJobTrackerTestJob(URLRequest* request, bool async_reads) |
74 : net::URLRequestJob(request), async_reads_(async_reads) {} | 75 : URLRequestJob(request), async_reads_(async_reads) {} |
75 | 76 |
76 void Start() { | 77 void Start() { |
77 ASSERT_TRUE(GetResponseBody(request_->url(), &response_data_)); | 78 ASSERT_TRUE(GetResponseBody(request_->url(), &response_data_)); |
78 | 79 |
79 // Start reading asynchronously so that all error reporting and data | 80 // Start reading asynchronously so that all error reporting and data |
80 // callbacks happen as they would for network requests. | 81 // callbacks happen as they would for network requests. |
81 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 82 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
82 this, &URLRequestJobTrackerTestJob::NotifyHeadersComplete)); | 83 this, &URLRequestJobTrackerTestJob::NotifyHeadersComplete)); |
83 } | 84 } |
84 | 85 |
85 bool ReadRawData(net::IOBuffer* buf, int buf_size, | 86 bool ReadRawData(IOBuffer* buf, int buf_size, |
86 int *bytes_read) { | 87 int *bytes_read) { |
87 const size_t bytes_to_read = std::min( | 88 const size_t bytes_to_read = std::min( |
88 response_data_.size(), static_cast<size_t>(buf_size)); | 89 response_data_.size(), static_cast<size_t>(buf_size)); |
89 | 90 |
90 // Regardless of whether we're performing a sync or async read, | 91 // Regardless of whether we're performing a sync or async read, |
91 // copy the data into the caller's buffer now. That way we don't | 92 // copy the data into the caller's buffer now. That way we don't |
92 // have to hold on to the buffers in the async case. | 93 // have to hold on to the buffers in the async case. |
93 memcpy(buf->data(), response_data_.data(), bytes_to_read); | 94 memcpy(buf->data(), response_data_.data(), bytes_to_read); |
94 response_data_.erase(0, bytes_to_read); | 95 response_data_.erase(0, bytes_to_read); |
95 | 96 |
96 if (async_reads_) { | 97 if (async_reads_) { |
97 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | 98 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); |
98 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 99 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
99 this, &URLRequestJobTrackerTestJob::OnReadCompleted, | 100 this, &URLRequestJobTrackerTestJob::OnReadCompleted, |
100 bytes_to_read)); | 101 bytes_to_read)); |
101 } else { | 102 } else { |
102 SetStatus(net::URLRequestStatus()); | 103 SetStatus(URLRequestStatus()); |
103 *bytes_read = bytes_to_read; | 104 *bytes_read = bytes_to_read; |
104 } | 105 } |
105 return !async_reads_; | 106 return !async_reads_; |
106 } | 107 } |
107 | 108 |
108 void OnReadCompleted(int status) { | 109 void OnReadCompleted(int status) { |
109 if (status == 0) { | 110 if (status == 0) { |
110 NotifyDone(net::URLRequestStatus()); | 111 NotifyDone(URLRequestStatus()); |
111 } else if (status > 0) { | 112 } else if (status > 0) { |
112 SetStatus(net::URLRequestStatus()); | 113 SetStatus(URLRequestStatus()); |
113 } else { | 114 } else { |
114 ASSERT_FALSE(true) << "Unexpected OnReadCompleted callback."; | 115 ASSERT_FALSE(true) << "Unexpected OnReadCompleted callback."; |
115 } | 116 } |
116 | 117 |
117 NotifyReadComplete(status); | 118 NotifyReadComplete(status); |
118 } | 119 } |
119 | 120 |
120 bool GetContentEncodings( | 121 bool GetContentEncodings( |
121 std::vector<Filter::FilterType>* encoding_types) { | 122 std::vector<Filter::FilterType>* encoding_types) { |
122 if (request_->url().spec() == "test:basic") { | 123 if (request_->url().spec() == "test:basic") { |
123 return false; | 124 return false; |
124 } else if (request_->url().spec() == "test:compressed") { | 125 } else if (request_->url().spec() == "test:compressed") { |
125 encoding_types->push_back(Filter::FILTER_TYPE_GZIP); | 126 encoding_types->push_back(Filter::FILTER_TYPE_GZIP); |
126 return true; | 127 return true; |
127 } else { | 128 } else { |
128 return net::URLRequestJob::GetContentEncodings(encoding_types); | 129 return URLRequestJob::GetContentEncodings(encoding_types); |
129 } | 130 } |
130 } | 131 } |
131 | 132 |
132 // The data to send, will be set in Start(). | 133 // The data to send, will be set in Start(). |
133 std::string response_data_; | 134 std::string response_data_; |
134 | 135 |
135 // Should reads be synchronous or asynchronous? | 136 // Should reads be synchronous or asynchronous? |
136 const bool async_reads_; | 137 const bool async_reads_; |
137 }; | 138 }; |
138 | 139 |
139 // Google Mock Matcher to check two net::URLRequestStatus instances for | 140 // Google Mock Matcher to check two URLRequestStatus instances for |
140 // equality. | 141 // equality. |
141 MATCHER_P(StatusEq, other, "") { | 142 MATCHER_P(StatusEq, other, "") { |
142 return (arg.status() == other.status() && | 143 return (arg.status() == other.status() && |
143 arg.os_error() == other.os_error()); | 144 arg.os_error() == other.os_error()); |
144 } | 145 } |
145 | 146 |
146 // Google Mock Matcher to check that two blocks of memory are equal. | 147 // Google Mock Matcher to check that two blocks of memory are equal. |
147 MATCHER_P2(MemEq, other, len, "") { | 148 MATCHER_P2(MemEq, other, len, "") { |
148 return memcmp(arg, other, len) == 0; | 149 return memcmp(arg, other, len) == 0; |
149 } | 150 } |
150 | 151 |
151 class URLRequestJobTrackerTest : public PlatformTest { | 152 class URLRequestJobTrackerTest : public PlatformTest { |
152 protected: | 153 protected: |
153 static void SetUpTestCase() { | 154 static void SetUpTestCase() { |
154 net::URLRequest::RegisterProtocolFactory("test", &Factory); | 155 URLRequest::RegisterProtocolFactory("test", &Factory); |
155 } | 156 } |
156 | 157 |
157 virtual void SetUp() { | 158 virtual void SetUp() { |
158 g_async_reads = true; | 159 g_async_reads = true; |
159 } | 160 } |
160 | 161 |
161 void AssertJobTrackerCallbacks(const char* url) { | 162 void AssertJobTrackerCallbacks(const char* url) { |
162 InSequence seq; | 163 InSequence seq; |
163 testing::StrictMock<MockJobObserver> observer; | 164 testing::StrictMock<MockJobObserver> observer; |
164 | 165 |
165 const GURL gurl(url); | 166 const GURL gurl(url); |
166 std::string body; | 167 std::string body; |
167 ASSERT_TRUE(GetResponseBody(gurl, &body)); | 168 ASSERT_TRUE(GetResponseBody(gurl, &body)); |
168 | 169 |
169 // We expect to receive one call for each method on the JobObserver, | 170 // We expect to receive one call for each method on the JobObserver, |
170 // in the following order: | 171 // in the following order: |
171 EXPECT_CALL(observer, OnJobAdded(NotNull())); | 172 EXPECT_CALL(observer, OnJobAdded(NotNull())); |
172 EXPECT_CALL(observer, OnBytesRead(NotNull(), | 173 EXPECT_CALL(observer, OnBytesRead(NotNull(), |
173 MemEq(body.data(), body.size()), | 174 MemEq(body.data(), body.size()), |
174 Eq(static_cast<int>(body.size())))); | 175 Eq(static_cast<int>(body.size())))); |
175 EXPECT_CALL(observer, OnJobDone(NotNull(), | 176 EXPECT_CALL(observer, OnJobDone(NotNull(), |
176 StatusEq(net::URLRequestStatus()))); | 177 StatusEq(URLRequestStatus()))); |
177 EXPECT_CALL(observer, OnJobRemoved(NotNull())); | 178 EXPECT_CALL(observer, OnJobRemoved(NotNull())); |
178 | 179 |
179 // Attach our observer and perform the resource fetch. | 180 // Attach our observer and perform the resource fetch. |
180 net::g_url_request_job_tracker.AddObserver(&observer); | 181 g_url_request_job_tracker.AddObserver(&observer); |
181 Fetch(gurl); | 182 Fetch(gurl); |
182 net::g_url_request_job_tracker.RemoveObserver(&observer); | 183 g_url_request_job_tracker.RemoveObserver(&observer); |
183 } | 184 } |
184 | 185 |
185 void Fetch(const GURL& url) { | 186 void Fetch(const GURL& url) { |
186 TestDelegate d; | 187 TestDelegate d; |
187 { | 188 { |
188 net::URLRequest request(url, &d); | 189 URLRequest request(url, &d); |
189 request.Start(); | 190 request.Start(); |
190 MessageLoop::current()->RunAllPending(); | 191 MessageLoop::current()->RunAllPending(); |
191 } | 192 } |
192 | 193 |
193 // A few sanity checks to make sure that the delegate also | 194 // A few sanity checks to make sure that the delegate also |
194 // receives the expected callbacks. | 195 // receives the expected callbacks. |
195 EXPECT_EQ(1, d.response_started_count()); | 196 EXPECT_EQ(1, d.response_started_count()); |
196 EXPECT_FALSE(d.received_data_before_response()); | 197 EXPECT_FALSE(d.received_data_before_response()); |
197 EXPECT_STREQ(kBasic, d.data_received().c_str()); | 198 EXPECT_STREQ(kBasic, d.data_received().c_str()); |
198 } | 199 } |
199 | 200 |
200 static net::URLRequest::ProtocolFactory Factory; | 201 static URLRequest::ProtocolFactory Factory; |
201 static bool g_async_reads; | 202 static bool g_async_reads; |
202 }; | 203 }; |
203 | 204 |
204 // static | 205 // static |
205 net::URLRequestJob* URLRequestJobTrackerTest::Factory( | 206 URLRequestJob* URLRequestJobTrackerTest::Factory( |
206 net::URLRequest* request, | 207 URLRequest* request, |
207 const std::string& scheme) { | 208 const std::string& scheme) { |
208 return new URLRequestJobTrackerTestJob(request, g_async_reads); | 209 return new URLRequestJobTrackerTestJob(request, g_async_reads); |
209 } | 210 } |
210 | 211 |
211 // static | 212 // static |
212 bool URLRequestJobTrackerTest::g_async_reads = true; | 213 bool URLRequestJobTrackerTest::g_async_reads = true; |
213 | 214 |
214 TEST_F(URLRequestJobTrackerTest, BasicAsync) { | 215 TEST_F(URLRequestJobTrackerTest, BasicAsync) { |
215 g_async_reads = true; | 216 g_async_reads = true; |
216 AssertJobTrackerCallbacks("test:basic"); | 217 AssertJobTrackerCallbacks("test:basic"); |
217 } | 218 } |
218 | 219 |
219 TEST_F(URLRequestJobTrackerTest, BasicSync) { | 220 TEST_F(URLRequestJobTrackerTest, BasicSync) { |
220 g_async_reads = false; | 221 g_async_reads = false; |
221 AssertJobTrackerCallbacks("test:basic"); | 222 AssertJobTrackerCallbacks("test:basic"); |
222 } | 223 } |
223 | 224 |
224 TEST_F(URLRequestJobTrackerTest, CompressedAsync) { | 225 TEST_F(URLRequestJobTrackerTest, CompressedAsync) { |
225 g_async_reads = true; | 226 g_async_reads = true; |
226 AssertJobTrackerCallbacks("test:compressed"); | 227 AssertJobTrackerCallbacks("test:compressed"); |
227 } | 228 } |
228 | 229 |
229 TEST_F(URLRequestJobTrackerTest, CompressedSync) { | 230 TEST_F(URLRequestJobTrackerTest, CompressedSync) { |
230 g_async_reads = false; | 231 g_async_reads = false; |
231 AssertJobTrackerCallbacks("test:compressed"); | 232 AssertJobTrackerCallbacks("test:compressed"); |
232 } | 233 } |
233 | 234 |
234 } // namespace | 235 } // namespace |
236 } // namespace net | |
OLD | NEW |