tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestFileOutputStream.cpp (7094B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "QuotaManagerDependencyFixture.h"
      8 #include "mozilla/dom/quota/Client.h"
      9 #include "mozilla/dom/quota/ClientDirectoryLock.h"
     10 #include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
     11 #include "mozilla/dom/quota/CommonMetadata.h"
     12 #include "mozilla/dom/quota/FileStreams.h"
     13 #include "mozilla/dom/quota/QuotaManager.h"
     14 #include "mozilla/gtest/MozAssertions.h"
     15 #include "nsIPrefBranch.h"
     16 #include "nsIPrefService.h"
     17 
     18 namespace mozilla::dom::quota::test {
     19 
     20 quota::OriginMetadata GetOutputStreamTestOriginMetadata() {
     21  return quota::OriginMetadata{""_ns,
     22                               "example.com"_ns,
     23                               "http://example.com"_ns,
     24                               "http://example.com"_ns,
     25                               /* aIsPrivate */ false,
     26                               quota::PERSISTENCE_TYPE_DEFAULT};
     27 }
     28 
     29 class TestFileOutputStream : public QuotaManagerDependencyFixture {
     30 public:
     31  static void SetUpTestCase() {
     32    ASSERT_NO_FATAL_FAILURE(InitializeFixture());
     33 
     34    nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
     35 
     36    prefs->SetIntPref("dom.quotaManager.temporaryStorage.fixedLimit",
     37                      mQuotaLimit);
     38  }
     39 
     40  static void TearDownTestCase() {
     41    nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
     42 
     43    prefs->ClearUserPref("dom.quotaManager.temporaryStorage.fixedLimit");
     44 
     45    EXPECT_NO_FATAL_FAILURE(
     46        ClearStoragesForOrigin(GetOutputStreamTestOriginMetadata()));
     47 
     48    ASSERT_NO_FATAL_FAILURE(ShutdownFixture());
     49  }
     50 
     51  static const int32_t mQuotaLimit = 8192;
     52 };
     53 
     54 TEST_F(TestFileOutputStream, extendFileStreamWithSetEOF) {
     55  auto backgroundTask = []() {
     56    auto ioTask = []() {
     57      quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
     58 
     59      auto originMetadata = GetOutputStreamTestOriginMetadata();
     60 
     61      const int64_t groupLimit =
     62          static_cast<int64_t>(quotaManager->GetGroupLimit());
     63      ASSERT_TRUE(mQuotaLimit * 1024LL == groupLimit);
     64 
     65      // We don't use the tested stream itself to check the file size as it
     66      // may report values which have not been written to disk.
     67      RefPtr<quota::FileOutputStream> check =
     68          MakeRefPtr<quota::FileOutputStream>(quota::PERSISTENCE_TYPE_DEFAULT,
     69                                              originMetadata,
     70                                              quota::Client::Type::SDB);
     71 
     72      RefPtr<quota::FileOutputStream> stream =
     73          MakeRefPtr<quota::FileOutputStream>(quota::PERSISTENCE_TYPE_DEFAULT,
     74                                              originMetadata,
     75                                              quota::Client::Type::SDB);
     76 
     77      {
     78        auto testPathRes =
     79            quotaManager->GetOrCreateTemporaryOriginDirectory(originMetadata);
     80 
     81        ASSERT_TRUE(testPathRes.isOk());
     82 
     83        nsCOMPtr<nsIFile> testPath = testPathRes.unwrap();
     84 
     85        ASSERT_NS_SUCCEEDED(testPath->AppendRelativePath(u"sdb"_ns));
     86 
     87        ASSERT_NS_SUCCEEDED(
     88            testPath->AppendRelativePath(u"tTestFileOutputStream.txt"_ns));
     89 
     90        bool exists = true;
     91        ASSERT_NS_SUCCEEDED(testPath->Exists(&exists));
     92 
     93        if (exists) {
     94          ASSERT_NS_SUCCEEDED(testPath->Remove(/* recursive */ false));
     95        }
     96 
     97        ASSERT_NS_SUCCEEDED(testPath->Exists(&exists));
     98        ASSERT_FALSE(exists);
     99 
    100        ASSERT_NS_SUCCEEDED(testPath->Create(nsIFile::NORMAL_FILE_TYPE, 0666));
    101 
    102        ASSERT_NS_SUCCEEDED(testPath->Exists(&exists));
    103        ASSERT_TRUE(exists);
    104 
    105        nsCOMPtr<nsIFile> checkPath;
    106        ASSERT_NS_SUCCEEDED(testPath->Clone(getter_AddRefs(checkPath)));
    107 
    108        const int32_t IOFlags = -1;
    109        const int32_t perm = -1;
    110        const int32_t behaviorFlags = 0;
    111        ASSERT_NS_SUCCEEDED(
    112            stream->Init(testPath, IOFlags, perm, behaviorFlags));
    113 
    114        ASSERT_NS_SUCCEEDED(
    115            check->Init(testPath, IOFlags, perm, behaviorFlags));
    116      }
    117 
    118      // Check that we start with an empty file
    119      int64_t avail = 42;
    120      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    121 
    122      ASSERT_TRUE(0 == avail);
    123 
    124      // Enlarge the file
    125      const int64_t toSize = groupLimit;
    126      ASSERT_NS_SUCCEEDED(stream->Seek(nsISeekableStream::NS_SEEK_SET, toSize));
    127 
    128      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    129 
    130      ASSERT_TRUE(0 == avail);
    131 
    132      ASSERT_NS_SUCCEEDED(stream->SetEOF());
    133 
    134      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    135 
    136      ASSERT_TRUE(toSize == avail);
    137 
    138      // Try to enlarge the file past the limit
    139      const int64_t overGroupLimit = groupLimit + 1;
    140 
    141      // Seeking is allowed
    142      ASSERT_NS_SUCCEEDED(
    143          stream->Seek(nsISeekableStream::NS_SEEK_SET, overGroupLimit));
    144 
    145      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    146 
    147      ASSERT_TRUE(toSize == avail);
    148 
    149      // Setting file size to exceed quota should yield no device space error
    150      ASSERT_TRUE(NS_ERROR_FILE_NO_DEVICE_SPACE == stream->SetEOF());
    151 
    152      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    153 
    154      ASSERT_TRUE(toSize == avail);
    155 
    156      // Shrink the file
    157      const int64_t toHalfSize = toSize / 2;
    158      ASSERT_NS_SUCCEEDED(
    159          stream->Seek(nsISeekableStream::NS_SEEK_SET, toHalfSize));
    160 
    161      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    162 
    163      ASSERT_TRUE(toSize == avail);
    164 
    165      ASSERT_NS_SUCCEEDED(stream->SetEOF());
    166 
    167      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    168 
    169      ASSERT_TRUE(toHalfSize == avail);
    170 
    171      // Shrink the file back to nothing
    172      ASSERT_NS_SUCCEEDED(stream->Seek(nsISeekableStream::NS_SEEK_SET, 0));
    173 
    174      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    175 
    176      ASSERT_TRUE(toHalfSize == avail);
    177 
    178      ASSERT_NS_SUCCEEDED(stream->SetEOF());
    179 
    180      ASSERT_NS_SUCCEEDED(check->GetSize(&avail));
    181 
    182      ASSERT_TRUE(0 == avail);
    183    };
    184 
    185    ClientDirectoryLockHandle directoryLockHandle;
    186 
    187    QuotaManager* quotaManager = QuotaManager::Get();
    188    ASSERT_TRUE(quotaManager);
    189 
    190    bool done = false;
    191 
    192    quotaManager
    193        ->OpenClientDirectory(
    194            {GetOutputStreamTestOriginMetadata(), Client::SDB})
    195        ->Then(
    196            GetCurrentSerialEventTarget(), __func__,
    197            [&directoryLockHandle,
    198             &done](ClientDirectoryLockHandle&& aResolveValue) {
    199              directoryLockHandle = std::move(aResolveValue);
    200 
    201              done = true;
    202            },
    203            [&done](const nsresult aRejectValue) {
    204              ASSERT_TRUE(false);
    205 
    206              done = true;
    207            });
    208 
    209    SpinEventLoopUntil("Promise is fulfilled"_ns, [&done]() { return done; });
    210 
    211    ASSERT_TRUE(directoryLockHandle);
    212 
    213    PerformOnIOThread(std::move(ioTask));
    214 
    215    {
    216      auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
    217    }
    218  };
    219 
    220  PerformOnBackgroundThread(std::move(backgroundTask));
    221 }
    222 
    223 }  // namespace mozilla::dom::quota::test