Home | History | Annotate | Download | only in fileapi
      1 // Copyright 2013 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 "content/child/fileapi/webfilewriter_base.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "third_party/WebKit/public/platform/WebFileError.h"
     13 #include "third_party/WebKit/public/platform/WebFileWriterClient.h"
     14 #include "third_party/WebKit/public/platform/WebURL.h"
     15 #include "url/gurl.h"
     16 
     17 namespace content {
     18 
     19 namespace {
     20 
     21 // We use particular offsets to trigger particular behaviors
     22 // in the TestableFileWriter.
     23 const int kNoOffset = -1;
     24 const int kBasicFileTruncate_Offset = 1;
     25 const int kErrorFileTruncate_Offset = 2;
     26 const int kCancelFileTruncate_Offset = 3;
     27 const int kCancelFailedTruncate_Offset = 4;
     28 const int kBasicFileWrite_Offset = 1;
     29 const int kErrorFileWrite_Offset = 2;
     30 const int kMultiFileWrite_Offset = 3;
     31 const int kCancelFileWriteBeforeCompletion_Offset = 4;
     32 const int kCancelFileWriteAfterCompletion_Offset = 5;
     33 
     34 GURL mock_path_as_gurl() {
     35   return GURL("MockPath");
     36 }
     37 
     38 }  // namespace
     39 
     40 class TestableFileWriter : public WebFileWriterBase {
     41  public:
     42   explicit TestableFileWriter(blink::WebFileWriterClient* client)
     43       : WebFileWriterBase(mock_path_as_gurl(), client) {
     44     reset();
     45   }
     46 
     47   void reset() {
     48     received_truncate_ = false;
     49     received_truncate_path_ = GURL();
     50     received_truncate_offset_ = kNoOffset;
     51     received_write_ = false;
     52     received_write_path_ = GURL();
     53     received_write_offset_ = kNoOffset;
     54     received_write_blob_uuid_ = std::string();
     55     received_cancel_ = false;
     56   }
     57 
     58   bool received_truncate_;
     59   GURL received_truncate_path_;
     60   int64 received_truncate_offset_;
     61   bool received_write_;
     62   GURL received_write_path_;
     63   std::string received_write_blob_uuid_;
     64   int64 received_write_offset_;
     65   bool received_cancel_;
     66 
     67  protected:
     68   virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE {
     69     received_truncate_ = true;
     70     received_truncate_path_ = path;
     71     received_truncate_offset_ = offset;
     72 
     73     if (offset == kBasicFileTruncate_Offset) {
     74       DidSucceed();
     75     } else if (offset == kErrorFileTruncate_Offset) {
     76       DidFail(base::File::FILE_ERROR_NOT_FOUND);
     77     } else if (offset == kCancelFileTruncate_Offset) {
     78       cancel();
     79       DidSucceed();  // truncate completion
     80       DidSucceed();  // cancel completion
     81     } else if (offset == kCancelFailedTruncate_Offset) {
     82       cancel();
     83       DidFail(base::File::FILE_ERROR_NOT_FOUND);  // truncate completion
     84       DidSucceed();  // cancel completion
     85     } else {
     86       FAIL();
     87     }
     88   }
     89 
     90   virtual void DoWrite(
     91         const GURL& path, const std::string& blob_uuid,
     92         int64 offset) OVERRIDE {
     93     received_write_ = true;
     94     received_write_path_ = path;
     95     received_write_offset_ = offset;
     96     received_write_blob_uuid_ = blob_uuid;
     97 
     98     if (offset == kBasicFileWrite_Offset) {
     99       DidWrite(1, true);
    100     } else if (offset == kErrorFileWrite_Offset) {
    101       DidFail(base::File::FILE_ERROR_NOT_FOUND);
    102     } else if (offset == kMultiFileWrite_Offset) {
    103       DidWrite(1, false);
    104       DidWrite(1, false);
    105       DidWrite(1, true);
    106     } else if (offset == kCancelFileWriteBeforeCompletion_Offset) {
    107       DidWrite(1, false);
    108       cancel();
    109       DidWrite(1, false);
    110       DidWrite(1, false);
    111       DidFail(base::File::FILE_ERROR_FAILED);  // write completion
    112       DidSucceed();  // cancel completion
    113     } else if (offset == kCancelFileWriteAfterCompletion_Offset) {
    114       DidWrite(1, false);
    115       cancel();
    116       DidWrite(1, false);
    117       DidWrite(1, false);
    118       DidWrite(1, true);  // write completion
    119       DidFail(base::File::FILE_ERROR_FAILED);  // cancel completion
    120     } else {
    121       FAIL();
    122     }
    123   }
    124 
    125   virtual void DoCancel() OVERRIDE {
    126     received_cancel_ = true;
    127   }
    128 };
    129 
    130 class FileWriterTest : public testing::Test,
    131                        public blink::WebFileWriterClient {
    132  public:
    133   FileWriterTest() {
    134     reset();
    135   }
    136 
    137   blink::WebFileWriter* writer() {
    138     return testable_writer_.get();
    139   }
    140 
    141   // WebFileWriterClient overrides
    142   virtual void didWrite(long long bytes, bool complete) {
    143     EXPECT_FALSE(received_did_write_complete_);
    144     ++received_did_write_count_;
    145     received_did_write_bytes_total_ += bytes;
    146     if (complete)
    147       received_did_write_complete_ = true;
    148 
    149     if (delete_in_client_callback_)
    150       testable_writer_.reset(NULL);
    151   }
    152 
    153   virtual void didTruncate() {
    154     EXPECT_FALSE(received_did_truncate_);
    155     received_did_truncate_ = true;
    156     if (delete_in_client_callback_)
    157       testable_writer_.reset(NULL);
    158   }
    159 
    160   virtual void didFail(blink::WebFileError error) {
    161     EXPECT_FALSE(received_did_fail_);
    162     received_did_fail_ = true;
    163     fail_error_received_ = error;
    164     if (delete_in_client_callback_)
    165       testable_writer_.reset(NULL);
    166   }
    167 
    168  protected:
    169   void reset() {
    170     testable_writer_.reset(new TestableFileWriter(this));
    171     delete_in_client_callback_ = false;
    172     received_did_write_count_ = 0;
    173     received_did_write_bytes_total_ = 0;
    174     received_did_write_complete_ = false;
    175     received_did_truncate_ = false;
    176     received_did_fail_ = false;
    177     fail_error_received_ = static_cast<blink::WebFileError>(0);
    178   }
    179 
    180   scoped_ptr<TestableFileWriter> testable_writer_;
    181   bool delete_in_client_callback_;
    182 
    183   // Observed WebFileWriterClient artifacts.
    184   int received_did_write_count_;
    185   long long received_did_write_bytes_total_;
    186   bool received_did_write_complete_;
    187   bool received_did_truncate_;
    188   bool received_did_fail_;
    189   blink::WebFileError fail_error_received_;
    190 
    191   DISALLOW_COPY_AND_ASSIGN(FileWriterTest);
    192 };
    193 
    194 TEST_F(FileWriterTest, BasicFileWrite) {
    195   // Call the webkit facing api.
    196   const std::string kBlobId("1234");
    197   writer()->write(kBasicFileWrite_Offset,
    198                   blink::WebString::fromUTF8(kBlobId));
    199 
    200   // Check that the derived class gets called correctly.
    201   EXPECT_TRUE(testable_writer_->received_write_);
    202   EXPECT_EQ(testable_writer_->received_write_path_,
    203             mock_path_as_gurl());
    204   EXPECT_EQ(kBasicFileWrite_Offset,
    205             testable_writer_->received_write_offset_);
    206   EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
    207   EXPECT_FALSE(testable_writer_->received_truncate_);
    208   EXPECT_FALSE(testable_writer_->received_cancel_);
    209 
    210   // Check that the client gets called correctly.
    211   EXPECT_EQ(1, received_did_write_count_);
    212   EXPECT_TRUE(received_did_write_complete_);
    213   EXPECT_EQ(1, received_did_write_bytes_total_);
    214   EXPECT_FALSE(received_did_truncate_);
    215   EXPECT_FALSE(received_did_fail_);
    216 }
    217 
    218 TEST_F(FileWriterTest, BasicFileTruncate) {
    219   // Call the webkit facing api.
    220   writer()->truncate(kBasicFileTruncate_Offset);
    221 
    222   // Check that the derived class gets called correctly.
    223   EXPECT_TRUE(testable_writer_->received_truncate_);
    224   EXPECT_EQ(mock_path_as_gurl(),
    225             testable_writer_->received_truncate_path_);
    226   EXPECT_EQ(kBasicFileTruncate_Offset,
    227             testable_writer_->received_truncate_offset_);
    228   EXPECT_FALSE(testable_writer_->received_write_);
    229   EXPECT_FALSE(testable_writer_->received_cancel_);
    230 
    231   // Check that the client gets called correctly.
    232   EXPECT_TRUE(received_did_truncate_);
    233   EXPECT_EQ(0, received_did_write_count_);
    234   EXPECT_FALSE(received_did_fail_);
    235 }
    236 
    237 TEST_F(FileWriterTest, ErrorFileWrite) {
    238   // Call the webkit facing api.
    239   const std::string kBlobId("1234");
    240   writer()->write(kErrorFileWrite_Offset,
    241                   blink::WebString::fromUTF8(kBlobId));
    242 
    243   // Check that the derived class gets called correctly.
    244   EXPECT_TRUE(testable_writer_->received_write_);
    245   EXPECT_EQ(testable_writer_->received_write_path_,
    246             mock_path_as_gurl());
    247   EXPECT_EQ(kErrorFileWrite_Offset,
    248             testable_writer_->received_write_offset_);
    249   EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
    250   EXPECT_FALSE(testable_writer_->received_truncate_);
    251   EXPECT_FALSE(testable_writer_->received_cancel_);
    252 
    253   // Check that the client gets called correctly.
    254   EXPECT_TRUE(received_did_fail_);
    255   EXPECT_EQ(blink::WebFileErrorNotFound, fail_error_received_);
    256   EXPECT_EQ(0, received_did_write_count_);
    257   EXPECT_FALSE(received_did_truncate_);
    258 }
    259 
    260 TEST_F(FileWriterTest, ErrorFileTruncate) {
    261   // Call the webkit facing api.
    262   writer()->truncate(kErrorFileTruncate_Offset);
    263 
    264   // Check that the derived class gets called correctly.
    265   EXPECT_TRUE(testable_writer_->received_truncate_);
    266   EXPECT_EQ(mock_path_as_gurl(),
    267             testable_writer_->received_truncate_path_);
    268   EXPECT_EQ(kErrorFileTruncate_Offset,
    269             testable_writer_->received_truncate_offset_);
    270   EXPECT_FALSE(testable_writer_->received_write_);
    271   EXPECT_FALSE(testable_writer_->received_cancel_);
    272 
    273   // Check that the client gets called correctly.
    274   EXPECT_TRUE(received_did_fail_);
    275   EXPECT_EQ(blink::WebFileErrorNotFound, fail_error_received_);
    276   EXPECT_FALSE(received_did_truncate_);
    277   EXPECT_EQ(0, received_did_write_count_);
    278 }
    279 
    280 TEST_F(FileWriterTest, MultiFileWrite) {
    281   // Call the webkit facing api.
    282   const std::string kBlobId("1234");
    283   writer()->write(kMultiFileWrite_Offset,
    284                   blink::WebString::fromUTF8(kBlobId));
    285 
    286   // Check that the derived class gets called correctly.
    287   EXPECT_TRUE(testable_writer_->received_write_);
    288   EXPECT_EQ(testable_writer_->received_write_path_,
    289             mock_path_as_gurl());
    290   EXPECT_EQ(kMultiFileWrite_Offset,
    291             testable_writer_->received_write_offset_);
    292   EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
    293   EXPECT_FALSE(testable_writer_->received_truncate_);
    294   EXPECT_FALSE(testable_writer_->received_cancel_);
    295 
    296   // Check that the client gets called correctly.
    297   EXPECT_EQ(3, received_did_write_count_);
    298   EXPECT_TRUE(received_did_write_complete_);
    299   EXPECT_EQ(3, received_did_write_bytes_total_);
    300   EXPECT_FALSE(received_did_truncate_);
    301   EXPECT_FALSE(received_did_fail_);
    302 }
    303 
    304 TEST_F(FileWriterTest, CancelFileWriteBeforeCompletion) {
    305   // Call the webkit facing api.
    306   const std::string kBlobId("1234");
    307   writer()->write(kCancelFileWriteBeforeCompletion_Offset,
    308                   blink::WebString::fromUTF8(kBlobId));
    309 
    310   // Check that the derived class gets called correctly.
    311   EXPECT_TRUE(testable_writer_->received_write_);
    312   EXPECT_EQ(testable_writer_->received_write_path_,
    313             mock_path_as_gurl());
    314   EXPECT_EQ(kCancelFileWriteBeforeCompletion_Offset,
    315             testable_writer_->received_write_offset_);
    316   EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
    317   EXPECT_TRUE(testable_writer_->received_cancel_);
    318   EXPECT_FALSE(testable_writer_->received_truncate_);
    319 
    320   // Check that the client gets called correctly.
    321   EXPECT_TRUE(received_did_fail_);
    322   EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
    323   EXPECT_EQ(1, received_did_write_count_);
    324   EXPECT_FALSE(received_did_write_complete_);
    325   EXPECT_EQ(1, received_did_write_bytes_total_);
    326   EXPECT_FALSE(received_did_truncate_);
    327 }
    328 
    329 TEST_F(FileWriterTest, CancelFileWriteAfterCompletion) {
    330   // Call the webkit facing api.
    331   const std::string kBlobId("1234");
    332   writer()->write(kCancelFileWriteAfterCompletion_Offset,
    333                   blink::WebString::fromUTF8(kBlobId));
    334 
    335   // Check that the derived class gets called correctly.
    336   EXPECT_TRUE(testable_writer_->received_write_);
    337   EXPECT_EQ(testable_writer_->received_write_path_,
    338             mock_path_as_gurl());
    339   EXPECT_EQ(kCancelFileWriteAfterCompletion_Offset,
    340             testable_writer_->received_write_offset_);
    341   EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_);
    342   EXPECT_TRUE(testable_writer_->received_cancel_);
    343   EXPECT_FALSE(testable_writer_->received_truncate_);
    344 
    345   // Check that the client gets called correctly.
    346   EXPECT_TRUE(received_did_fail_);
    347   EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
    348   EXPECT_EQ(1, received_did_write_count_);
    349   EXPECT_FALSE(received_did_write_complete_);
    350   EXPECT_EQ(1, received_did_write_bytes_total_);
    351   EXPECT_FALSE(received_did_truncate_);
    352 }
    353 
    354 TEST_F(FileWriterTest, CancelFileTruncate) {
    355   // Call the webkit facing api.
    356   writer()->truncate(kCancelFileTruncate_Offset);
    357 
    358   // Check that the derived class gets called correctly.
    359   EXPECT_TRUE(testable_writer_->received_truncate_);
    360   EXPECT_EQ(mock_path_as_gurl(),
    361             testable_writer_->received_truncate_path_);
    362   EXPECT_EQ(kCancelFileTruncate_Offset,
    363             testable_writer_->received_truncate_offset_);
    364   EXPECT_TRUE(testable_writer_->received_cancel_);
    365   EXPECT_FALSE(testable_writer_->received_write_);
    366 
    367   // Check that the client gets called correctly.
    368   EXPECT_TRUE(received_did_fail_);
    369   EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
    370   EXPECT_FALSE(received_did_truncate_);
    371   EXPECT_EQ(0, received_did_write_count_);
    372 }
    373 
    374 TEST_F(FileWriterTest, CancelFailedTruncate) {
    375   // Call the webkit facing api.
    376   writer()->truncate(kCancelFailedTruncate_Offset);
    377 
    378   // Check that the derived class gets called correctly.
    379   EXPECT_TRUE(testable_writer_->received_truncate_);
    380   EXPECT_EQ(mock_path_as_gurl(),
    381             testable_writer_->received_truncate_path_);
    382   EXPECT_EQ(kCancelFailedTruncate_Offset,
    383             testable_writer_->received_truncate_offset_);
    384   EXPECT_TRUE(testable_writer_->received_cancel_);
    385   EXPECT_FALSE(testable_writer_->received_write_);
    386 
    387   // Check that the client gets called correctly.
    388   EXPECT_TRUE(received_did_fail_);
    389   EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_);
    390   EXPECT_FALSE(received_did_truncate_);
    391   EXPECT_EQ(0, received_did_write_count_);
    392 }
    393 
    394 TEST_F(FileWriterTest, DeleteInCompletionCallbacks) {
    395   const std::string kBlobId("1234");
    396   delete_in_client_callback_ = true;
    397   writer()->write(kBasicFileWrite_Offset,
    398                   blink::WebString::fromUTF8(kBlobId));
    399   EXPECT_FALSE(testable_writer_.get());
    400 
    401   reset();
    402   delete_in_client_callback_ = true;
    403   writer()->truncate(kBasicFileTruncate_Offset);
    404   EXPECT_FALSE(testable_writer_.get());
    405 
    406   reset();
    407   delete_in_client_callback_ = true;
    408   writer()->write(kErrorFileWrite_Offset,
    409                   blink::WebString::fromUTF8(kBlobId));
    410   EXPECT_FALSE(testable_writer_.get());
    411 
    412   reset();
    413   delete_in_client_callback_ = true;
    414   writer()->truncate(kErrorFileTruncate_Offset);
    415   EXPECT_FALSE(testable_writer_.get());
    416 
    417   // Not crashing counts as passing.
    418 }
    419 
    420 }  // namespace content
    421