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