blob: 0767bbb55a971eba97e197b5c233064e2aefb300 [file] [log] [blame]
// 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));
}