[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / fileapi / local_file_stream_reader_unittest.cc
blobfefd996095ba521ee18e83f158e52c90cbcce8c1
1 // Copyright 2014 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.
5 #include "storage/browser/fileapi/local_file_stream_reader.h"
7 #include <string>
9 #include "base/files/file.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/location.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/run_loop.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/threading/thread.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/test_completion_callback.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using storage::LocalFileStreamReader;
25 namespace content {
27 namespace {
29 const char kTestData[] = "0123456789";
30 const int kTestDataSize = arraysize(kTestData) - 1;
32 void ReadFromReader(LocalFileStreamReader* reader,
33 std::string* data, size_t size,
34 int* result) {
35 ASSERT_TRUE(reader != NULL);
36 ASSERT_TRUE(result != NULL);
37 *result = net::OK;
38 net::TestCompletionCallback callback;
39 size_t total_bytes_read = 0;
40 while (total_bytes_read < size) {
41 scoped_refptr<net::IOBufferWithSize> buf(
42 new net::IOBufferWithSize(size - total_bytes_read));
43 int rv = reader->Read(buf.get(), buf->size(), callback.callback());
44 if (rv == net::ERR_IO_PENDING)
45 rv = callback.WaitForResult();
46 if (rv < 0)
47 *result = rv;
48 if (rv <= 0)
49 break;
50 total_bytes_read += rv;
51 data->append(buf->data(), rv);
55 void NeverCalled(int) { ADD_FAILURE(); }
56 void EmptyCallback() {}
58 void QuitLoop() {
59 base::MessageLoop::current()->Quit();
62 } // namespace
64 class LocalFileStreamReaderTest : public testing::Test {
65 public:
66 LocalFileStreamReaderTest()
67 : file_thread_("FileUtilProxyTestFileThread") {}
69 void SetUp() override {
70 ASSERT_TRUE(file_thread_.Start());
71 ASSERT_TRUE(dir_.CreateUniqueTempDir());
73 base::WriteFile(test_path(), kTestData, kTestDataSize);
74 base::File::Info info;
75 ASSERT_TRUE(base::GetFileInfo(test_path(), &info));
76 test_file_modification_time_ = info.last_modified;
79 void TearDown() override {
80 // Give another chance for deleted streams to perform Close.
81 base::RunLoop().RunUntilIdle();
82 file_thread_.Stop();
83 base::RunLoop().RunUntilIdle();
86 protected:
87 LocalFileStreamReader* CreateFileReader(
88 const base::FilePath& path,
89 int64 initial_offset,
90 const base::Time& expected_modification_time) {
91 return new LocalFileStreamReader(
92 file_task_runner(),
93 path,
94 initial_offset,
95 expected_modification_time);
98 void TouchTestFile(base::TimeDelta delta) {
99 base::Time new_modified_time = test_file_modification_time() + delta;
100 ASSERT_TRUE(base::TouchFile(test_path(),
101 test_file_modification_time(),
102 new_modified_time));
105 base::SingleThreadTaskRunner* file_task_runner() const {
106 return file_thread_.task_runner().get();
109 base::FilePath test_dir() const { return dir_.path(); }
110 base::FilePath test_path() const { return dir_.path().AppendASCII("test"); }
111 base::Time test_file_modification_time() const {
112 return test_file_modification_time_;
115 void EnsureFileTaskFinished() {
116 file_task_runner()->PostTaskAndReply(
117 FROM_HERE, base::Bind(&EmptyCallback), base::Bind(&QuitLoop));
118 base::MessageLoop::current()->Run();
121 private:
122 base::MessageLoopForIO message_loop_;
123 base::Thread file_thread_;
124 base::ScopedTempDir dir_;
125 base::Time test_file_modification_time_;
128 TEST_F(LocalFileStreamReaderTest, NonExistent) {
129 base::FilePath nonexistent_path = test_dir().AppendASCII("nonexistent");
130 scoped_ptr<LocalFileStreamReader> reader(
131 CreateFileReader(nonexistent_path, 0, base::Time()));
132 int result = 0;
133 std::string data;
134 ReadFromReader(reader.get(), &data, 10, &result);
135 ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
136 ASSERT_EQ(0U, data.size());
139 TEST_F(LocalFileStreamReaderTest, Empty) {
140 base::FilePath empty_path = test_dir().AppendASCII("empty");
141 base::File file(empty_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
142 ASSERT_TRUE(file.IsValid());
143 file.Close();
145 scoped_ptr<LocalFileStreamReader> reader(
146 CreateFileReader(empty_path, 0, base::Time()));
147 int result = 0;
148 std::string data;
149 ReadFromReader(reader.get(), &data, 10, &result);
150 ASSERT_EQ(net::OK, result);
151 ASSERT_EQ(0U, data.size());
153 net::TestInt64CompletionCallback callback;
154 int64 length_result = reader->GetLength(callback.callback());
155 if (length_result == net::ERR_IO_PENDING)
156 length_result = callback.WaitForResult();
157 ASSERT_EQ(0, result);
160 TEST_F(LocalFileStreamReaderTest, GetLengthNormal) {
161 scoped_ptr<LocalFileStreamReader> reader(
162 CreateFileReader(test_path(), 0, test_file_modification_time()));
163 net::TestInt64CompletionCallback callback;
164 int64 result = reader->GetLength(callback.callback());
165 if (result == net::ERR_IO_PENDING)
166 result = callback.WaitForResult();
167 ASSERT_EQ(kTestDataSize, result);
170 TEST_F(LocalFileStreamReaderTest, GetLengthAfterModified) {
171 // Touch file so that the file's modification time becomes different
172 // from what we expect.
173 TouchTestFile(base::TimeDelta::FromSeconds(-1));
175 scoped_ptr<LocalFileStreamReader> reader(
176 CreateFileReader(test_path(), 0, test_file_modification_time()));
177 net::TestInt64CompletionCallback callback;
178 int64 result = reader->GetLength(callback.callback());
179 if (result == net::ERR_IO_PENDING)
180 result = callback.WaitForResult();
181 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
183 // With NULL expected modification time this should work.
184 reader.reset(CreateFileReader(test_path(), 0, base::Time()));
185 result = reader->GetLength(callback.callback());
186 if (result == net::ERR_IO_PENDING)
187 result = callback.WaitForResult();
188 ASSERT_EQ(kTestDataSize, result);
191 TEST_F(LocalFileStreamReaderTest, GetLengthWithOffset) {
192 scoped_ptr<LocalFileStreamReader> reader(
193 CreateFileReader(test_path(), 3, base::Time()));
194 net::TestInt64CompletionCallback callback;
195 int64 result = reader->GetLength(callback.callback());
196 if (result == net::ERR_IO_PENDING)
197 result = callback.WaitForResult();
198 // Initial offset does not affect the result of GetLength.
199 ASSERT_EQ(kTestDataSize, result);
202 TEST_F(LocalFileStreamReaderTest, ReadNormal) {
203 scoped_ptr<LocalFileStreamReader> reader(
204 CreateFileReader(test_path(), 0, test_file_modification_time()));
205 int result = 0;
206 std::string data;
207 ReadFromReader(reader.get(), &data, kTestDataSize, &result);
208 ASSERT_EQ(net::OK, result);
209 ASSERT_EQ(kTestData, data);
212 TEST_F(LocalFileStreamReaderTest, ReadAfterModified) {
213 // Touch file so that the file's modification time becomes different
214 // from what we expect. Note that the resolution on some filesystems
215 // is 1s so we can't test with deltas less than that.
216 TouchTestFile(base::TimeDelta::FromSeconds(-1));
217 scoped_ptr<LocalFileStreamReader> reader(
218 CreateFileReader(test_path(), 0, test_file_modification_time()));
219 int result = 0;
220 std::string data;
221 ReadFromReader(reader.get(), &data, kTestDataSize, &result);
222 EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
223 EXPECT_EQ(0U, data.size());
225 // Due to precision loss converting int64->double->int64 (e.g. through
226 // Blink) the expected/actual time may vary by microseconds. With
227 // modification time delta < 10us this should work.
228 TouchTestFile(base::TimeDelta::FromMicroseconds(1));
229 data.clear();
230 reader.reset(CreateFileReader(test_path(), 0, test_file_modification_time()));
231 ReadFromReader(reader.get(), &data, kTestDataSize, &result);
232 EXPECT_EQ(net::OK, result);
233 EXPECT_EQ(kTestData, data);
235 // With matching modification times time this should work.
236 TouchTestFile(base::TimeDelta());
237 data.clear();
238 reader.reset(CreateFileReader(test_path(), 0, test_file_modification_time()));
239 ReadFromReader(reader.get(), &data, kTestDataSize, &result);
240 EXPECT_EQ(net::OK, result);
241 EXPECT_EQ(kTestData, data);
243 // And with NULL expected modification time this should work.
244 data.clear();
245 reader.reset(CreateFileReader(test_path(), 0, base::Time()));
246 ReadFromReader(reader.get(), &data, kTestDataSize, &result);
247 EXPECT_EQ(net::OK, result);
248 EXPECT_EQ(kTestData, data);
251 TEST_F(LocalFileStreamReaderTest, ReadWithOffset) {
252 scoped_ptr<LocalFileStreamReader> reader(
253 CreateFileReader(test_path(), 3, base::Time()));
254 int result = 0;
255 std::string data;
256 ReadFromReader(reader.get(), &data, kTestDataSize, &result);
257 ASSERT_EQ(net::OK, result);
258 ASSERT_EQ(&kTestData[3], data);
261 TEST_F(LocalFileStreamReaderTest, DeleteWithUnfinishedRead) {
262 scoped_ptr<LocalFileStreamReader> reader(
263 CreateFileReader(test_path(), 0, base::Time()));
265 net::TestCompletionCallback callback;
266 scoped_refptr<net::IOBufferWithSize> buf(
267 new net::IOBufferWithSize(kTestDataSize));
268 int rv = reader->Read(buf.get(), buf->size(), base::Bind(&NeverCalled));
269 ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
271 // Delete immediately.
272 // Should not crash; nor should NeverCalled be callback.
273 reader.reset();
274 EnsureFileTaskFinished();
277 } // namespace content