blob: 0336bf9b0c81c4c830404ec634b501e65e658c01 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <utility>
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_util.h"
#include "content/browser/attribution_reporting/attribution_storage_sql.h"
#include "content/browser/attribution_reporting/attribution_test_utils.h"
#include "content/browser/attribution_reporting/sql_queries.h"
#include "content/browser/attribution_reporting/sql_query_plan_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
namespace {
class AttributionSqlQueryPlanTest : public testing::Test {
public:
AttributionSqlQueryPlanTest() = default;
void SetUp() override {
ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
std::unique_ptr<AttributionStorage> storage =
std::make_unique<AttributionStorageSql>(
temp_directory_.GetPath(),
std::make_unique<ConfigurableStorageDelegate>());
// Make sure lazy initialization happens by adding a record to the db, but
// then ensure the database is closed so the sqlite_dev_shell can read it.
storage->StoreSource(SourceBuilder().Build());
storage.reset();
explainer_ = std::make_unique<SqlQueryPlanExplainer>(
temp_directory_.GetPath().Append(FILE_PATH_LITERAL("Conversions")));
}
// Helper method to make tests as readable as possible.
SqlQueryPlan GetPlan(
std::string query,
absl::optional<SqlFullScanReason> reason = absl::nullopt) {
auto plan = explainer_->GetPlan(std::move(query), reason);
EXPECT_TRUE(plan.has_value());
return *plan;
}
protected:
base::ScopedTempDir temp_directory_;
std::unique_ptr<SqlQueryPlanExplainer> explainer_;
};
TEST_F(AttributionSqlQueryPlanTest, kMinPrioritySql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kMinPrioritySql);
auto matcher = SqlIndexMatcher("event_level_reports_by_source_id");
EXPECT_TRUE(plan.UsesIndex(matcher)) << plan;
}
TEST_F(AttributionSqlQueryPlanTest, kGetMatchingSourcesSql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kGetMatchingSourcesSql);
auto matcher = SqlIndexMatcher("sources_by_expiry_time");
EXPECT_TRUE(plan.UsesIndex(matcher)) << plan;
}
TEST_F(AttributionSqlQueryPlanTest, kSelectExpiredSourcesSql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kSelectExpiredSourcesSql);
EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("sources_by_expiry_time")
.set_type(SqlIndexMatcher::Type::kCovering)))
<< plan;
EXPECT_TRUE(
plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
<< plan;
EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kSelectInactiveSourcesSql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kSelectInactiveSourcesSql);
EXPECT_TRUE(plan.UsesIndex(
SqlIndexMatcher("sources_by_active_destination_site_reporting_origin")
.set_type(SqlIndexMatcher::Type::kCovering)
.set_columns({"event_level_active", "aggregatable_active"})))
<< plan;
EXPECT_TRUE(
plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
<< plan;
EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kScanCandidateData) {
SqlQueryPlan plan = GetPlan(attribution_queries::kScanCandidateData,
SqlFullScanReason::kNotOptimized);
EXPECT_TRUE(
plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kDeleteVestigialConversionSql) {
SqlQueryPlan plan =
GetPlan(attribution_queries::kDeleteVestigialConversionSql);
EXPECT_TRUE(
plan.UsesIndex(SqlIndexMatcher("event_level_reports_by_source_id")))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kCountSourcesSql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kCountSourcesSql);
EXPECT_TRUE(
plan.UsesIndex(SqlIndexMatcher("active_sources_by_source_origin")))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kDedupKeySql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kDedupKeySql);
EXPECT_TRUE(plan.UsesIndex(
SqlIndexMatcher().set_type(SqlIndexMatcher::Type::kPrimaryKey)))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kScanCandidateDataAggregatable) {
SqlQueryPlan plan =
GetPlan(attribution_queries::kScanCandidateDataAggregatable,
SqlFullScanReason::kNotOptimized);
EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")))
<< plan;
}
TEST_F(AttributionSqlQueryPlanTest, kDeleteAggregationsSql) {
SqlQueryPlan plan = GetPlan(attribution_queries::kDeleteAggregationsSql);
EXPECT_TRUE(plan.UsesIndex(SqlIndexMatcher("aggregate_source_id_idx")
.set_type(SqlIndexMatcher::Type::kCovering)))
<< plan;
}
} // namespace
} // namespace content