| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/page_load_metrics/browser/resource_tracker.h" |
| |
| #include <utility> |
| |
| #include "base/byte_count.h" |
| #include "components/page_load_metrics/common/page_load_metrics.mojom.h" |
| #include "content/public/browser/global_request_id.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| class ResourceTrackerTest : public testing::Test { |
| public: |
| ResourceTrackerTest() = default; |
| |
| void StartResourceLoad(int resource_id, bool is_complete = false) { |
| CreateResourceUpdate(resource_id, /*delta_bytes=*/base::ByteCount(0), |
| /*is_complete=*/is_complete); |
| } |
| |
| void AdvanceResourceLoad(int resource_id, base::ByteCount bytes) { |
| CreateResourceUpdate(resource_id, /*delta_bytes=*/bytes, |
| /*is_complete=*/false); |
| } |
| |
| void CompleteResourceLoad(int resource_id) { |
| CreateResourceUpdate(resource_id, /*delta_bytes=*/base::ByteCount(0), |
| /*is_complete=*/true); |
| } |
| |
| bool HasUnfinishedResource(int resource_id) { |
| return resource_tracker_.unfinished_resources().find( |
| content::GlobalRequestID(process_id_, resource_id)) != |
| resource_tracker_.unfinished_resources().end(); |
| } |
| |
| base::ByteCount GetUnfinishedResourceBytes(int resource_id) { |
| return resource_tracker_.unfinished_resources() |
| .find(content::GlobalRequestID(process_id_, resource_id)) |
| ->second->delta_bytes; |
| } |
| |
| bool HasPreviousUpdateForResource(int resource_id) { |
| return resource_tracker_.HasPreviousUpdateForResource( |
| content::GlobalRequestID(process_id_, resource_id)); |
| } |
| |
| base::ByteCount GetPreviousResourceUpdateDelta(int resource_id) { |
| return resource_tracker_ |
| .GetPreviousUpdateForResource( |
| content::GlobalRequestID(process_id_, resource_id)) |
| ->delta_bytes; |
| } |
| |
| private: |
| void CreateResourceUpdate(int request_id, |
| base::ByteCount delta_bytes, |
| bool is_complete) { |
| std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr> resources; |
| auto resource_data_update = |
| page_load_metrics::mojom::ResourceDataUpdate::New(); |
| resource_data_update->request_id = request_id; |
| resource_data_update->delta_bytes = delta_bytes; |
| resource_data_update->is_complete = is_complete; |
| resources.push_back(std::move(resource_data_update)); |
| resource_tracker_.UpdateResourceDataUse(process_id_, resources); |
| } |
| |
| const int process_id_ = 0; |
| |
| page_load_metrics::ResourceTracker resource_tracker_; |
| }; |
| |
| // Verifies that resources are added to and removed from the map |
| // of ongoing resource loads as expected. |
| TEST_F(ResourceTrackerTest, UnfinishedResourceMap) { |
| StartResourceLoad(/*resource_id=*/0); |
| StartResourceLoad(/*resource_id=*/1); |
| StartResourceLoad(/*resource_id=*/2); |
| |
| // Verify completed resources are not stored in the unfinished map. |
| EXPECT_TRUE(HasUnfinishedResource(/*resource_id=*/0)); |
| CompleteResourceLoad(/*resource_id=*/0); |
| EXPECT_FALSE(HasUnfinishedResource(/*resource_id=*/0)); |
| |
| // Verify that resources receiving multiple updates are not removed from the |
| // map. |
| AdvanceResourceLoad(/*resource_id=*/1, /*bytes=*/base::ByteCount(10)); |
| AdvanceResourceLoad(/*resource_id=*/1, /*bytes=*/base::ByteCount(20)); |
| EXPECT_TRUE(HasUnfinishedResource(/*resource_id=*/1)); |
| CompleteResourceLoad(/*resource_id=*/1); |
| EXPECT_FALSE(HasUnfinishedResource(/*resource_id=*/1)); |
| |
| // Verify the unfinished map stores the most recent resource update. |
| EXPECT_EQ(base::ByteCount(0), GetUnfinishedResourceBytes(/*resource_id=*/2)); |
| AdvanceResourceLoad(/*resource_id=*/2, /*bytes=*/base::ByteCount(10)); |
| EXPECT_EQ(base::ByteCount(10), GetUnfinishedResourceBytes(/*resource_id=*/2)); |
| AdvanceResourceLoad(/*resource_id=*/2, /*bytes=*/base::ByteCount(20)); |
| AdvanceResourceLoad(/*resource_id=*/2, /*bytes=*/base::ByteCount(30)); |
| EXPECT_EQ(base::ByteCount(30), GetUnfinishedResourceBytes(/*resource_id=*/2)); |
| } |
| |
| // Verifies that resources are added to and removed from the map |
| // of previous resource updates as expected. |
| TEST_F(ResourceTrackerTest, PreviousUpdateResourceMap) { |
| StartResourceLoad(/*resource_id=*/0); |
| StartResourceLoad(/*resource_id=*/1); |
| EXPECT_FALSE(HasPreviousUpdateForResource(/*resource_id=*/0)); |
| EXPECT_FALSE(HasPreviousUpdateForResource(/*resource_id=*/1)); |
| |
| AdvanceResourceLoad(/*resource_id=*/1, /*bytes=*/base::ByteCount(10)); |
| EXPECT_TRUE(HasPreviousUpdateForResource(/*resource_id=*/1)); |
| |
| // Previous resource update should only be available for resources |
| // who received resource updates in the previous call to |
| // ResourceTracker::UpdateResourceDataUse(). resource_id "1" should not be |
| // available in this case. |
| AdvanceResourceLoad(/*resource_id=*/0, /*bytes=*/base::ByteCount(0)); |
| EXPECT_FALSE(HasPreviousUpdateForResource(/*resource_id=*/1)); |
| |
| // The update should not be available because the load for resource_id "1" was |
| // still ongoing. This should hold the data for the last update, 10 bytes. |
| AdvanceResourceLoad(/*resource_id=*/1, /*bytes=*/base::ByteCount(20)); |
| EXPECT_TRUE(HasPreviousUpdateForResource(/*resource_id=*/1)); |
| EXPECT_EQ(base::ByteCount(10), |
| GetPreviousResourceUpdateDelta(/*resource_id=*/1)); |
| |
| // Verify previous resource update is available for newly complete resources. |
| CompleteResourceLoad(/*resource_id=*/1); |
| EXPECT_TRUE(HasPreviousUpdateForResource(/*resource_id=*/1)); |
| EXPECT_EQ(base::ByteCount(20), |
| GetPreviousResourceUpdateDelta(/*resource_id=*/1)); |
| |
| // Verify this completed resource update is removed once other resources are |
| // loaded. |
| CompleteResourceLoad(/*resource_id=*/0); |
| EXPECT_FALSE(HasPreviousUpdateForResource(/*resource_id=*/1)); |
| } |
| |
| TEST_F(ResourceTrackerTest, SingleUpdateResourceNotStored) { |
| // Verify that resources who only receive one update and complete are never |
| // stored. |
| StartResourceLoad(/*resource_id=*/0, true /* is_complete */); |
| EXPECT_FALSE(HasUnfinishedResource(/*resource_id=*/0)); |
| EXPECT_FALSE(HasPreviousUpdateForResource(/*resource_id=*/0)); |
| |
| // Load new resource and verify we don't have a previous update for the |
| // resource that completed. |
| StartResourceLoad(/*resource_id=*/1, true /* is_complete */); |
| EXPECT_FALSE(HasUnfinishedResource(/*resource_id=*/0)); |
| EXPECT_FALSE(HasPreviousUpdateForResource(/*resource_id=*/0)); |
| } |