[ledger] DCHECK that the parent dir exists before moving to destination.

Test: LevelDbFactoryTest.InitWithCachedDbAvailable
      Rest of existing tests still pass.

Change-Id: I65debc6ee085c21d9c112d89bbce0a1c9c2d253b
diff --git a/bin/ledger/storage/impl/leveldb_factory.cc b/bin/ledger/storage/impl/leveldb_factory.cc
index 5427e94..8486544 100644
--- a/bin/ledger/storage/impl/leveldb_factory.cc
+++ b/bin/ledger/storage/impl/leveldb_factory.cc
@@ -40,6 +40,16 @@
 
 constexpr size_t kRandomBytesCount = 16;
 
+// Returns whether the parent directory of |path| exists. If it is not possible
+// to access the parent directory, returns whether the given |path| exists.
+bool ParentDirectoryExists(ledger::DetachedPath path) {
+  size_t last_slash = path.path().find_last_of('/');
+  return files::IsDirectoryAt(path.root_fd(),
+                              last_slash == std::string::npos
+                                  ? path.path()
+                                  : path.path().substr(0, last_slash));
+}
+
 }  // namespace
 
 enum class LevelDbFactory::CreateInStagingPath : bool {
@@ -221,6 +231,15 @@
   if (status != Status::OK) {
     return status;
   }
+  // If the parent directory doesn't exist, renameat will fail.
+  // Note that |cached_db_path_| will also be created throught the staging path
+  // and thus, this code path will be reached. Its parent directory is lazily
+  // created when result->Init() (see code above) is called:
+  // - |staging_path_| and |cached_db_path_| share the same parent (the
+  //   |cache_path| given on the constructor), and
+  // - in LevelDb initialization, the directories up to the db path are created.
+  FXL_DCHECK(ParentDirectoryExists(db_path))
+      << "Parent directory does not exit for path: " << db_path.path();
   // Move it to the final destination.
   if (renameat(tmp_destination.root_fd(), tmp_destination.path().c_str(),
                db_path.root_fd(), db_path.path().c_str()) != 0) {
diff --git a/bin/ledger/storage/impl/leveldb_factory_unittest.cc b/bin/ledger/storage/impl/leveldb_factory_unittest.cc
index 5a2e5be..ddb62c4 100644
--- a/bin/ledger/storage/impl/leveldb_factory_unittest.cc
+++ b/bin/ledger/storage/impl/leveldb_factory_unittest.cc
@@ -181,19 +181,24 @@
   // one directly.
   scoped_tmpfs::ScopedTmpFS tmpfs;
   ledger::DetachedPath cache_path(tmpfs.root_fd(), "cache");
+  // Must be the same as |kCachedDbPath| in leveldb_factory.cc.
+  ledger::DetachedPath cached_db_path = cache_path.SubPath("cached_db");
+
   auto db_factory = std::make_unique<LevelDbFactory>(&environment_, cache_path);
 
-  // The cache directory should not be created, yet.
-  EXPECT_FALSE(files::IsDirectoryAt(cache_path.root_fd(), cache_path.path()));
+  // The cached db directory should not be created, yet.
+  EXPECT_FALSE(
+      files::IsDirectoryAt(cached_db_path.root_fd(), cached_db_path.path()));
 
   // Initialize and wait for the cached instance to be created.
   db_factory->Init();
   RunLoopUntilIdle();
 
   // Close the factory. This will not affect the created cached instance, which
-  // was created under |cache_path|.
+  // was created under |cached_db_path|.
   db_factory.reset();
-  EXPECT_TRUE(files::IsDirectoryAt(cache_path.root_fd(), cache_path.path()));
+  EXPECT_TRUE(
+      files::IsDirectoryAt(cached_db_path.root_fd(), cached_db_path.path()));
 
   // Reset and re-initialize the factory object. It should now use the
   // previously created instance.