Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / quota / quota_reservation_manager_unittest.cc
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.
4
5 #include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/file_util.h"
10 #include "base/files/file.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webkit/browser/fileapi/quota/open_file_handle.h"
16 #include "webkit/browser/fileapi/quota/quota_reservation.h"
17
18 using fileapi::FileSystemType;
19 using fileapi::kFileSystemTypeTemporary;
20 using fileapi::OpenFileHandle;
21 using fileapi::QuotaReservation;
22 using fileapi::QuotaReservationManager;
23
24 namespace content {
25
26 namespace {
27
28 const char kOrigin[] = "http://example.com";
29 const FileSystemType kType = kFileSystemTypeTemporary;
30 const int64 kInitialFileSize = 1;
31
32 typedef QuotaReservationManager::ReserveQuotaCallback ReserveQuotaCallback;
33
34 int64 GetFileSize(const base::FilePath& path) {
35   int64 size = 0;
36   base::GetFileSize(path, &size);
37   return size;
38 }
39
40 void SetFileSize(const base::FilePath& path, int64 size) {
41   base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE);
42   ASSERT_TRUE(file.IsValid());
43   ASSERT_TRUE(file.SetLength(size));
44 }
45
46 class FakeBackend : public QuotaReservationManager::QuotaBackend {
47  public:
48   FakeBackend()
49       : on_memory_usage_(kInitialFileSize),
50         on_disk_usage_(kInitialFileSize) {}
51   virtual ~FakeBackend() {}
52
53   virtual void ReserveQuota(const GURL& origin,
54                             FileSystemType type,
55                             int64 delta,
56                             const ReserveQuotaCallback& callback) OVERRIDE {
57     EXPECT_EQ(GURL(kOrigin), origin);
58     EXPECT_EQ(kType, type);
59     on_memory_usage_ += delta;
60     base::MessageLoopProxy::current()->PostTask(
61         FROM_HERE,
62         base::Bind(base::IgnoreResult(callback), base::File::FILE_OK, delta));
63   }
64
65   virtual void ReleaseReservedQuota(const GURL& origin,
66                                     FileSystemType type,
67                                     int64 size) OVERRIDE {
68     EXPECT_LE(0, size);
69     EXPECT_EQ(GURL(kOrigin), origin);
70     EXPECT_EQ(kType, type);
71     on_memory_usage_ -= size;
72   }
73
74   virtual void CommitQuotaUsage(const GURL& origin,
75                                 FileSystemType type,
76                                 int64 delta) OVERRIDE {
77     EXPECT_EQ(GURL(kOrigin), origin);
78     EXPECT_EQ(kType, type);
79     on_disk_usage_ += delta;
80     on_memory_usage_ += delta;
81   }
82
83   virtual void IncrementDirtyCount(const GURL& origin,
84                                    FileSystemType type) OVERRIDE {}
85   virtual void DecrementDirtyCount(const GURL& origin,
86                                    FileSystemType type) OVERRIDE {}
87
88   int64 on_memory_usage() { return on_memory_usage_; }
89   int64 on_disk_usage() { return on_disk_usage_; }
90
91  private:
92   int64 on_memory_usage_;
93   int64 on_disk_usage_;
94
95   DISALLOW_COPY_AND_ASSIGN(FakeBackend);
96 };
97
98 class FakeWriter {
99  public:
100   explicit FakeWriter(scoped_ptr<OpenFileHandle> handle)
101       : handle_(handle.Pass()),
102         path_(handle_->platform_path()),
103         max_written_offset_(handle_->GetEstimatedFileSize()),
104         append_mode_write_amount_(0),
105         dirty_(false) {
106   }
107
108   ~FakeWriter() {
109     if (handle_)
110       EXPECT_FALSE(dirty_);
111   }
112
113   int64 Truncate(int64 length) {
114     int64 consumed = 0;
115
116     if (max_written_offset_ < length) {
117       consumed = length - max_written_offset_;
118       max_written_offset_ = length;
119     }
120     SetFileSize(path_, length);
121     return consumed;
122   }
123
124   int64 Write(int64 max_offset) {
125     dirty_ = true;
126
127     int64 consumed = 0;
128     if (max_written_offset_ < max_offset) {
129       consumed = max_offset - max_written_offset_;
130       max_written_offset_ = max_offset;
131     }
132     if (GetFileSize(path_) < max_offset)
133       SetFileSize(path_, max_offset);
134     return consumed;
135   }
136
137   int64 Append(int64 amount) {
138     dirty_ = true;
139     append_mode_write_amount_ += amount;
140     SetFileSize(path_, GetFileSize(path_) + amount);
141     return amount;
142   }
143
144   void ReportUsage() {
145     handle_->UpdateMaxWrittenOffset(max_written_offset_);
146     handle_->AddAppendModeWriteAmount(append_mode_write_amount_);
147     max_written_offset_ = handle_->GetEstimatedFileSize();
148     append_mode_write_amount_ = 0;
149     dirty_ = false;
150   }
151
152   void ClearWithoutUsageReport() {
153     handle_.reset();
154   }
155
156  private:
157   scoped_ptr<OpenFileHandle> handle_;
158   base::FilePath path_;
159   int64 max_written_offset_;
160   int64 append_mode_write_amount_;
161   bool dirty_;
162 };
163
164 void ExpectSuccess(bool* done, base::File::Error error) {
165   EXPECT_FALSE(*done);
166   *done = true;
167   EXPECT_EQ(base::File::FILE_OK, error);
168 }
169
170 void RefreshReservation(QuotaReservation* reservation, int64 size) {
171   DCHECK(reservation);
172
173   bool done = false;
174   reservation->RefreshReservation(size, base::Bind(&ExpectSuccess, &done));
175   base::RunLoop().RunUntilIdle();
176   EXPECT_TRUE(done);
177 }
178
179 }  // namespace
180
181 class QuotaReservationManagerTest : public testing::Test {
182  public:
183   QuotaReservationManagerTest() {}
184   virtual ~QuotaReservationManagerTest() {}
185
186   virtual void SetUp() OVERRIDE {
187     ASSERT_TRUE(work_dir_.CreateUniqueTempDir());
188     file_path_ = work_dir_.path().Append(FILE_PATH_LITERAL("hoge"));
189     SetFileSize(file_path_, kInitialFileSize);
190
191     scoped_ptr<QuotaReservationManager::QuotaBackend> backend(new FakeBackend);
192     reservation_manager_.reset(new QuotaReservationManager(backend.Pass()));
193   }
194
195   virtual void TearDown() OVERRIDE {
196     reservation_manager_.reset();
197   }
198
199   FakeBackend* fake_backend() {
200     return static_cast<FakeBackend*>(reservation_manager_->backend_.get());
201   }
202
203   QuotaReservationManager* reservation_manager() {
204     return reservation_manager_.get();
205   }
206
207   const base::FilePath& file_path() const {
208     return file_path_;
209   }
210
211  private:
212   base::MessageLoop message_loop_;
213   base::ScopedTempDir work_dir_;
214   base::FilePath file_path_;
215   scoped_ptr<QuotaReservationManager> reservation_manager_;
216
217   DISALLOW_COPY_AND_ASSIGN(QuotaReservationManagerTest);
218 };
219
220 TEST_F(QuotaReservationManagerTest, BasicTest) {
221   scoped_refptr<QuotaReservation> reservation =
222       reservation_manager()->CreateReservation(GURL(kOrigin), kType);
223
224   {
225     RefreshReservation(reservation.get(), 10 + 20 + 3);
226     int64 cached_reserved_quota = reservation->remaining_quota();
227     FakeWriter writer(reservation->GetOpenFileHandle(file_path()));
228
229     cached_reserved_quota -= writer.Write(kInitialFileSize + 10);
230     EXPECT_LE(0, cached_reserved_quota);
231     cached_reserved_quota -= writer.Append(20);
232     EXPECT_LE(0, cached_reserved_quota);
233
234     writer.ReportUsage();
235   }
236
237   EXPECT_EQ(3, reservation->remaining_quota());
238   EXPECT_EQ(kInitialFileSize + 10 + 20, GetFileSize(file_path()));
239   EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_disk_usage());
240   EXPECT_EQ(kInitialFileSize + 10 + 20 + 3, fake_backend()->on_memory_usage());
241
242   {
243     RefreshReservation(reservation.get(), 5);
244     FakeWriter writer(reservation->GetOpenFileHandle(file_path()));
245
246     EXPECT_EQ(0, writer.Truncate(3));
247
248     writer.ReportUsage();
249   }
250
251   EXPECT_EQ(5, reservation->remaining_quota());
252   EXPECT_EQ(3, GetFileSize(file_path()));
253   EXPECT_EQ(3, fake_backend()->on_disk_usage());
254   EXPECT_EQ(3 + 5, fake_backend()->on_memory_usage());
255
256   reservation = NULL;
257
258   EXPECT_EQ(3, fake_backend()->on_memory_usage());
259 }
260
261 TEST_F(QuotaReservationManagerTest, MultipleWriter) {
262   scoped_refptr<QuotaReservation> reservation =
263       reservation_manager()->CreateReservation(GURL(kOrigin), kType);
264
265   {
266     RefreshReservation(reservation.get(), 10 + 20 + 30 + 40 + 5);
267     int64 cached_reserved_quota = reservation->remaining_quota();
268     FakeWriter writer1(reservation->GetOpenFileHandle(file_path()));
269     FakeWriter writer2(reservation->GetOpenFileHandle(file_path()));
270     FakeWriter writer3(reservation->GetOpenFileHandle(file_path()));
271
272     cached_reserved_quota -= writer1.Write(kInitialFileSize + 10);
273     EXPECT_LE(0, cached_reserved_quota);
274     cached_reserved_quota -= writer2.Write(kInitialFileSize + 20);
275     cached_reserved_quota -= writer3.Append(30);
276     EXPECT_LE(0, cached_reserved_quota);
277     cached_reserved_quota -= writer3.Append(40);
278     EXPECT_LE(0, cached_reserved_quota);
279
280     writer1.ReportUsage();
281     writer2.ReportUsage();
282     writer3.ReportUsage();
283   }
284
285   EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, GetFileSize(file_path()));
286   EXPECT_EQ(kInitialFileSize + 10 + 20 + 30 + 40 + 5,
287             fake_backend()->on_memory_usage());
288   EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, fake_backend()->on_disk_usage());
289
290   reservation = NULL;
291
292   EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, fake_backend()->on_disk_usage());
293 }
294
295 TEST_F(QuotaReservationManagerTest, MultipleClient) {
296   scoped_refptr<QuotaReservation> reservation1 =
297       reservation_manager()->CreateReservation(GURL(kOrigin), kType);
298   RefreshReservation(reservation1, 10);
299   int64 cached_reserved_quota1 = reservation1->remaining_quota();
300
301   scoped_refptr<QuotaReservation> reservation2 =
302       reservation_manager()->CreateReservation(GURL(kOrigin), kType);
303   RefreshReservation(reservation2, 20);
304   int64 cached_reserved_quota2 = reservation2->remaining_quota();
305
306   scoped_ptr<FakeWriter> writer1(
307       new FakeWriter(reservation1->GetOpenFileHandle(file_path())));
308
309   scoped_ptr<FakeWriter> writer2(
310       new FakeWriter(reservation2->GetOpenFileHandle(file_path())));
311
312   cached_reserved_quota1 -= writer1->Write(kInitialFileSize + 10);
313   EXPECT_LE(0, cached_reserved_quota1);
314
315   cached_reserved_quota2 -= writer2->Append(20);
316   EXPECT_LE(0, cached_reserved_quota2);
317
318   writer1->ReportUsage();
319   RefreshReservation(reservation1.get(), 2);
320   cached_reserved_quota1 = reservation1->remaining_quota();
321
322   writer2->ReportUsage();
323   RefreshReservation(reservation2.get(), 3);
324   cached_reserved_quota2 = reservation2->remaining_quota();
325
326   writer1.reset();
327   writer2.reset();
328
329   EXPECT_EQ(kInitialFileSize + 10 + 20, GetFileSize(file_path()));
330   EXPECT_EQ(kInitialFileSize + 10 + 20 + 2 + 3,
331             fake_backend()->on_memory_usage());
332   EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_disk_usage());
333
334   reservation1 = NULL;
335   EXPECT_EQ(kInitialFileSize + 10 + 20 + 3, fake_backend()->on_memory_usage());
336
337   reservation2 = NULL;
338   EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_memory_usage());
339 }
340
341 TEST_F(QuotaReservationManagerTest, ClientCrash) {
342   scoped_refptr<QuotaReservation> reservation1 =
343       reservation_manager()->CreateReservation(GURL(kOrigin), kType);
344   RefreshReservation(reservation1.get(), 15);
345
346   scoped_refptr<QuotaReservation> reservation2 =
347       reservation_manager()->CreateReservation(GURL(kOrigin), kType);
348   RefreshReservation(reservation2.get(), 20);
349
350   {
351     FakeWriter writer(reservation1->GetOpenFileHandle(file_path()));
352
353     writer.Write(kInitialFileSize + 10);
354
355     reservation1->OnClientCrash();
356     writer.ClearWithoutUsageReport();
357   }
358   reservation1 = NULL;
359
360   EXPECT_EQ(kInitialFileSize + 10, GetFileSize(file_path()));
361   EXPECT_EQ(kInitialFileSize + 15 + 20, fake_backend()->on_memory_usage());
362   EXPECT_EQ(kInitialFileSize + 10, fake_backend()->on_disk_usage());
363
364   reservation2 = NULL;
365   EXPECT_EQ(kInitialFileSize + 10, fake_backend()->on_memory_usage());
366 }
367
368 }  // namespace content