blob: 794d15c1faadf59111330a0eb34446c8a5305e22 [file] [log] [blame]
Benjamin Lerman5d429aa2015-05-07 16:21:00 +02001// Copyright 2015 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 "base/files/file_util.h"
6#include "base/rand_util.h"
7#include "base/run_loop.h"
8#include "base/strings/stringprintf.h"
9#include "mojo/public/cpp/application/application_impl.h"
10#include "mojo/public/cpp/application/application_test_base.h"
11#include "mojo/public/cpp/system/data_pipe.h"
Viet-Trung Luu2e11a3f2015-10-13 13:20:30 -070012#include "mojo/services/network/interfaces/url_loader.mojom.h"
Viet-Trung Luu0f4f3ba2015-10-10 01:08:40 -070013#include "mojo/services/url_response_disk_cache/interfaces/url_response_disk_cache.mojom.h"
Benjamin Lerman5d429aa2015-05-07 16:21:00 +020014#include "services/url_response_disk_cache/kTestData.h"
15
16namespace mojo {
17
18namespace {
19
20class URLResponseDiskCacheAppTest : public mojo::test::ApplicationTestBase {
21 public:
22 URLResponseDiskCacheAppTest() : ApplicationTestBase() {}
23 ~URLResponseDiskCacheAppTest() override {}
24
25 void SetUp() override {
26 mojo::test::ApplicationTestBase::SetUp();
27 application_impl()->ConnectToService("mojo:url_response_disk_cache",
28 &url_response_disk_cache_);
29 }
30
31 protected:
32 URLResponseDiskCachePtr url_response_disk_cache_;
33
34 DISALLOW_COPY_AND_ASSIGN(URLResponseDiskCacheAppTest);
35};
36
37base::FilePath toPath(Array<uint8_t> path) {
38 if (path.is_null()) {
39 return base::FilePath();
40 }
41 return base::FilePath(
42 std::string(reinterpret_cast<char*>(&path.front()), path.size()));
43}
44
James Robinsond4709742015-05-27 13:24:56 -070045HttpHeaderPtr RandomEtagHeader() {
46 auto etag_header = HttpHeader::New();
47 etag_header->name = "ETag";
48 etag_header->value = base::StringPrintf("%f", base::RandDouble());
49 return etag_header;
50}
51
Benjamin Lerman5d429aa2015-05-07 16:21:00 +020052} // namespace
53
Benjamin Lermand15e3f42015-09-17 11:26:18 +020054TEST_F(URLResponseDiskCacheAppTest, BaseCache) {
55 const std::string url = "http://www.example.com/1";
56
57 url_response_disk_cache_->Get(
58 url, [](URLResponsePtr url_response, Array<uint8_t> received_file_path,
59 Array<uint8_t> received_cache_dir_path) {
60 EXPECT_FALSE(url_response);
61 });
62 url_response_disk_cache_.WaitForIncomingResponse();
63
64 URLResponsePtr url_response = mojo::URLResponse::New();
65 url_response->url = "http://www.example.com/1";
66 url_response->headers.push_back(RandomEtagHeader());
67 DataPipe pipe;
68 std::string content = base::RandBytesAsString(32);
69 uint32_t num_bytes = content.size();
70 ASSERT_EQ(MOJO_RESULT_OK,
71 WriteDataRaw(pipe.producer_handle.get(), content.c_str(),
72 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
73 ASSERT_EQ(content.size(), num_bytes);
74 pipe.producer_handle.reset();
75 url_response->body = pipe.consumer_handle.Pass();
76
77 url_response_disk_cache_->Update(url_response.Pass());
78
79 base::FilePath file;
80 base::FilePath cache_dir;
81
82 // Wait up to 1 second for the cache to be updated.
83 base::Time start = base::Time::Now();
84 while (file.empty() &&
85 ((base::Time::Now() - start) < base::TimeDelta::FromSeconds(1))) {
86 url_response_disk_cache_->Get(
87 url, [&url_response, &file, &cache_dir](
88 URLResponsePtr response, Array<uint8_t> received_file_path,
89 Array<uint8_t> received_cache_dir_path) {
90 url_response = response.Pass();
91 file = toPath(received_file_path.Pass());
92 cache_dir = toPath(received_cache_dir_path.Pass());
93 });
94 url_response_disk_cache_.WaitForIncomingResponse();
95 }
96
97 EXPECT_TRUE(url_response);
98 EXPECT_FALSE(file.empty());
99 EXPECT_EQ(url, url_response->url);
100 std::string received_content;
101 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
102 EXPECT_EQ(content, received_content);
103}
104
105TEST_F(URLResponseDiskCacheAppTest, UpdateAndGet) {
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200106 URLResponsePtr url_response = mojo::URLResponse::New();
107 url_response->url = "http://www.example.com/1";
James Robinsond4709742015-05-27 13:24:56 -0700108 url_response->headers.push_back(RandomEtagHeader());
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200109 DataPipe pipe;
110 std::string content = base::RandBytesAsString(32);
111 uint32_t num_bytes = content.size();
112 ASSERT_EQ(MOJO_RESULT_OK,
113 WriteDataRaw(pipe.producer_handle.get(), content.c_str(),
114 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
115 ASSERT_EQ(content.size(), num_bytes);
116 pipe.producer_handle.reset();
117 url_response->body = pipe.consumer_handle.Pass();
118 base::FilePath file;
119 base::FilePath cache_dir;
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200120 url_response_disk_cache_->UpdateAndGet(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200121 url_response.Pass(),
122 [&file, &cache_dir](Array<uint8_t> received_file_path,
123 Array<uint8_t> received_cache_dir_path) {
124 file = toPath(received_file_path.Pass());
125 cache_dir = toPath(received_cache_dir_path.Pass());
126 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700127 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200128 ASSERT_FALSE(file.empty());
129 std::string received_content;
130 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
131 EXPECT_EQ(content, received_content);
132}
133
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200134TEST_F(URLResponseDiskCacheAppTest, UpdateAndGetExtracted) {
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200135 URLResponsePtr url_response = mojo::URLResponse::New();
136 url_response->url = "http://www.example.com/2";
James Robinsond4709742015-05-27 13:24:56 -0700137 url_response->headers.push_back(RandomEtagHeader());
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200138 DataPipe pipe;
139 std::string content = base::RandBytesAsString(32);
140 uint32_t num_bytes = kTestData.size;
141 ASSERT_EQ(MOJO_RESULT_OK,
142 WriteDataRaw(pipe.producer_handle.get(), kTestData.data, &num_bytes,
143 MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
144 ASSERT_EQ(kTestData.size, num_bytes);
145 pipe.producer_handle.reset();
146 url_response->body = pipe.consumer_handle.Pass();
147 base::FilePath extracted_dir;
148 base::FilePath cache_dir;
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200149 url_response_disk_cache_->UpdateAndGetExtracted(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200150 url_response.Pass(),
151 [&extracted_dir, &cache_dir](Array<uint8_t> received_extracted_dir,
152 Array<uint8_t> received_cache_dir_path) {
153 extracted_dir = toPath(received_extracted_dir.Pass());
154 cache_dir = toPath(received_cache_dir_path.Pass());
155 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700156 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200157 ASSERT_FALSE(extracted_dir.empty());
158 base::FilePath file1 = extracted_dir.Append("file1");
159 std::string file_content;
160 ASSERT_TRUE(base::ReadFileToString(file1, &file_content));
161 EXPECT_EQ("hello\n", file_content);
162 base::FilePath file2 = extracted_dir.Append("file2");
163 ASSERT_TRUE(base::ReadFileToString(file2, &file_content));
164 EXPECT_EQ("world\n", file_content);
165}
166
167TEST_F(URLResponseDiskCacheAppTest, CacheTest) {
168 URLResponsePtr url_response = mojo::URLResponse::New();
169 url_response->url = "http://www.example.com/3";
James Robinsond4709742015-05-27 13:24:56 -0700170 std::string etag_value = base::StringPrintf("%f", base::RandDouble());
171 {
172 auto etag_header = HttpHeader::New();
173 etag_header->name = "ETag";
174 etag_header->value = etag_value;
175 url_response->headers.push_back(etag_header.Pass());
176 }
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200177 DataPipe pipe1;
178 std::string content = base::RandBytesAsString(32);
179 uint32_t num_bytes = content.size();
180 ASSERT_EQ(MOJO_RESULT_OK,
181 WriteDataRaw(pipe1.producer_handle.get(), content.c_str(),
182 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
183 ASSERT_EQ(content.size(), num_bytes);
184 pipe1.producer_handle.reset();
185 url_response->body = pipe1.consumer_handle.Pass();
186 base::FilePath file;
187 base::FilePath cache_dir;
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200188 url_response_disk_cache_->UpdateAndGet(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200189 url_response.Pass(),
190 [&file, &cache_dir](Array<uint8_t> received_file_path,
191 Array<uint8_t> received_cache_dir_path) {
192 file = toPath(received_file_path.Pass());
193 cache_dir = toPath(received_cache_dir_path.Pass());
194 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700195 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200196 ASSERT_FALSE(file.empty());
197 std::string received_content;
198 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
199 EXPECT_EQ(content, received_content);
200 base::FilePath saved_file = cache_dir.Append("file");
201 EXPECT_FALSE(base::PathExists(saved_file));
202 std::string cached_content = base::RandBytesAsString(32);
203 ASSERT_TRUE(base::WriteFile(saved_file, cached_content.data(),
204 cached_content.size()));
205
206 // Request using a response for the same URL, with the same etag, but a
207 // different content. The cached value should be returned.
208 url_response = mojo::URLResponse::New();
209 url_response->url = "http://www.example.com/3";
James Robinsond4709742015-05-27 13:24:56 -0700210 {
211 auto etag_header = HttpHeader::New();
212 etag_header->name = "ETag";
213 etag_header->value = etag_value;
214 url_response->headers.push_back(etag_header.Pass());
215 }
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200216 DataPipe pipe2;
217 std::string new_content = base::RandBytesAsString(32);
218 num_bytes = new_content.size();
219 ASSERT_EQ(MOJO_RESULT_OK,
220 WriteDataRaw(pipe2.producer_handle.get(), new_content.c_str(),
221 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
222 ASSERT_EQ(new_content.size(), num_bytes);
223 pipe2.producer_handle.reset();
224 url_response->body = pipe2.consumer_handle.Pass();
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200225 url_response_disk_cache_->UpdateAndGet(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200226 url_response.Pass(),
227 [&file, &cache_dir](Array<uint8_t> received_file_path,
228 Array<uint8_t> received_cache_dir_path) {
229 file = toPath(received_file_path.Pass());
230 cache_dir = toPath(received_cache_dir_path.Pass());
231 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700232 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200233 ASSERT_FALSE(file.empty());
234 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
235 EXPECT_EQ(content, received_content);
236 saved_file = cache_dir.Append("file");
237 EXPECT_TRUE(base::PathExists(saved_file));
238 std::string received_cached_content;
239 ASSERT_TRUE(base::ReadFileToString(saved_file, &received_cached_content));
240 EXPECT_EQ(cached_content, received_cached_content);
241
242 // Request using a response for the same URL, with the a different etag. Check
243 // that the new content is returned, and the cached files is deleted.
244 url_response = mojo::URLResponse::New();
245 url_response->url = "http://www.example.com/3";
James Robinsond4709742015-05-27 13:24:56 -0700246 url_response->headers.push_back(RandomEtagHeader());
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200247 DataPipe pipe3;
248 new_content = base::RandBytesAsString(32);
249 num_bytes = new_content.size();
250 ASSERT_EQ(MOJO_RESULT_OK,
251 WriteDataRaw(pipe3.producer_handle.get(), new_content.c_str(),
252 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
253 ASSERT_EQ(new_content.size(), num_bytes);
254 pipe3.producer_handle.reset();
255 url_response->body = pipe3.consumer_handle.Pass();
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200256 url_response_disk_cache_->UpdateAndGet(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200257 url_response.Pass(),
258 [&file, &cache_dir](Array<uint8_t> received_file_path,
259 Array<uint8_t> received_cache_dir_path) {
260 file = toPath(received_file_path.Pass());
261 cache_dir = toPath(received_cache_dir_path.Pass());
262 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700263 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200264 ASSERT_FALSE(file.empty());
265 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
266 EXPECT_EQ(new_content, received_content);
267 saved_file = cache_dir.Append("file");
268 EXPECT_FALSE(base::PathExists(saved_file));
269 ASSERT_TRUE(base::WriteFile(saved_file, cached_content.data(),
270 cached_content.size()));
271
272 // Request using a response without an etag header. Check that the new
273 // content is returned, and the cached files is deleted.
274 url_response = mojo::URLResponse::New();
275 url_response->url = "http://www.example.com/3";
276 DataPipe pipe4;
277 new_content = base::RandBytesAsString(32);
278 num_bytes = new_content.size();
279 ASSERT_EQ(MOJO_RESULT_OK,
280 WriteDataRaw(pipe4.producer_handle.get(), new_content.c_str(),
281 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
282 ASSERT_EQ(new_content.size(), num_bytes);
283 pipe4.producer_handle.reset();
284 url_response->body = pipe4.consumer_handle.Pass();
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200285 url_response_disk_cache_->UpdateAndGet(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200286 url_response.Pass(),
287 [&file, &cache_dir](Array<uint8_t> received_file_path,
288 Array<uint8_t> received_cache_dir_path) {
289 file = toPath(received_file_path.Pass());
290 cache_dir = toPath(received_cache_dir_path.Pass());
291 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700292 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200293 ASSERT_FALSE(file.empty());
294 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
295 EXPECT_EQ(new_content, received_content);
296 saved_file = cache_dir.Append("file");
297 EXPECT_FALSE(base::PathExists(saved_file));
298 ASSERT_TRUE(base::WriteFile(saved_file, cached_content.data(),
299 cached_content.size()));
300
301 // Request using a response with an etag header while the cache version
302 // doesn't have one. Check that the new content is returned, and the cached
303 // files is deleted.
304 url_response = mojo::URLResponse::New();
305 url_response->url = "http://www.example.com/3";
306 DataPipe pipe5;
307 new_content = base::RandBytesAsString(32);
308 num_bytes = new_content.size();
309 ASSERT_EQ(MOJO_RESULT_OK,
310 WriteDataRaw(pipe5.producer_handle.get(), new_content.c_str(),
311 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
312 ASSERT_EQ(new_content.size(), num_bytes);
313 pipe5.producer_handle.reset();
314 url_response->body = pipe5.consumer_handle.Pass();
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200315 url_response_disk_cache_->UpdateAndGet(
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200316 url_response.Pass(),
317 [&file, &cache_dir](Array<uint8_t> received_file_path,
318 Array<uint8_t> received_cache_dir_path) {
319 file = toPath(received_file_path.Pass());
320 cache_dir = toPath(received_cache_dir_path.Pass());
321 });
Viet-Trung Luuc23bde82015-05-21 09:53:50 -0700322 url_response_disk_cache_.WaitForIncomingResponse();
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200323 ASSERT_FALSE(file.empty());
324 ASSERT_TRUE(base::ReadFileToString(file, &received_content));
325 EXPECT_EQ(new_content, received_content);
326 saved_file = cache_dir.Append("file");
327 EXPECT_FALSE(base::PathExists(saved_file));
328}
329
330} // namespace mojo