// Copyright (c) 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/disk_cache/backend_cleanup_tracker.h" #include "base/bind.h" #include "base/callback.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" #include "net/test/test_with_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace disk_cache { namespace { using testing::UnorderedElementsAre; using testing::IsEmpty; class BackendCleanupTrackerTest : public net::TestWithTaskEnvironment { protected: BackendCleanupTrackerTest() = default; void SetUp() override { testing::Test::SetUp(); ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir()); // Create two unique paths. path1_ = tmp_dir_.GetPath().Append(FILE_PATH_LITERAL("a")); path2_ = tmp_dir_.GetPath().Append(FILE_PATH_LITERAL("b")); } void RecordCall(int val) { called_.push_back(val); } base::OnceClosure RecordCallClosure(int val) { return base::BindOnce(&BackendCleanupTrackerTest::RecordCall, base::Unretained(this), val); } base::ScopedTempDir tmp_dir_; base::FilePath path1_; base::FilePath path2_; std::vector called_; }; TEST_F(BackendCleanupTrackerTest, DistinctPath) { scoped_refptr t1 = BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(1)); scoped_refptr t2 = BackendCleanupTracker::TryCreate(path2_, RecordCallClosure(2)); // Both should be created immediately (since the paths are distinct), none of // the callbacks should be invoked. ASSERT_TRUE(t1 != nullptr); ASSERT_TRUE(t2 != nullptr); RunUntilIdle(); EXPECT_TRUE(called_.empty()); t1->AddPostCleanupCallback(RecordCallClosure(3)); t2->AddPostCleanupCallback(RecordCallClosure(4)); t2->AddPostCleanupCallback(RecordCallClosure(5)); // Just adding callbacks doesn't run them, nor just an event loop. EXPECT_TRUE(called_.empty()); RunUntilIdle(); EXPECT_TRUE(called_.empty()); t1 = nullptr; // Callbacks are not invoked immediately. EXPECT_TRUE(called_.empty()); // ... but via the event loop. RunUntilIdle(); EXPECT_THAT(called_, UnorderedElementsAre(3)); // Now cleanup t2. t2 = nullptr; EXPECT_THAT(called_, UnorderedElementsAre(3)); RunUntilIdle(); EXPECT_THAT(called_, UnorderedElementsAre(3, 4, 5)); } TEST_F(BackendCleanupTrackerTest, SamePath) { scoped_refptr t1 = BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(1)); scoped_refptr t2 = BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(2)); // Since path is the same, only first call succeeds. No callback yet, // since t1 controls the path. ASSERT_TRUE(t1 != nullptr); EXPECT_TRUE(t2 == nullptr); RunUntilIdle(); EXPECT_TRUE(called_.empty()); t1->AddPostCleanupCallback(RecordCallClosure(3)); t1->AddPostCleanupCallback(RecordCallClosure(4)); // Create an alias denoting work in progress. scoped_refptr alias = t1; t1 = nullptr; EXPECT_TRUE(called_.empty()); RunUntilIdle(); EXPECT_TRUE(called_.empty()); alias = nullptr; EXPECT_TRUE(called_.empty()); RunUntilIdle(); // Both the callback passed to the TryCreate that failed and ones passed to // AddPostCleanupCallback are called. EXPECT_THAT(called_, UnorderedElementsAre(2, 3, 4)); } } // namespace } // namespace disk_cache