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