| // 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<int> called_; |
| }; |
| |
| TEST_F(BackendCleanupTrackerTest, DistinctPath) { |
| scoped_refptr<BackendCleanupTracker> t1 = |
| BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(1)); |
| scoped_refptr<BackendCleanupTracker> 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<BackendCleanupTracker> t1 = |
| BackendCleanupTracker::TryCreate(path1_, RecordCallClosure(1)); |
| scoped_refptr<BackendCleanupTracker> 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<BackendCleanupTracker> 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 |