tor-browser

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

TestFileSystemDataManagerVersions.cpp (41291B)


      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 <algorithm>
      8 
      9 #include "ErrorList.h"
     10 #include "FileSystemDataManager.h"
     11 #include "FileSystemDatabaseManagerVersion001.h"
     12 #include "FileSystemDatabaseManagerVersion002.h"
     13 #include "FileSystemFileManager.h"
     14 #include "FileSystemHashSource.h"
     15 #include "ResultStatement.h"
     16 #include "SchemaVersion001.h"
     17 #include "SchemaVersion002.h"
     18 #include "TestHelpers.h"
     19 #include "gtest/gtest.h"
     20 #include "mozIStorageService.h"
     21 #include "mozStorageCID.h"
     22 #include "mozStorageHelper.h"
     23 #include "mozilla/ErrorNames.h"
     24 #include "mozilla/dom/FileSystemTypes.h"
     25 #include "mozilla/dom/PFileSystemManager.h"
     26 #include "mozilla/dom/quota/CommonMetadata.h"
     27 #include "mozilla/dom/quota/test/QuotaManagerDependencyFixture.h"
     28 #include "nsContentUtils.h"
     29 #include "nsIFile.h"
     30 #include "nsLiteralString.h"
     31 #include "nsNetCID.h"
     32 #include "nsReadableUtils.h"
     33 #include "nsString.h"
     34 #include "nsStringFwd.h"
     35 #include "nsTArray.h"
     36 #include "nsTHashSet.h"
     37 
     38 namespace mozilla::dom::fs::test {
     39 
     40 using data::FileSystemDatabaseManagerVersion001;
     41 using data::FileSystemDatabaseManagerVersion002;
     42 using data::FileSystemFileManager;
     43 
     44 quota::OriginMetadata GetOriginMetadataSample() {
     45  return quota::OriginMetadata{""_ns,
     46                               "firefox.com"_ns,
     47                               "http://firefox.com"_ns,
     48                               "http://firefox.com"_ns,
     49                               /* aIsPrivate */ false,
     50                               quota::PERSISTENCE_TYPE_DEFAULT};
     51 }
     52 
     53 class TestFileSystemDatabaseManagerVersionsBase
     54    : public quota::test::QuotaManagerDependencyFixture {
     55 public:
     56  void SetUp() override { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
     57 
     58  void TearDown() override {
     59    EXPECT_NO_FATAL_FAILURE(ClearStoragesForOrigin(GetOriginMetadataSample()));
     60    ASSERT_NO_FATAL_FAILURE(ShutdownFixture());
     61  }
     62 };
     63 
     64 class TestFileSystemDatabaseManagerVersions
     65    : public TestFileSystemDatabaseManagerVersionsBase,
     66      public ::testing::WithParamInterface<DatabaseVersion> {
     67 public:
     68  static void AssertEntryIdMoved(const EntryId& aOriginal,
     69                                 const EntryId& aMoved) {
     70    switch (sVersion) {
     71      case 1: {
     72        ASSERT_EQ(aOriginal, aMoved);
     73        break;
     74      }
     75      case 2: {
     76        ASSERT_NE(aOriginal, aMoved);
     77        break;
     78      }
     79      default: {
     80        ASSERT_FALSE(false)
     81        << "Unknown database version";
     82      }
     83    }
     84  }
     85 
     86  static void AssertEntryIdCollision(const EntryId& aOriginal,
     87                                     const EntryId& aMoved) {
     88    switch (sVersion) {
     89      case 1: {
     90        // We generated a new entryId
     91        ASSERT_NE(aOriginal, aMoved);
     92        break;
     93      }
     94      case 2: {
     95        // We get the same entryId for the same input
     96        ASSERT_EQ(aOriginal, aMoved);
     97        break;
     98      }
     99      default: {
    100        ASSERT_FALSE(false)
    101        << "Unknown database version";
    102      }
    103    }
    104  }
    105 
    106  static DatabaseVersion sVersion;
    107 };
    108 
    109 // This is a minimal mock  to allow us to safely call the lock methods
    110 // while avoiding assertions
    111 class MockFileSystemDataManager final : public data::FileSystemDataManager {
    112 public:
    113  MockFileSystemDataManager(const quota::OriginMetadata& aOriginMetadata,
    114                            MovingNotNull<nsCOMPtr<nsIEventTarget>> aIOTarget,
    115                            MovingNotNull<RefPtr<TaskQueue>> aIOTaskQueue)
    116      : FileSystemDataManager(aOriginMetadata, nullptr, std::move(aIOTarget),
    117                              std::move(aIOTaskQueue)) {}
    118 
    119  void SetDatabaseManager(data::FileSystemDatabaseManager* aDatabaseManager) {
    120    mDatabaseManager =
    121        UniquePtr<data::FileSystemDatabaseManager>(aDatabaseManager);
    122  }
    123 
    124  virtual ~MockFileSystemDataManager() {
    125    mDatabaseManager->Close();
    126    mDatabaseManager = nullptr;
    127 
    128    // Need to avoid assertions
    129    mState = State::Closed;
    130  }
    131 };
    132 
    133 static void MakeDatabaseManagerVersions(
    134    const DatabaseVersion aVersion,
    135    RefPtr<MockFileSystemDataManager>& aDataManager,
    136    FileSystemDatabaseManagerVersion001*& aDatabaseManager) {
    137  TEST_TRY_UNWRAP(auto storageService,
    138                  MOZ_TO_RESULT_GET_TYPED(nsCOMPtr<mozIStorageService>,
    139                                          MOZ_SELECT_OVERLOAD(do_GetService),
    140                                          MOZ_STORAGE_SERVICE_CONTRACTID));
    141 
    142  const auto flags = mozIStorageService::CONNECTION_DEFAULT;
    143  ResultConnection connection;
    144 
    145  nsresult rv = storageService->OpenSpecialDatabase(kMozStorageMemoryStorageKey,
    146                                                    VoidCString(), flags,
    147                                                    getter_AddRefs(connection));
    148  ASSERT_NSEQ(NS_OK, rv);
    149 
    150  auto fmRes = FileSystemFileManager::CreateFileSystemFileManager(
    151      GetOriginMetadataSample());
    152  ASSERT_FALSE(fmRes.isErr());
    153 
    154  const Origin& testOrigin = GetTestOrigin();
    155 
    156  if (1 == aVersion) {
    157    TEST_TRY_UNWRAP(
    158        TestFileSystemDatabaseManagerVersions::sVersion,
    159        SchemaVersion001::InitializeConnection(connection, testOrigin));
    160  } else {
    161    ASSERT_EQ(2, aVersion);
    162 
    163    TEST_TRY_UNWRAP(TestFileSystemDatabaseManagerVersions::sVersion,
    164                    SchemaVersion002::InitializeConnection(
    165                        connection, *fmRes.inspect(), testOrigin));
    166  }
    167  ASSERT_NE(0, TestFileSystemDatabaseManagerVersions::sVersion);
    168 
    169  TEST_TRY_UNWRAP(EntryId rootId, data::GetRootHandle(GetTestOrigin()));
    170 
    171  QM_TRY_UNWRAP(auto streamTransportService,
    172                MOZ_TO_RESULT_GET_TYPED(nsCOMPtr<nsIEventTarget>,
    173                                        MOZ_SELECT_OVERLOAD(do_GetService),
    174                                        NS_STREAMTRANSPORTSERVICE_CONTRACTID),
    175                QM_VOID);
    176 
    177  quota::OriginMetadata originMetadata = GetOriginMetadataSample();
    178 
    179  nsCString taskQueueName("OPFS "_ns + originMetadata.mOrigin);
    180 
    181  RefPtr<TaskQueue> ioTaskQueue =
    182      TaskQueue::Create(do_AddRef(streamTransportService), taskQueueName.get());
    183 
    184  aDataManager = MakeRefPtr<MockFileSystemDataManager>(
    185      originMetadata, WrapMovingNotNull(streamTransportService),
    186      WrapMovingNotNull(ioTaskQueue));
    187 
    188  if (1 == aVersion) {
    189    aDatabaseManager = new FileSystemDatabaseManagerVersion001(
    190        aDataManager, std::move(connection), fmRes.unwrap(), rootId);
    191  } else {
    192    ASSERT_EQ(2, aVersion);
    193 
    194    aDatabaseManager = new FileSystemDatabaseManagerVersion002(
    195        aDataManager, std::move(connection), fmRes.unwrap(), rootId);
    196  }
    197 
    198  aDataManager->SetDatabaseManager(aDatabaseManager);
    199 }
    200 
    201 DatabaseVersion TestFileSystemDatabaseManagerVersions::sVersion = 0;
    202 
    203 TEST_P(TestFileSystemDatabaseManagerVersions,
    204       smokeTestCreateRemoveDirectories) {
    205  const DatabaseVersion version = GetParam();
    206 
    207  auto ioTask = [version]() {
    208    nsresult rv = NS_OK;
    209    // Ensure that FileSystemDataManager lives for the lifetime of the test
    210    RefPtr<MockFileSystemDataManager> dataManager;
    211    FileSystemDatabaseManagerVersion001* dm = nullptr;
    212    ASSERT_NO_FATAL_FAILURE(
    213        MakeDatabaseManagerVersions(version, dataManager, dm));
    214    ASSERT_TRUE(dm);
    215    // if any of these exit early, we have to close
    216    auto autoClose = MakeScopeExit([dm] { dm->Close(); });
    217 
    218    TEST_TRY_UNWRAP(EntryId rootId, data::GetRootHandle(GetTestOrigin()));
    219 
    220    FileSystemChildMetadata firstChildMeta(rootId, u"First"_ns);
    221    TEST_TRY_UNWRAP_ERR(
    222        rv, dm->GetOrCreateDirectory(firstChildMeta, /* create */ false));
    223    ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    224 
    225    TEST_TRY_UNWRAP(EntryId firstChild, dm->GetOrCreateDirectory(
    226                                            firstChildMeta, /* create */ true));
    227 
    228    int32_t dbVersion = 0;
    229    TEST_TRY_UNWRAP(FileSystemDirectoryListing entries,
    230                    dm->GetDirectoryEntries(rootId, dbVersion));
    231    ASSERT_EQ(1u, entries.directories().Length());
    232    ASSERT_EQ(0u, entries.files().Length());
    233 
    234    const auto& firstItemRef = entries.directories()[0];
    235    ASSERT_TRUE(u"First"_ns == firstItemRef.entryName())
    236    << firstItemRef.entryName();
    237    ASSERT_EQ(firstChild, firstItemRef.entryId());
    238 
    239    TEST_TRY_UNWRAP(
    240        EntryId firstChildClone,
    241        dm->GetOrCreateDirectory(firstChildMeta, /* create */ true));
    242    ASSERT_EQ(firstChild, firstChildClone);
    243 
    244    FileSystemChildMetadata secondChildMeta(firstChild, u"Second"_ns);
    245    TEST_TRY_UNWRAP(
    246        EntryId secondChild,
    247        dm->GetOrCreateDirectory(secondChildMeta, /* create */ true));
    248 
    249    FileSystemEntryPair shortPair(firstChild, secondChild);
    250    TEST_TRY_UNWRAP(Path shortPath, dm->Resolve(shortPair));
    251    ASSERT_EQ(1u, shortPath.Length());
    252    ASSERT_EQ(u"Second"_ns, shortPath[0]);
    253 
    254    FileSystemEntryPair longPair(rootId, secondChild);
    255    TEST_TRY_UNWRAP(Path longPath, dm->Resolve(longPair));
    256    ASSERT_EQ(2u, longPath.Length());
    257    ASSERT_EQ(u"First"_ns, longPath[0]);
    258    ASSERT_EQ(u"Second"_ns, longPath[1]);
    259 
    260    FileSystemEntryPair wrongPair(secondChild, rootId);
    261    TEST_TRY_UNWRAP(Path emptyPath, dm->Resolve(wrongPair));
    262    ASSERT_TRUE(emptyPath.IsEmpty());
    263 
    264    PageNumber page = 0;
    265    TEST_TRY_UNWRAP(FileSystemDirectoryListing fEntries,
    266                    dm->GetDirectoryEntries(firstChild, page));
    267    ASSERT_EQ(1u, fEntries.directories().Length());
    268    ASSERT_EQ(0u, fEntries.files().Length());
    269 
    270    const auto& secItemRef = fEntries.directories()[0];
    271    ASSERT_TRUE(u"Second"_ns == secItemRef.entryName())
    272    << secItemRef.entryName();
    273    ASSERT_EQ(secondChild, secItemRef.entryId());
    274 
    275    TEST_TRY_UNWRAP_ERR(
    276        rv, dm->RemoveDirectory(firstChildMeta, /* recursive */ false));
    277    ASSERT_NSEQ(NS_ERROR_DOM_INVALID_MODIFICATION_ERR, rv);
    278 
    279    TEST_TRY_UNWRAP(bool isDeleted,
    280                    dm->RemoveDirectory(firstChildMeta, /* recursive */ true));
    281    ASSERT_TRUE(isDeleted);
    282 
    283    FileSystemChildMetadata thirdChildMeta(secondChild, u"Second"_ns);
    284    TEST_TRY_UNWRAP_ERR(
    285        rv, dm->GetOrCreateDirectory(thirdChildMeta, /* create */ true));
    286    ASSERT_NSEQ(NS_ERROR_STORAGE_CONSTRAINT, rv);  // Is this a good error?
    287 
    288    dm->Close();
    289  };
    290 
    291  PerformOnIOThread(std::move(ioTask));
    292 }
    293 
    294 TEST_P(TestFileSystemDatabaseManagerVersions, smokeTestCreateRemoveFiles) {
    295  const DatabaseVersion version = GetParam();
    296 
    297  auto ioTask = [version]() {
    298    nsresult rv = NS_OK;
    299    // Ensure that FileSystemDataManager lives for the lifetime of the test
    300    RefPtr<MockFileSystemDataManager> datamanager;
    301    FileSystemDatabaseManagerVersion001* dm = nullptr;
    302    ASSERT_NO_FATAL_FAILURE(
    303        MakeDatabaseManagerVersions(version, datamanager, dm));
    304 
    305    TEST_TRY_UNWRAP(EntryId rootId, data::GetRootHandle(GetTestOrigin()));
    306 
    307    FileSystemChildMetadata firstChildMeta(rootId, u"First"_ns);
    308    // If creating is not allowed, getting a file from empty root fails
    309    TEST_TRY_UNWRAP_ERR(
    310        rv, dm->GetOrCreateFile(firstChildMeta, /* create */ false));
    311    ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    312 
    313    // Creating a file under empty root succeeds
    314    TEST_TRY_UNWRAP(EntryId firstChild,
    315                    dm->GetOrCreateFile(firstChildMeta, /* create */ true));
    316 
    317    // Second time, the same file is returned
    318    TEST_TRY_UNWRAP(EntryId firstChildClone,
    319                    dm->GetOrCreateFile(firstChildMeta, /* create */ true));
    320    ASSERT_EQ(firstChild, firstChildClone);
    321 
    322    // Directory listing returns the created file
    323    PageNumber page = 0;
    324    TEST_TRY_UNWRAP(FileSystemDirectoryListing entries,
    325                    dm->GetDirectoryEntries(rootId, page));
    326    ASSERT_EQ(0u, entries.directories().Length());
    327    ASSERT_EQ(1u, entries.files().Length());
    328 
    329    auto& firstItemRef = entries.files()[0];
    330    ASSERT_TRUE(u"First"_ns == firstItemRef.entryName())
    331    << firstItemRef.entryName();
    332    ASSERT_EQ(firstChild, firstItemRef.entryId());
    333 
    334    FileId fileId = FileId(firstItemRef.entryId());  // Default
    335 
    336    ContentType type;
    337    TimeStamp lastModifiedMilliSeconds;
    338    Path path;
    339    nsCOMPtr<nsIFile> file;
    340    rv = dm->GetFile(firstItemRef.entryId(), fileId, FileMode::EXCLUSIVE, type,
    341                     lastModifiedMilliSeconds, path, file);
    342    ASSERT_NSEQ(NS_OK, rv);
    343 
    344    const int64_t nowMilliSeconds = PR_Now() / 1000;
    345    ASSERT_GE(nowMilliSeconds, lastModifiedMilliSeconds);
    346    const int64_t expectedMaxDelayMilliSeconds = 100;
    347    const int64_t actualDelay = nowMilliSeconds - lastModifiedMilliSeconds;
    348    ASSERT_LT(actualDelay, expectedMaxDelayMilliSeconds);
    349 
    350    ASSERT_EQ(1u, path.Length());
    351    ASSERT_STREQ(u"First"_ns, path[0]);
    352 
    353    ASSERT_NE(nullptr, file);
    354 
    355    // Getting the file entry as directory fails
    356    TEST_TRY_UNWRAP_ERR(
    357        rv, dm->GetOrCreateDirectory(firstChildMeta, /* create */ false));
    358    ASSERT_NSEQ(NS_ERROR_DOM_TYPE_MISMATCH_ERR, rv);
    359 
    360    // Getting or creating the file entry as directory also fails
    361    TEST_TRY_UNWRAP_ERR(
    362        rv, dm->GetOrCreateDirectory(firstChildMeta, /* create */ true));
    363    ASSERT_NSEQ(NS_ERROR_DOM_TYPE_MISMATCH_ERR, rv);
    364 
    365    // Creating a file with non existing parent hash fails
    366 
    367    EntryId notAChildHash = "0123456789abcdef0123456789abcdef"_ns;
    368    FileSystemChildMetadata notAChildMeta(notAChildHash, u"Dummy"_ns);
    369    TEST_TRY_UNWRAP_ERR(rv,
    370                        dm->GetOrCreateFile(notAChildMeta, /* create */ true));
    371    ASSERT_NSEQ(NS_ERROR_STORAGE_CONSTRAINT, rv);  // Is this a good error?
    372 
    373    // We create a directory under root
    374    FileSystemChildMetadata secondChildMeta(rootId, u"Second"_ns);
    375    TEST_TRY_UNWRAP(
    376        EntryId secondChild,
    377        dm->GetOrCreateDirectory(secondChildMeta, /* create */ true));
    378 
    379    // The root should now contain the existing file and the new directory
    380    TEST_TRY_UNWRAP(FileSystemDirectoryListing fEntries,
    381                    dm->GetDirectoryEntries(rootId, page));
    382    ASSERT_EQ(1u, fEntries.directories().Length());
    383    ASSERT_EQ(1u, fEntries.files().Length());
    384 
    385    const auto& secItemRef = fEntries.directories()[0];
    386    ASSERT_TRUE(u"Second"_ns == secItemRef.entryName())
    387    << secItemRef.entryName();
    388    ASSERT_EQ(secondChild, secItemRef.entryId());
    389 
    390    // Create a file under the new directory
    391    FileSystemChildMetadata thirdChildMeta(secondChild, u"Third"_ns);
    392    TEST_TRY_UNWRAP(EntryId thirdChild,
    393                    dm->GetOrCreateFile(thirdChildMeta, /* create */ true));
    394 
    395    FileSystemEntryPair entryPair(rootId, thirdChild);
    396    TEST_TRY_UNWRAP(Path entryPath, dm->Resolve(entryPair));
    397    ASSERT_EQ(2u, entryPath.Length());
    398    ASSERT_EQ(u"Second"_ns, entryPath[0]);
    399    ASSERT_EQ(u"Third"_ns, entryPath[1]);
    400 
    401    // If recursion is not allowed, the non-empty new directory may not be
    402    // removed
    403    TEST_TRY_UNWRAP_ERR(
    404        rv, dm->RemoveDirectory(secondChildMeta, /* recursive */ false));
    405    ASSERT_NSEQ(NS_ERROR_DOM_INVALID_MODIFICATION_ERR, rv);
    406 
    407    // If recursion is allowed, the new directory goes away.
    408    TEST_TRY_UNWRAP(bool isDeleted,
    409                    dm->RemoveDirectory(secondChildMeta, /* recursive */ true));
    410    ASSERT_TRUE(isDeleted);
    411 
    412    // The file under the removed directory is no longer accessible.
    413    TEST_TRY_UNWRAP_ERR(rv,
    414                        dm->GetOrCreateFile(thirdChildMeta, /* create */ true));
    415    ASSERT_NSEQ(NS_ERROR_STORAGE_CONSTRAINT, rv);  // Is this a good error?
    416 
    417    // The deletion is reflected by the root directory listing
    418    TEST_TRY_UNWRAP(FileSystemDirectoryListing nEntries,
    419                    dm->GetDirectoryEntries(rootId, 0));
    420    ASSERT_EQ(0u, nEntries.directories().Length());
    421    ASSERT_EQ(1u, nEntries.files().Length());
    422 
    423    const auto& fileItemRef = nEntries.files()[0];
    424    ASSERT_TRUE(u"First"_ns == fileItemRef.entryName())
    425    << fileItemRef.entryName();
    426    ASSERT_EQ(firstChild, fileItemRef.entryId());
    427 
    428    dm->Close();
    429  };
    430 
    431  PerformOnIOThread(std::move(ioTask));
    432 }
    433 
    434 TEST_P(TestFileSystemDatabaseManagerVersions, smokeTestCreateMoveDirectories) {
    435  const DatabaseVersion version = GetParam();
    436 
    437  auto ioTask = [version]() {
    438    // Ensure that FileSystemDataManager lives for the lifetime of the test
    439    RefPtr<MockFileSystemDataManager> datamanager;
    440    FileSystemDatabaseManagerVersion001* dm = nullptr;
    441    ASSERT_NO_FATAL_FAILURE(
    442        MakeDatabaseManagerVersions(version, datamanager, dm));
    443    auto closeAtExit = MakeScopeExit([&dm]() { dm->Close(); });
    444 
    445    TEST_TRY_UNWRAP(EntryId rootId, data::GetRootHandle(GetTestOrigin()));
    446 
    447    FileSystemEntryMetadata rootMeta{rootId, u"root"_ns,
    448                                     /* is directory */ true};
    449 
    450    {
    451      // Sanity check: no existing items should be found
    452      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    453                      dm->GetDirectoryEntries(rootId, /* page */ 0u));
    454      ASSERT_TRUE(contents.directories().IsEmpty());
    455      ASSERT_TRUE(contents.files().IsEmpty());
    456    }
    457 
    458    // Create subdirectory
    459    FileSystemChildMetadata firstChildMeta(rootId, u"First"_ns);
    460    TEST_TRY_UNWRAP(
    461        EntryId firstChildDir,
    462        dm->GetOrCreateDirectory(firstChildMeta, /* create */ true));
    463 
    464    {
    465      // Check that directory listing is as expected
    466      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    467                      dm->GetDirectoryEntries(rootId, /* page */ 0u));
    468      ASSERT_TRUE(contents.files().IsEmpty());
    469      ASSERT_EQ(1u, contents.directories().Length());
    470      ASSERT_STREQ(firstChildMeta.childName(),
    471                   contents.directories()[0].entryName());
    472    }
    473 
    474    {
    475      // Try to move subdirectory to its current location
    476      FileSystemEntryMetadata src{firstChildDir, firstChildMeta.childName(),
    477                                  /* is directory */ true};
    478      FileSystemChildMetadata dest{rootId, src.entryName()};
    479      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    480      ASSERT_FALSE(moved.IsEmpty());
    481      firstChildDir = moved;
    482    }
    483 
    484    {
    485      // Try to move subdirectory under itself
    486      FileSystemEntryMetadata src{firstChildDir, firstChildMeta.childName(),
    487                                  /* is directory */ true};
    488      FileSystemChildMetadata dest{src.entryId(), src.entryName()};
    489      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->MoveEntry(src, dest));
    490      ASSERT_NSEQ(NS_ERROR_DOM_INVALID_MODIFICATION_ERR, rv);
    491    }
    492 
    493    {
    494      // Try to move root under its subdirectory
    495      FileSystemEntryMetadata src{rootId, rootMeta.entryName(),
    496                                  /* is directory */ true};
    497      FileSystemChildMetadata dest{firstChildDir, src.entryName()};
    498      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->MoveEntry(src, dest));
    499      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    500    }
    501 
    502    // Create subsubdirectory
    503    FileSystemChildMetadata firstChildDescendantMeta(firstChildDir,
    504                                                     u"Descendant"_ns);
    505    TEST_TRY_UNWRAP(EntryId firstChildDescendant,
    506                    dm->GetOrCreateDirectory(firstChildDescendantMeta,
    507                                             /* create */ true));
    508 
    509    {
    510      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    511                      dm->GetDirectoryEntries(firstChildDir, /* page */ 0u));
    512      ASSERT_TRUE(contents.files().IsEmpty());
    513      ASSERT_EQ(1u, contents.directories().Length());
    514      ASSERT_STREQ(firstChildDescendantMeta.childName(),
    515                   contents.directories()[0].entryName());
    516 
    517      TEST_TRY_UNWRAP(
    518          Path subSubDirPath,
    519          dm->Resolve({rootId, contents.directories()[0].entryId()}));
    520      ASSERT_EQ(2u, subSubDirPath.Length());
    521      ASSERT_STREQ(firstChildMeta.childName(), subSubDirPath[0]);
    522      ASSERT_STREQ(firstChildDescendantMeta.childName(), subSubDirPath[1]);
    523    }
    524 
    525    {
    526      // Try to move subsubdirectory to its current location
    527      FileSystemEntryMetadata src{firstChildDescendant,
    528                                  firstChildDescendantMeta.childName(),
    529                                  /* is directory */ true};
    530      FileSystemChildMetadata dest{firstChildDir, src.entryName()};
    531      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    532      ASSERT_FALSE(moved.IsEmpty());
    533      firstChildDescendant = moved;
    534    }
    535 
    536    {
    537      // Try to move subsubdirectory under itself
    538      FileSystemEntryMetadata src{firstChildDescendant,
    539                                  firstChildDescendantMeta.childName(),
    540                                  /* is directory */ true};
    541      FileSystemChildMetadata dest{src.entryId(), src.entryName()};
    542      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->MoveEntry(src, dest));
    543      ASSERT_NSEQ(NS_ERROR_DOM_INVALID_MODIFICATION_ERR, rv);
    544    }
    545 
    546    {
    547      // Try to move subdirectory under its descendant
    548      FileSystemEntryMetadata src{firstChildDir, firstChildMeta.childName(),
    549                                  /* is directory */ true};
    550      FileSystemChildMetadata dest{firstChildDescendant, src.entryName()};
    551      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->MoveEntry(src, dest));
    552      ASSERT_NSEQ(NS_ERROR_DOM_INVALID_MODIFICATION_ERR, rv);
    553    }
    554 
    555    {
    556      // Try to move root under its subsubdirectory
    557      FileSystemEntryMetadata src{rootId, rootMeta.entryName(),
    558                                  /* is directory */ true};
    559      FileSystemChildMetadata dest{firstChildDescendant, src.entryName()};
    560      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->MoveEntry(src, dest));
    561      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    562    }
    563 
    564    // Create file in the subdirectory with already existing subsubdirectory
    565    FileSystemChildMetadata testFileMeta(firstChildDir, u"Subfile"_ns);
    566    TEST_TRY_UNWRAP(EntryId testFile,
    567                    dm->GetOrCreateFile(testFileMeta, /* create */ true));
    568 
    569    // Get handles to the original locations of the entries
    570    FileSystemEntryMetadata subSubDir;
    571    FileSystemEntryMetadata subSubFile;
    572 
    573    {
    574      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    575                      dm->GetDirectoryEntries(firstChildDir, /* page */ 0u));
    576      ASSERT_EQ(1u, contents.files().Length());
    577      ASSERT_EQ(1u, contents.directories().Length());
    578 
    579      subSubDir = contents.directories()[0];
    580      ASSERT_STREQ(firstChildDescendantMeta.childName(), subSubDir.entryName());
    581 
    582      subSubFile = contents.files()[0];
    583      ASSERT_STREQ(testFileMeta.childName(), subSubFile.entryName());
    584      ASSERT_EQ(testFile, subSubFile.entryId());
    585    }
    586 
    587    {
    588      TEST_TRY_UNWRAP(Path entryPath,
    589                      dm->Resolve({rootId, subSubFile.entryId()}));
    590      ASSERT_EQ(2u, entryPath.Length());
    591      ASSERT_STREQ(firstChildMeta.childName(), entryPath[0]);
    592      ASSERT_STREQ(testFileMeta.childName(), entryPath[1]);
    593    }
    594 
    595    {
    596      // Try to move file to its current location
    597      FileSystemEntryMetadata src{testFile, testFileMeta.childName(),
    598                                  /* is directory */ false};
    599      FileSystemChildMetadata dest{firstChildDir, src.entryName()};
    600      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    601      ASSERT_FALSE(moved.IsEmpty());
    602      testFile = moved;
    603    }
    604 
    605    {
    606      // Try to move subsubdirectory under a file
    607      FileSystemEntryMetadata src{firstChildDescendant,
    608                                  firstChildDescendantMeta.childName(),
    609                                  /* is directory */ true};
    610      FileSystemChildMetadata dest{testFile,
    611                                   firstChildDescendantMeta.childName()};
    612      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->MoveEntry(src, dest));
    613      ASSERT_NSEQ(NS_ERROR_STORAGE_CONSTRAINT, rv);
    614    }
    615 
    616    {
    617      // Silently overwrite a directory with a file using rename
    618      FileSystemEntryMetadata src{testFile, testFileMeta.childName(),
    619                                  /* is directory */ false};
    620      const FileSystemChildMetadata& dest = firstChildDescendantMeta;
    621      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    622      ASSERT_FALSE(moved.IsEmpty());
    623      testFile = moved;
    624    }
    625 
    626    {
    627      // Move file back and recreate the directory
    628      FileSystemEntryMetadata src{testFile,
    629                                  firstChildDescendantMeta.childName(),
    630                                  /* is directory */ false};
    631 
    632      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, testFileMeta));
    633      ASSERT_FALSE(moved.IsEmpty());
    634      testFile = moved;
    635 
    636      TEST_TRY_UNWRAP(EntryId firstChildDescendantCheck,
    637                      dm->GetOrCreateDirectory(firstChildDescendantMeta,
    638                                               /* create */ true));
    639      ASSERT_EQ(firstChildDescendant, firstChildDescendantCheck);
    640    }
    641 
    642    {
    643      // Try to rename directory to quietly overwrite a file
    644      FileSystemEntryMetadata src{firstChildDescendant,
    645                                  firstChildDescendantMeta.childName(),
    646                                  /* is directory */ true};
    647      const FileSystemChildMetadata& dest = testFileMeta;
    648      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    649      ASSERT_FALSE(moved.IsEmpty());
    650      firstChildDescendant = moved;
    651    }
    652 
    653    {
    654      // Move directory back and recreate the file
    655      FileSystemEntryMetadata src{firstChildDescendant,
    656                                  testFileMeta.childName(),
    657                                  /* is directory */ true};
    658 
    659      FileSystemChildMetadata dest{firstChildDir,
    660                                   firstChildDescendantMeta.childName()};
    661 
    662      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    663      ASSERT_FALSE(moved.IsEmpty());
    664      firstChildDescendant = moved;
    665 
    666      TEST_TRY_UNWRAP(EntryId testFileCheck,
    667                      dm->GetOrCreateFile(testFileMeta, /* create */ true));
    668      ASSERT_EQ(testFile, testFileCheck);
    669    }
    670 
    671    {
    672      // Move file one level up
    673      FileSystemEntryMetadata src{testFile, testFileMeta.childName(),
    674                                  /* is directory */ false};
    675      FileSystemChildMetadata dest{rootId, src.entryName()};
    676      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    677      ASSERT_FALSE(moved.IsEmpty());
    678      testFile = moved;
    679    }
    680 
    681    {
    682      // Check that listings are as expected
    683      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    684                      dm->GetDirectoryEntries(firstChildDir, 0u));
    685      ASSERT_TRUE(contents.files().IsEmpty());
    686      ASSERT_EQ(1u, contents.directories().Length());
    687      ASSERT_STREQ(firstChildDescendantMeta.childName(),
    688                   contents.directories()[0].entryName());
    689    }
    690 
    691    {
    692      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    693                      dm->GetDirectoryEntries(rootId, 0u));
    694      ASSERT_EQ(1u, contents.files().Length());
    695      ASSERT_EQ(1u, contents.directories().Length());
    696      ASSERT_STREQ(testFileMeta.childName(), contents.files()[0].entryName());
    697      ASSERT_STREQ(firstChildMeta.childName(),
    698                   contents.directories()[0].entryName());
    699    }
    700 
    701    {
    702      ASSERT_NO_FATAL_FAILURE(
    703          AssertEntryIdMoved(subSubFile.entryId(), testFile));
    704      TEST_TRY_UNWRAP(Path entryPath,
    705                      dm->Resolve({rootId, subSubFile.entryId()}));
    706      if (1 == sVersion) {
    707        ASSERT_EQ(1u, entryPath.Length());
    708        ASSERT_STREQ(testFileMeta.childName(), entryPath[0]);
    709      } else {
    710        ASSERT_EQ(2, sVersion);
    711        // Per spec, path result is empty when no path exists.
    712        ASSERT_TRUE(entryPath.IsEmpty());
    713      }
    714    }
    715 
    716    {
    717      // Try to get a handle to the old item
    718      TEST_TRY_UNWRAP_ERR(
    719          nsresult rv, dm->GetOrCreateFile(testFileMeta, /* create */ false));
    720      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    721    }
    722 
    723    {
    724      // Try to move + rename file one level down to collide with a
    725      // subSubDirectory, silently overwriting it
    726      FileSystemEntryMetadata src{testFile, testFileMeta.childName(),
    727                                  /* is directory */ false};
    728      FileSystemChildMetadata dest{firstChildDir,
    729                                   firstChildDescendantMeta.childName()};
    730      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    731      ASSERT_FALSE(moved.IsEmpty());
    732      testFile = moved;
    733    }
    734 
    735    {
    736      // Restore filename, move file to its original location and recreate
    737      // the overwritten directory
    738      FileSystemEntryMetadata src{testFile,
    739                                  firstChildDescendantMeta.childName(),
    740                                  /* is directory */ false};
    741      FileSystemChildMetadata dest{rootId, testFileMeta.childName()};
    742      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    743      ASSERT_FALSE(moved.IsEmpty());
    744      testFile = moved;
    745 
    746      FileSystemChildMetadata oldLocation{firstChildDir,
    747                                          firstChildDescendantMeta.childName()};
    748 
    749      // Is there still something out there?
    750      TEST_TRY_UNWRAP_ERR(nsresult rv,
    751                          dm->GetOrCreateFile(oldLocation, /* create */ false));
    752      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    753 
    754      TEST_TRY_UNWRAP(EntryId firstChildDescendantCheck,
    755                      dm->GetOrCreateDirectory(oldLocation, /* create */ true));
    756      ASSERT_EQ(firstChildDescendant, firstChildDescendantCheck);
    757    }
    758 
    759    // Rename file first and then try to move it to collide with
    760    // subSubDirectory, silently overwriting it
    761    {
    762      // Rename
    763      FileSystemEntryMetadata src{testFile, testFileMeta.childName(),
    764                                  /* is directory */ false};
    765      FileSystemChildMetadata dest{rootId,
    766                                   firstChildDescendantMeta.childName()};
    767      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    768      ASSERT_FALSE(moved.IsEmpty());
    769      testFile = moved;
    770    }
    771 
    772    {
    773      // Try to move one level down
    774      FileSystemEntryMetadata src{testFile,
    775                                  firstChildDescendantMeta.childName(),
    776                                  /* is directory */ false};
    777      FileSystemChildMetadata dest{firstChildDir,
    778                                   firstChildDescendantMeta.childName()};
    779      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    780      ASSERT_FALSE(moved.IsEmpty());
    781      testFile = moved;
    782    }
    783 
    784    {
    785      // Move the file back and recreate the directory
    786      FileSystemEntryMetadata src{testFile,
    787                                  firstChildDescendantMeta.childName(),
    788                                  /* is directory */ false};
    789      FileSystemChildMetadata dest{rootId,
    790                                   firstChildDescendantMeta.childName()};
    791      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    792      ASSERT_FALSE(moved.IsEmpty());
    793      testFile = moved;
    794 
    795      FileSystemChildMetadata oldLocation{firstChildDir,
    796                                          firstChildDescendantMeta.childName()};
    797 
    798      // Is there still something out there?
    799      TEST_TRY_UNWRAP_ERR(nsresult rv,
    800                          dm->GetOrCreateFile(oldLocation, /* create */ false));
    801      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    802 
    803      TEST_TRY_UNWRAP(EntryId firstChildDescendantCheck,
    804                      dm->GetOrCreateDirectory(oldLocation, /* create */ true));
    805      ASSERT_EQ(firstChildDescendant, firstChildDescendantCheck);
    806    }
    807 
    808    {
    809      // Try to move subSubDirectory one level up to quietly overwrite a file
    810      FileSystemEntryMetadata src{firstChildDescendant,
    811                                  firstChildDescendantMeta.childName(),
    812                                  /* is directory */ true};
    813      FileSystemChildMetadata dest{rootId,
    814                                   firstChildDescendantMeta.childName()};
    815      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    816      ASSERT_FALSE(moved.IsEmpty());
    817      firstChildDescendant = moved;
    818    }
    819 
    820    {
    821      // Move subSubDirectory back one level down and recreate the file
    822      FileSystemEntryMetadata src{firstChildDescendant,
    823                                  firstChildDescendantMeta.childName(),
    824                                  /* is directory */ true};
    825      FileSystemChildMetadata dest{firstChildDir,
    826                                   firstChildDescendantMeta.childName()};
    827      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    828      ASSERT_FALSE(moved.IsEmpty());
    829      firstChildDescendant = moved;
    830 
    831      FileSystemChildMetadata oldLocation{rootId,
    832                                          firstChildDescendantMeta.childName()};
    833 
    834      // We should no longer find anything there
    835      TEST_TRY_UNWRAP_ERR(nsresult rv, dm->GetOrCreateDirectory(
    836                                           oldLocation, /* create */ false));
    837      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    838 
    839      TEST_TRY_UNWRAP(EntryId testFileCheck,
    840                      dm->GetOrCreateFile(oldLocation, /* create */ true));
    841      ASSERT_NO_FATAL_FAILURE(AssertEntryIdCollision(testFile, testFileCheck));
    842      testFile = testFileCheck;
    843    }
    844 
    845    // Create a new file in the subsubdirectory
    846    FileSystemChildMetadata newFileMeta{firstChildDescendant,
    847                                        testFileMeta.childName()};
    848    EntryId oldFirstChildDescendant = firstChildDescendant;
    849 
    850    TEST_TRY_UNWRAP(EntryId newFile,
    851                    dm->GetOrCreateFile(newFileMeta, /* create */ true));
    852 
    853    {
    854      TEST_TRY_UNWRAP(Path entryPath, dm->Resolve({rootId, newFile}));
    855      ASSERT_EQ(3u, entryPath.Length());
    856      ASSERT_STREQ(firstChildMeta.childName(), entryPath[0]);
    857      ASSERT_STREQ(firstChildDescendantMeta.childName(), entryPath[1]);
    858      ASSERT_STREQ(testFileMeta.childName(), entryPath[2]);
    859    }
    860 
    861    {
    862      // Move subSubDirectory one level up and rename it to testFile's old name
    863      FileSystemEntryMetadata src{firstChildDescendant,
    864                                  firstChildDescendantMeta.childName(),
    865                                  /* is directory */ true};
    866      FileSystemChildMetadata dest{rootId, testFileMeta.childName()};
    867      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    868      ASSERT_FALSE(moved.IsEmpty());
    869      firstChildDescendant = moved;
    870    }
    871 
    872    {
    873      // Try to get handles to the moved items
    874      TEST_TRY_UNWRAP_ERR(nsresult rv,
    875                          dm->GetOrCreateDirectory(firstChildDescendantMeta,
    876                                                   /* create */ false));
    877      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    878 
    879      //  Still under the same parent which was moved
    880      if (1 == sVersion) {
    881        TEST_TRY_UNWRAP(EntryId handle,
    882                        dm->GetOrCreateFile(newFileMeta, /* create */ false));
    883        ASSERT_EQ(handle, newFile);
    884 
    885        TEST_TRY_UNWRAP(
    886            handle, dm->GetOrCreateDirectory({rootId, testFileMeta.childName()},
    887                                             /* create */ false));
    888        ASSERT_EQ(handle, firstChildDescendant);
    889      } else if (2 == sVersion) {
    890        TEST_TRY_UNWRAP_ERR(
    891            rv, dm->GetOrCreateFile(newFileMeta, /* create */ false));
    892        ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
    893 
    894        TEST_TRY_UNWRAP(
    895            EntryId newFileCheck,
    896            dm->GetOrCreateFile({firstChildDescendant, newFileMeta.childName()},
    897                                /* create */ false));
    898        ASSERT_FALSE(newFileCheck.IsEmpty());
    899      } else {
    900        ASSERT_FALSE(false)
    901        << "Unknown database version";
    902      }
    903    }
    904 
    905    {
    906      // Check that new file path is as expected
    907      TEST_TRY_UNWRAP(
    908          EntryId newFileCheck,
    909          dm->GetOrCreateFile({firstChildDescendant, newFileMeta.childName()},
    910                              /* create */ false));
    911      ASSERT_NO_FATAL_FAILURE(AssertEntryIdMoved(newFileCheck, newFile));
    912      newFile = newFileCheck;
    913 
    914      TEST_TRY_UNWRAP(Path entryPath, dm->Resolve({rootId, newFile}));
    915      ASSERT_EQ(2u, entryPath.Length());
    916      ASSERT_STREQ(testFileMeta.childName(), entryPath[0]);
    917      ASSERT_STREQ(testFileMeta.childName(), entryPath[1]);
    918    }
    919 
    920    // Move first file and subSubDirectory back one level down keeping the names
    921    {
    922      FileSystemEntryMetadata src{testFile,
    923                                  firstChildDescendantMeta.childName(),
    924                                  /* is directory */ false};
    925      FileSystemChildMetadata dest{firstChildDir,
    926                                   firstChildDescendantMeta.childName()};
    927 
    928      // Flag is ignored
    929      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    930      ASSERT_FALSE(moved.IsEmpty());
    931      testFile = moved;
    932    }
    933 
    934    {
    935      // Then move the directory
    936      FileSystemEntryMetadata src{firstChildDescendant,
    937                                  testFileMeta.childName(),
    938                                  /* is directory */ true};
    939      FileSystemChildMetadata dest{firstChildDir, testFileMeta.childName()};
    940 
    941      // Flag is ignored
    942      TEST_TRY_UNWRAP(EntryId moved, dm->MoveEntry(src, dest));
    943      ASSERT_FALSE(moved.IsEmpty());
    944      firstChildDescendant = moved;
    945    }
    946 
    947    // Check that listings are as expected
    948    {
    949      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    950                      dm->GetDirectoryEntries(rootId, 0u));
    951      ASSERT_TRUE(contents.files().IsEmpty());
    952      ASSERT_EQ(1u, contents.directories().Length());
    953      ASSERT_STREQ(firstChildMeta.childName(),
    954                   contents.directories()[0].entryName());
    955    }
    956 
    957    {
    958      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    959                      dm->GetDirectoryEntries(firstChildDir, 0u));
    960      ASSERT_EQ(1u, contents.files().Length());
    961      ASSERT_EQ(1u, contents.directories().Length());
    962      ASSERT_STREQ(firstChildDescendantMeta.childName(),
    963                   contents.files()[0].entryName());
    964      ASSERT_STREQ(testFileMeta.childName(),
    965                   contents.directories()[0].entryName());
    966    }
    967 
    968    {
    969      TEST_TRY_UNWRAP(FileSystemDirectoryListing contents,
    970                      dm->GetDirectoryEntries(firstChildDescendant, 0u));
    971      ASSERT_EQ(1u, contents.files().Length());
    972      ASSERT_TRUE(contents.directories().IsEmpty());
    973      ASSERT_STREQ(testFileMeta.childName(), contents.files()[0].entryName());
    974    }
    975 
    976    // Names are swapped
    977    {
    978      TEST_TRY_UNWRAP(Path entryPath, dm->Resolve({rootId, testFile}));
    979      ASSERT_EQ(2u, entryPath.Length());
    980      ASSERT_STREQ(firstChildMeta.childName(), entryPath[0]);
    981      ASSERT_STREQ(firstChildDescendantMeta.childName(), entryPath[1]);
    982    }
    983 
    984    {
    985      TEST_TRY_UNWRAP(Path entryPath,
    986                      dm->Resolve({rootId, firstChildDescendant}));
    987      ASSERT_EQ(2u, entryPath.Length());
    988      ASSERT_STREQ(firstChildMeta.childName(), entryPath[0]);
    989      ASSERT_STREQ(testFileMeta.childName(), entryPath[1]);
    990    }
    991 
    992    {
    993      // Check that new file path is also as expected
    994      TEST_TRY_UNWRAP(
    995          EntryId newFileCheck,
    996          dm->GetOrCreateFile({firstChildDescendant, newFileMeta.childName()},
    997                              /* create */ false));
    998      ASSERT_NO_FATAL_FAILURE(AssertEntryIdMoved(newFileCheck, newFile));
    999      newFile = newFileCheck;
   1000 
   1001      TEST_TRY_UNWRAP(Path entryPath, dm->Resolve({rootId, newFile}));
   1002      ASSERT_EQ(3u, entryPath.Length());
   1003      ASSERT_STREQ(firstChildMeta.childName(), entryPath[0]);
   1004      ASSERT_STREQ(testFileMeta.childName(), entryPath[1]);
   1005      ASSERT_STREQ(testFileMeta.childName(), entryPath[2]);
   1006    }
   1007 
   1008    {
   1009      // Try to get handles to the old items
   1010      TEST_TRY_UNWRAP_ERR(
   1011          nsresult rv, dm->GetOrCreateFile({rootId, testFileMeta.childName()},
   1012                                           /* create */ false));
   1013      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
   1014 
   1015      TEST_TRY_UNWRAP_ERR(
   1016          rv,
   1017          dm->GetOrCreateFile({rootId, firstChildDescendantMeta.childName()},
   1018                              /* create */ false));
   1019      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
   1020 
   1021      TEST_TRY_UNWRAP_ERR(
   1022          rv, dm->GetOrCreateDirectory({rootId, testFileMeta.childName()},
   1023                                       /* create */ false));
   1024      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
   1025 
   1026      TEST_TRY_UNWRAP_ERR(rv,
   1027                          dm->GetOrCreateDirectory(
   1028                              {rootId, firstChildDescendantMeta.childName()},
   1029                              /* create */ false));
   1030      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
   1031 
   1032      TEST_TRY_UNWRAP_ERR(
   1033          rv, dm->GetOrCreateFile({firstChildDir, testFileMeta.childName()},
   1034                                  /* create */ false));
   1035      ASSERT_NSEQ(NS_ERROR_DOM_TYPE_MISMATCH_ERR, rv);
   1036 
   1037      TEST_TRY_UNWRAP_ERR(
   1038          rv, dm->GetOrCreateDirectory(
   1039                  {firstChildDir, firstChildDescendantMeta.childName()},
   1040                  /* create */ false));
   1041      ASSERT_NSEQ(NS_ERROR_DOM_TYPE_MISMATCH_ERR, rv);
   1042 
   1043      TEST_TRY_UNWRAP_ERR(
   1044          rv, dm->GetOrCreateFile({testFile, newFileMeta.childName()},
   1045                                  /* create */ false));
   1046      ASSERT_NSEQ(NS_ERROR_DOM_NOT_FOUND_ERR, rv);
   1047    }
   1048  };
   1049 
   1050  PerformOnIOThread(std::move(ioTask));
   1051 }
   1052 
   1053 INSTANTIATE_TEST_SUITE_P(TestDatabaseManagerVersions,
   1054                         TestFileSystemDatabaseManagerVersions,
   1055                         testing::Values(1, 2));
   1056 
   1057 }  // namespace mozilla::dom::fs::test