1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/device_bound_sessions/session_store_impl.h"
#include <memory>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "components/unexportable_keys/unexportable_key_service_impl.h"
#include "components/unexportable_keys/unexportable_key_task_manager.h"
#include "crypto/scoped_fake_unexportable_key_provider.h"
#include "crypto/unexportable_key.h"
#include "net/base/schemeful_site.h"
#include "net/base/test_completion_callback.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_result_reporter.h"
#include "url/gurl.h"
namespace net::device_bound_sessions {
namespace {
const base::FilePath::CharType dbsc_filename[] =
FILE_PATH_LITERAL("DBSC_Sessions");
static constexpr char kMetricPrefixDbscSS[] = "DBSCSessionStore.";
static constexpr char kMetricOperationDurationMs[] = "operation_duration";
static const int kNumSites = 200;
static const int kSessionsPerSite = 5;
constexpr crypto::SignatureVerifier::SignatureAlgorithm
kAcceptableAlgorithms[] = {crypto::SignatureVerifier::ECDSA_SHA256};
constexpr unexportable_keys::BackgroundTaskPriority kTaskPriority =
unexportable_keys::BackgroundTaskPriority::kUserBlocking;
perf_test::PerfResultReporter SetUpDbscSSReporter(const std::string& story) {
perf_test::PerfResultReporter reporter(kMetricPrefixDbscSS, story);
reporter.RegisterImportantMetric(kMetricOperationDurationMs, "ms");
return reporter;
}
} // namespace
class DBSCSessionStorePerfTest : public testing::Test {
public:
DBSCSessionStorePerfTest() : key_service_(task_manager_) {}
void CreateStore() {
store_ = std::make_unique<SessionStoreImpl>(
temp_dir_.GetPath().Append(dbsc_filename), key_service_);
}
void DeleteStore() {
base::RunLoop run_loop;
store_->SetShutdownCallbackForTesting(run_loop.QuitClosure());
store_ = nullptr;
run_loop.Run();
}
SessionStore::SessionsMap LoadSessions() {
base::RunLoop run_loop;
SessionStore::SessionsMap loaded_sessions;
store_->LoadSessions(base::BindLambdaForTesting(
[&run_loop, &loaded_sessions](SessionStore::SessionsMap sessions) {
loaded_sessions = std::move(sessions);
run_loop.Quit();
}));
run_loop.Run();
return loaded_sessions;
}
unexportable_keys::UnexportableKeyId GenerateNewKey() {
base::test::TestFuture<
unexportable_keys::ServiceErrorOr<unexportable_keys::UnexportableKeyId>>
generate_future;
key_service_.GenerateSigningKeySlowlyAsync(
kAcceptableAlgorithms, kTaskPriority, generate_future.GetCallback());
unexportable_keys::ServiceErrorOr<unexportable_keys::UnexportableKeyId>
key_id = generate_future.Get();
CHECK(key_id.has_value());
return *key_id;
}
void AddSession(int site_idx, int session_idx) {
std::string session_str = base::StringPrintf("session_id_%d", session_idx);
std::string url_str =
base::StringPrintf("https://%d.example%d.test", session_idx, site_idx);
std::string refresh_url =
base::StringPrintf("https://example%d.test/refresh.html", site_idx);
std::string cookie_name =
base::StringPrintf("cookie_%d_%d", site_idx, session_idx);
std::string cookie_attr =
base::StringPrintf("Secure; Domain=example%d.test", site_idx);
SessionParams::Scope scope;
std::vector<SessionParams::Credential> cookie_credentials(
{SessionParams::Credential{cookie_name, cookie_attr}});
SessionParams params{session_str,
GURL(url_str),
refresh_url,
std::move(scope),
std::move(cookie_credentials),
GenerateNewKey()};
auto session_or_error = Session::CreateIfValid(params);
ASSERT_TRUE(session_or_error.has_value());
std::unique_ptr<Session> session = std::move(*session_or_error);
ASSERT_TRUE(session);
store_->SaveSession(SchemefulSite(GURL(url_str)), *session);
}
unsigned int NumSessionsInStore() { return store_->GetAllSessions().size(); }
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
CreateStore();
LoadSessions(); // empty load
ASSERT_TRUE(store_);
// StartPerfMeasurement();
for (int site_num = 0; site_num < kNumSites; site_num++) {
for (int session_num = 0; session_num < kSessionsPerSite; ++session_num) {
AddSession(site_num, session_num);
}
}
// Delete the store. This action will cause all the session data to be
// written to disk.
DeleteStore();
}
void TearDown() override {
if (store_) {
DeleteStore();
}
}
void StartPerfMeasurement() {
DCHECK(perf_measurement_start_.is_null());
perf_measurement_start_ = base::Time::Now();
}
void EndPerfMeasurement(const std::string& story) {
DCHECK(!perf_measurement_start_.is_null());
base::TimeDelta elapsed = base::Time::Now() - perf_measurement_start_;
perf_measurement_start_ = base::Time();
auto reporter = SetUpDbscSSReporter(story);
reporter.AddResult(kMetricOperationDurationMs, elapsed.InMillisecondsF());
}
protected:
base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<SessionStoreImpl> store_;
crypto::ScopedFakeUnexportableKeyProvider scoped_key_provider_;
unexportable_keys::UnexportableKeyTaskManager task_manager_{
crypto::UnexportableKeyProvider::Config()};
unexportable_keys::UnexportableKeyServiceImpl key_service_;
base::Time perf_measurement_start_;
};
// Test the performance of load
// TODO(crbug.com/371964293): Refactor this test to use the
// Google Benchmark library instead.
TEST_F(DBSCSessionStorePerfTest, TestLoadPerformance) {
CreateStore();
VLOG(0) << "Beginning load from disk..";
StartPerfMeasurement();
SessionStore::SessionsMap sessions_map = LoadSessions();
EndPerfMeasurement("load");
EXPECT_EQ(NumSessionsInStore(), (unsigned int)(kNumSites * kSessionsPerSite));
VLOG(0) << "Loaded " << sessions_map.size() << " sessions.";
}
} // namespace net::device_bound_sessions
|