blob: 2967635e9572d9737be63a0694ef2f98ca91e0ec [file] [log] [blame]
// Copyright 2018 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 "components/blacklist/opt_out_blacklist/opt_out_blacklist.h"
#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h"
#include "components/blacklist/opt_out_blacklist/opt_out_store.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blacklist {
namespace {
const char kTestHost1[] = "testhost1.com";
const char kTestHost2[] = "testhost2.com";
// Mock class to test that OptOutBlacklist notifies the delegate with correct
// events (e.g. New host blacklisted, user blacklisted, and blacklist cleared).
class TestOptOutBlacklistDelegate : public OptOutBlacklistDelegate {
public:
TestOptOutBlacklistDelegate()
: user_blacklisted_(false),
blacklist_cleared_(false),
blacklist_cleared_time_(base::Time::Now()) {}
// OptOutBlacklistDelegate:
void OnNewBlacklistedHost(const std::string& host, base::Time time) override {
blacklisted_hosts_[host] = time;
}
void OnUserBlacklistedStatusChange(bool blacklisted) override {
user_blacklisted_ = blacklisted;
}
void OnBlacklistCleared(base::Time time) override {
blacklist_cleared_ = true;
blacklist_cleared_time_ = time;
}
// Gets the set of blacklisted hosts recorded.
const std::unordered_map<std::string, base::Time>& blacklisted_hosts() const {
return blacklisted_hosts_;
}
// Gets the state of user blacklisted status.
bool user_blacklisted() const { return user_blacklisted_; }
// Gets the state of blacklisted cleared status of |this| for testing.
bool blacklist_cleared() const { return blacklist_cleared_; }
// Gets the event time of blacklist is as cleared.
base::Time blacklist_cleared_time() const { return blacklist_cleared_time_; }
private:
// The user blacklisted status of |this| blacklist_delegate.
bool user_blacklisted_;
// Check if the blacklist is notified as cleared on |this| blacklist_delegate.
bool blacklist_cleared_;
// The time when blacklist is cleared.
base::Time blacklist_cleared_time_;
// |this| blacklist_delegate's collection of blacklisted hosts.
std::unordered_map<std::string, base::Time> blacklisted_hosts_;
};
class TestOptOutStore : public OptOutStore {
public:
TestOptOutStore() : clear_blacklist_count_(0) {}
~TestOptOutStore() override {}
int clear_blacklist_count() { return clear_blacklist_count_; }
void SetBlacklistData(std::unique_ptr<BlacklistData> data) {
data_ = std::move(data);
}
private:
// OptOutStore implementation:
void AddEntry(bool opt_out,
const std::string& host_name,
int type,
base::Time now) override {}
void LoadBlackList(std::unique_ptr<BlacklistData> blacklist_data,
LoadBlackListCallback callback) override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback),
data_ ? std::move(data_) : std::move(blacklist_data)));
}
void ClearBlackList(base::Time begin_time, base::Time end_time) override {
++clear_blacklist_count_;
}
int clear_blacklist_count_;
std::unique_ptr<BlacklistData> data_;
};
class TestOptOutBlacklist : public OptOutBlacklist {
public:
TestOptOutBlacklist(std::unique_ptr<OptOutStore> opt_out_store,
base::Clock* clock,
OptOutBlacklistDelegate* blacklist_delegate)
: OptOutBlacklist(std::move(opt_out_store), clock, blacklist_delegate) {}
~TestOptOutBlacklist() override {}
void SetSessionRule(std::unique_ptr<BlacklistData::Policy> policy) {
session_policy_ = std::move(policy);
}
void SetPersistentRule(std::unique_ptr<BlacklistData::Policy> policy) {
persistent_policy_ = std::move(policy);
}
void SetHostRule(std::unique_ptr<BlacklistData::Policy> policy,
size_t max_hosts) {
host_policy_ = std::move(policy);
max_hosts_ = max_hosts;
}
void SetTypeRule(std::unique_ptr<BlacklistData::Policy> policy) {
type_policy_ = std::move(policy);
}
void SetAllowedTypes(BlacklistData::AllowedTypesAndVersions allowed_types) {
allowed_types_ = std::move(allowed_types);
}
private:
bool ShouldUseSessionPolicy(base::TimeDelta* duration,
size_t* history,
int* threshold) const override {
if (!session_policy_)
return false;
*duration = session_policy_->duration;
*history = session_policy_->history;
*threshold = session_policy_->threshold;
return true;
}
bool ShouldUsePersistentPolicy(base::TimeDelta* duration,
size_t* history,
int* threshold) const override {
if (!persistent_policy_)
return false;
*duration = persistent_policy_->duration;
*history = persistent_policy_->history;
*threshold = persistent_policy_->threshold;
return true;
}
bool ShouldUseHostPolicy(base::TimeDelta* duration,
size_t* history,
int* threshold,
size_t* max_hosts) const override {
if (!host_policy_)
return false;
*duration = host_policy_->duration;
*history = host_policy_->history;
*threshold = host_policy_->threshold;
*max_hosts = max_hosts_;
return true;
}
bool ShouldUseTypePolicy(base::TimeDelta* duration,
size_t* history,
int* threshold) const override {
if (!type_policy_)
return false;
*duration = type_policy_->duration;
*history = type_policy_->history;
*threshold = type_policy_->threshold;
return true;
}
BlacklistData::AllowedTypesAndVersions GetAllowedTypes() const override {
return allowed_types_;
}
std::unique_ptr<BlacklistData::Policy> session_policy_;
std::unique_ptr<BlacklistData::Policy> persistent_policy_;
std::unique_ptr<BlacklistData::Policy> host_policy_;
std::unique_ptr<BlacklistData::Policy> type_policy_;
size_t max_hosts_ = 0;
BlacklistData::AllowedTypesAndVersions allowed_types_;
};
class OptOutBlacklistTest : public testing::Test {
public:
OptOutBlacklistTest() {}
~OptOutBlacklistTest() override {}
void StartTest(bool null_opt_out_store) {
std::unique_ptr<TestOptOutStore> opt_out_store =
null_opt_out_store ? nullptr : std::make_unique<TestOptOutStore>();
opt_out_store_ = opt_out_store.get();
black_list_ = std::make_unique<TestOptOutBlacklist>(
std::move(opt_out_store), &test_clock_, &blacklist_delegate_);
if (session_policy_) {
black_list_->SetSessionRule(std::move(session_policy_));
}
if (persistent_policy_) {
black_list_->SetPersistentRule(std::move(persistent_policy_));
}
if (host_policy_) {
black_list_->SetHostRule(std::move(host_policy_), max_hosts_);
}
if (type_policy_) {
black_list_->SetTypeRule(std::move(type_policy_));
}
black_list_->SetAllowedTypes(std::move(allowed_types_));
black_list_->Init();
start_ = test_clock_.Now();
passed_reasons_ = {};
}
void SetSessionRule(std::unique_ptr<BlacklistData::Policy> policy) {
session_policy_ = std::move(policy);
}
void SetPersistentRule(std::unique_ptr<BlacklistData::Policy> policy) {
persistent_policy_ = std::move(policy);
}
void SetHostRule(std::unique_ptr<BlacklistData::Policy> policy,
size_t max_hosts) {
host_policy_ = std::move(policy);
max_hosts_ = max_hosts;
}
void SetTypeRule(std::unique_ptr<BlacklistData::Policy> policy) {
type_policy_ = std::move(policy);
}
void SetAllowedTypes(BlacklistData::AllowedTypesAndVersions allowed_types) {
allowed_types_ = std::move(allowed_types);
}
protected:
base::test::ScopedTaskEnvironment task_environment_;
// Observer to |black_list_|.
TestOptOutBlacklistDelegate blacklist_delegate_;
base::SimpleTestClock test_clock_;
TestOptOutStore* opt_out_store_;
base::Time start_;
std::unique_ptr<TestOptOutBlacklist> black_list_;
std::vector<BlacklistReason> passed_reasons_;
private:
std::unique_ptr<BlacklistData::Policy> session_policy_;
std::unique_ptr<BlacklistData::Policy> persistent_policy_;
std::unique_ptr<BlacklistData::Policy> host_policy_;
std::unique_ptr<BlacklistData::Policy> type_policy_;
size_t max_hosts_ = 0;
BlacklistData::AllowedTypesAndVersions allowed_types_;
DISALLOW_COPY_AND_ASSIGN(OptOutBlacklistTest);
};
TEST_F(OptOutBlacklistTest, HostBlackListNoStore) {
// Tests the black list behavior when a null OptOutStore is passed in.
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 2);
SetHostRule(std::move(host_policy), 5);
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
black_list_->AddEntry(kTestHost2, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost2, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
black_list_->AddEntry(kTestHost2, false, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost2, false, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost2, false, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
black_list_->ClearBlackList(start_, test_clock_.Now());
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, TypeBlackListWithStore) {
// Tests the black list behavior when a non-null OptOutStore is passed in.
auto type_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 2);
SetTypeRule(std::move(type_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
allowed_types.insert({2, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(false /* null_opt_out */);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, true, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, false, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, false, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, false, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
EXPECT_EQ(0, opt_out_store_->clear_blacklist_count());
black_list_->ClearBlackList(start_, base::Time::Now());
EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, TypeBlackListNoStore) {
// Tests the black list behavior when a null OptOutStore is passed in.
auto type_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 2);
SetTypeRule(std::move(type_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
allowed_types.insert({2, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, true, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->AddEntry(kTestHost1, false, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, false, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, false, 2);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfType,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
black_list_->ClearBlackList(start_, test_clock_.Now());
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, HostIndifferentBlacklist) {
// Tests the black list behavior when a null OptOutStore is passed in.
const std::string hosts[] = {
"url_0.com", "url_1.com", "url_2.com", "url_3.com",
};
int host_indifferent_threshold = 4;
auto persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, host_indifferent_threshold);
SetPersistentRule(std::move(persistent_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
for (int i = 0; i < host_indifferent_threshold; i++) {
black_list_->AddEntry(hosts[i], true, 1);
EXPECT_EQ(
i != 3 ? BlacklistReason::kAllowed
: BlacklistReason::kUserOptedOutInGeneral,
black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
}
EXPECT_EQ(
BlacklistReason::kUserOptedOutInGeneral,
black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInGeneral,
black_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInGeneral,
black_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInGeneral,
black_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[3], 1, true, &passed_reasons_));
black_list_->AddEntry(hosts[3], false, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
// New non-opt-out entry will cause these to be allowed now.
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, QueueBehavior) {
// Tests the black list asynchronous queue behavior. Methods called while
// loading the opt-out store are queued and should run in the order they were
// queued.
std::vector<bool> test_opt_out{true, false};
for (auto opt_out : test_opt_out) {
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 2);
SetHostRule(std::move(host_policy), 5);
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(false /* null_opt_out */);
EXPECT_EQ(BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
&passed_reasons_));
black_list_->AddEntry(kTestHost1, opt_out, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, opt_out, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
&passed_reasons_));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(opt_out ? BlacklistReason::kUserOptedOutOfHost
: BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
&passed_reasons_));
black_list_->AddEntry(kTestHost1, opt_out, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, opt_out, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(0, opt_out_store_->clear_blacklist_count());
black_list_->ClearBlackList(
start_, test_clock_.Now() + base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
black_list_->AddEntry(kTestHost2, opt_out, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost2, opt_out, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
EXPECT_EQ(BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
&passed_reasons_));
EXPECT_EQ(opt_out ? BlacklistReason::kUserOptedOutOfHost
: BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false,
&passed_reasons_));
}
}
TEST_F(OptOutBlacklistTest, MaxHosts) {
// Test that the black list only stores n hosts, and it stores the correct n
// hosts.
const std::string test_host_3("host3.com");
const std::string test_host_4("host4.com");
const std::string test_host_5("host5.com");
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 1u, 1);
SetHostRule(std::move(host_policy), 2);
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
black_list_->AddEntry(kTestHost1, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost2, false, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(test_host_3, false, 1);
// kTestHost1 should stay in the map, since it has an opt out time.
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(test_host_4, true, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(test_host_5, true, 1);
// test_host_4 and test_host_5 should remain in the map, but host should be
// evicted.
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(test_host_4, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(test_host_5, 1, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, SingleOptOut) {
// Test that when a user opts out of an action, actions won't be allowed until
// |single_opt_out_duration| has elapsed.
int single_opt_out_duration = 5;
const std::string test_host_3("host3.com");
auto session_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromSeconds(single_opt_out_duration), 1u, 1);
SetSessionRule(std::move(session_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
black_list_->AddEntry(kTestHost1, false, 1);
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
test_clock_.Advance(
base::TimeDelta::FromSeconds(single_opt_out_duration + 1));
black_list_->AddEntry(kTestHost2, true, 1);
EXPECT_EQ(
BlacklistReason::kUserOptedOutInSession,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInSession,
black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
test_clock_.Advance(
base::TimeDelta::FromSeconds(single_opt_out_duration - 1));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInSession,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInSession,
black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
test_clock_.Advance(
base::TimeDelta::FromSeconds(single_opt_out_duration + 1));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, ClearingBlackListClearsRecentNavigation) {
// Tests that clearing the black list for a long amount of time (relative to
// "single_opt_out_duration_in_seconds") resets the blacklist's recent opt out
// rule.
auto session_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromSeconds(5), 1u, 1);
SetSessionRule(std::move(session_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(false /* null_opt_out */);
black_list_->AddEntry(kTestHost1, true /* opt_out */, 1);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->ClearBlackList(start_, test_clock_.Now());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
}
TEST_F(OptOutBlacklistTest, ObserverIsNotifiedOnHostBlacklisted) {
// Tests the black list behavior when a null OptOutStore is passed in.
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 2);
SetHostRule(std::move(host_policy), 5);
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
// Observer is not notified as blacklisted when the threshold does not met.
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 1);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(0));
// Observer is notified as blacklisted when the threshold is met.
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 1);
base::RunLoop().RunUntilIdle();
const base::Time blacklisted_time = test_clock_.Now();
EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(1));
EXPECT_EQ(blacklisted_time,
blacklist_delegate_.blacklisted_hosts().find(kTestHost1)->second);
// Observer is not notified when the host is already blacklisted.
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(kTestHost1, true, 1);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(1));
EXPECT_EQ(blacklisted_time,
blacklist_delegate_.blacklisted_hosts().find(kTestHost1)->second);
// Observer is notified when blacklist is cleared.
EXPECT_FALSE(blacklist_delegate_.blacklist_cleared());
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->ClearBlackList(start_, test_clock_.Now());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(blacklist_delegate_.blacklist_cleared());
EXPECT_EQ(test_clock_.Now(), blacklist_delegate_.blacklist_cleared_time());
}
TEST_F(OptOutBlacklistTest, ObserverIsNotifiedOnUserBlacklisted) {
// Tests the black list behavior when a null OptOutStore is passed in.
const std::string hosts[] = {
"url_0.com", "url_1.com", "url_2.com", "url_3.com",
};
int host_indifferent_threshold = 4;
auto persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), 4u, host_indifferent_threshold);
SetPersistentRule(std::move(persistent_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
// Initially no host is blacklisted, and user is not blacklisted.
EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(0));
EXPECT_FALSE(blacklist_delegate_.user_blacklisted());
for (int i = 0; i < host_indifferent_threshold; ++i) {
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(hosts[i], true, 1);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(0));
// Observer is notified when number of recently opt out meets
// |host_indifferent_threshold|.
EXPECT_EQ(i >= host_indifferent_threshold - 1,
blacklist_delegate_.user_blacklisted());
}
// Observer is notified when the user is no longer blacklisted.
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
black_list_->AddEntry(hosts[3], false, 1);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(blacklist_delegate_.user_blacklisted());
}
TEST_F(OptOutBlacklistTest, ObserverIsNotifiedWhenLoadBlacklistDone) {
int host_indifferent_threshold = 4;
size_t host_indifferent_history = 4u;
auto persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), host_indifferent_history,
host_indifferent_threshold);
SetPersistentRule(std::move(persistent_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(false /* null_opt_out */);
allowed_types.clear();
allowed_types[0] = 0;
std::unique_ptr<BlacklistData> data = std::make_unique<BlacklistData>(
nullptr,
std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromSeconds(365),
host_indifferent_history,
host_indifferent_threshold),
nullptr, nullptr, 0, std::move(allowed_types));
base::SimpleTestClock test_clock;
for (int i = 0; i < host_indifferent_threshold; ++i) {
test_clock.Advance(base::TimeDelta::FromSeconds(1));
data->AddEntry(kTestHost1, true, 0, test_clock.Now(), true);
}
std::unique_ptr<TestOptOutStore> opt_out_store =
std::make_unique<TestOptOutStore>();
opt_out_store->SetBlacklistData(std::move(data));
EXPECT_FALSE(blacklist_delegate_.user_blacklisted());
allowed_types.clear();
allowed_types[1] = 0;
auto black_list = std::make_unique<TestOptOutBlacklist>(
std::move(opt_out_store), &test_clock, &blacklist_delegate_);
black_list->SetAllowedTypes(std::move(allowed_types));
persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), host_indifferent_history,
host_indifferent_threshold);
black_list->SetPersistentRule(std::move(persistent_policy));
black_list->Init();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(blacklist_delegate_.user_blacklisted());
}
TEST_F(OptOutBlacklistTest, ObserverIsNotifiedOfHistoricalBlacklistedHosts) {
// Tests the black list behavior when a non-null OptOutStore is passed in.
int host_indifferent_threshold = 2;
size_t host_indifferent_history = 4u;
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), host_indifferent_history,
host_indifferent_threshold);
SetHostRule(std::move(host_policy), 5);
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(false /* null_opt_out */);
base::SimpleTestClock test_clock;
allowed_types.clear();
allowed_types[static_cast<int>(1)] = 0;
std::unique_ptr<BlacklistData> data = std::make_unique<BlacklistData>(
nullptr, nullptr,
std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromDays(365),
host_indifferent_history,
host_indifferent_threshold),
nullptr, 2, std::move(allowed_types));
test_clock.Advance(base::TimeDelta::FromSeconds(1));
data->AddEntry(kTestHost1, true, static_cast<int>(1), test_clock.Now(), true);
test_clock.Advance(base::TimeDelta::FromSeconds(1));
data->AddEntry(kTestHost1, true, static_cast<int>(1), test_clock.Now(), true);
base::Time blacklisted_time = test_clock.Now();
base::RunLoop().RunUntilIdle();
std::vector<BlacklistReason> reasons;
EXPECT_NE(BlacklistReason::kAllowed,
data->IsAllowed(kTestHost1, static_cast<int>(1), false,
test_clock.Now(), &reasons));
// Host |url_b| is not blacklisted.
test_clock.Advance(base::TimeDelta::FromSeconds(1));
data->AddEntry(kTestHost2, true, static_cast<int>(1), test_clock.Now(), true);
std::unique_ptr<TestOptOutStore> opt_out_store =
std::make_unique<TestOptOutStore>();
opt_out_store->SetBlacklistData(std::move(data));
allowed_types.clear();
allowed_types[static_cast<int>(1)] = 0;
auto black_list = std::make_unique<TestOptOutBlacklist>(
std::move(opt_out_store), &test_clock, &blacklist_delegate_);
black_list->SetAllowedTypes(std::move(allowed_types));
host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), host_indifferent_history,
host_indifferent_threshold);
black_list->SetPersistentRule(std::move(host_policy));
black_list->Init();
base::RunLoop().RunUntilIdle();
ASSERT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(1));
EXPECT_EQ(blacklisted_time,
blacklist_delegate_.blacklisted_hosts().find(kTestHost1)->second);
}
TEST_F(OptOutBlacklistTest, PassedReasonsWhenBlacklistDataNotLoaded) {
// Test that IsLoadedAndAllow, push checked BlacklistReasons to the
// |passed_reasons| vector.
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(false /* null_opt_out */);
EXPECT_EQ(
BlacklistReason::kBlacklistNotLoaded,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(0UL, passed_reasons_.size());
}
TEST_F(OptOutBlacklistTest, PassedReasonsWhenUserRecentlyOptedOut) {
// Test that IsLoadedAndAllow, push checked BlacklistReasons to the
// |passed_reasons| vector.
auto session_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromSeconds(5), 1u, 1);
SetSessionRule(std::move(session_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
black_list_->AddEntry(kTestHost1, true, 1);
EXPECT_EQ(
BlacklistReason::kUserOptedOutInSession,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
EXPECT_EQ(1UL, passed_reasons_.size());
EXPECT_EQ(BlacklistReason::kBlacklistNotLoaded, passed_reasons_[0]);
}
TEST_F(OptOutBlacklistTest, PassedReasonsWhenUserBlacklisted) {
// Test that IsLoadedAndAllow, push checked BlacklistReasons to the
// |passed_reasons| vector.
const std::string hosts[] = {
"http://www.url_0.com", "http://www.url_1.com", "http://www.url_2.com",
"http://www.url_3.com",
};
auto session_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromSeconds(1), 1u, 1);
SetSessionRule(std::move(session_policy));
auto persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 4);
SetPersistentRule(std::move(persistent_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
test_clock_.Advance(base::TimeDelta::FromSeconds(1));
for (auto host : hosts) {
black_list_->AddEntry(host, true, 1);
}
test_clock_.Advance(base::TimeDelta::FromSeconds(2));
EXPECT_EQ(
BlacklistReason::kUserOptedOutInGeneral,
black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
BlacklistReason expected_reasons[] = {
BlacklistReason::kBlacklistNotLoaded,
BlacklistReason::kUserOptedOutInSession,
};
EXPECT_EQ(base::size(expected_reasons), passed_reasons_.size());
for (size_t i = 0; i < passed_reasons_.size(); i++) {
EXPECT_EQ(expected_reasons[i], passed_reasons_[i]);
}
}
TEST_F(OptOutBlacklistTest, PassedReasonsWhenHostBlacklisted) {
// Test that IsLoadedAndAllow, push checked BlacklistReasons to the
// |passed_reasons| vector.
auto session_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(5), 3u, 3);
SetSessionRule(std::move(session_policy));
auto persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 4);
SetPersistentRule(std::move(persistent_policy));
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), 4u, 2);
SetHostRule(std::move(host_policy), 2);
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
black_list_->AddEntry(kTestHost1, true, 1);
black_list_->AddEntry(kTestHost1, true, 1);
EXPECT_EQ(
BlacklistReason::kUserOptedOutOfHost,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
BlacklistReason expected_reasons[] = {
BlacklistReason::kBlacklistNotLoaded,
BlacklistReason::kUserOptedOutInSession,
BlacklistReason::kUserOptedOutInGeneral,
};
EXPECT_EQ(base::size(expected_reasons), passed_reasons_.size());
for (size_t i = 0; i < passed_reasons_.size(); i++) {
EXPECT_EQ(expected_reasons[i], passed_reasons_[i]);
}
}
TEST_F(OptOutBlacklistTest, PassedReasonsWhenAllowed) {
// Test that IsLoadedAndAllow, push checked BlacklistReasons to the
// |passed_reasons| vector.
auto session_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromSeconds(1), 1u, 1);
SetSessionRule(std::move(session_policy));
auto persistent_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(365), 4u, 4);
SetPersistentRule(std::move(persistent_policy));
auto host_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), 4u, 4);
SetHostRule(std::move(host_policy), 1);
auto type_policy = std::make_unique<BlacklistData::Policy>(
base::TimeDelta::FromDays(30), 4u, 4);
SetTypeRule(std::move(type_policy));
BlacklistData::AllowedTypesAndVersions allowed_types;
allowed_types.insert({1, 0});
SetAllowedTypes(std::move(allowed_types));
StartTest(true /* null_opt_out */);
EXPECT_EQ(
BlacklistReason::kAllowed,
black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
BlacklistReason expected_reasons[] = {
BlacklistReason::kBlacklistNotLoaded,
BlacklistReason::kUserOptedOutInSession,
BlacklistReason::kUserOptedOutInGeneral,
BlacklistReason::kUserOptedOutOfHost,
BlacklistReason::kUserOptedOutOfType,
};
EXPECT_EQ(base::size(expected_reasons), passed_reasons_.size());
for (size_t i = 0; i < passed_reasons_.size(); i++) {
EXPECT_EQ(expected_reasons[i], passed_reasons_[i]);
}
}
} // namespace
} // namespace blacklist