blob: fe7886d377408b33acfed536e0ba3ec25c45fbdf [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/password_manager/core/browser/password_requirements_service.h"
#include <map>
#include "base/logging.h"
#include "base/test/bind_test_util.h"
#include "components/autofill/core/browser/password_requirements_spec_fetcher.h"
#include "components/autofill/core/browser/proto/password_requirements.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace password_manager {
namespace {
class MockPasswordRequirementsSpecFetcher
: public autofill::PasswordRequirementsSpecFetcher {
public:
MockPasswordRequirementsSpecFetcher() = default;
~MockPasswordRequirementsSpecFetcher() override = default;
void Fetch(GURL origin, FetchCallback callback) override {
auto iter = data_to_return_.find(origin);
std::move(callback).Run(iter != data_to_return_.end()
? iter->second
: autofill::PasswordRequirementsSpec());
}
void SetDataToReturn(const GURL& origin,
const autofill::PasswordRequirementsSpec& spec) {
data_to_return_[origin] = spec;
}
private:
std::map<GURL, autofill::PasswordRequirementsSpec> data_to_return_;
};
class PasswordRequirementsServiceTest : public testing::Test {
public:
PasswordRequirementsServiceTest()
: test_origin_("http://www.example.com"),
// Ownership is passed to the |service_| below.
fetcher_ptr_(new MockPasswordRequirementsSpecFetcher()),
service_(std::unique_ptr<MockPasswordRequirementsSpecFetcher>(
fetcher_ptr_)) {}
~PasswordRequirementsServiceTest() override = default;
protected:
// Prepopulated test data.
GURL test_origin_;
autofill::FormSignature test_form_signature_ = 123;
autofill::FieldSignature test_field_signature_ = 22;
// Weak pointer.
MockPasswordRequirementsSpecFetcher* fetcher_ptr_;
PasswordRequirementsService service_;
};
TEST_F(PasswordRequirementsServiceTest, ExerciseEverything) {
// The following specs are names according to the following scheme:
// spec_l${max_length value}_p${priority value}
// values of 0 imply that no value is specified.
// It would be possible to test the behavior with fewer instances than below
// but these are chosen to be representative of what we expect the server
// to send with regards to priorities.
autofill::PasswordRequirementsSpec spec_l0_p0; // empty spec.
autofill::PasswordRequirementsSpec spec_l7_p0;
spec_l7_p0.set_max_length(7u);
autofill::PasswordRequirementsSpec spec_l8_p10;
spec_l8_p10.set_max_length(8u);
spec_l8_p10.set_priority(10);
autofill::PasswordRequirementsSpec spec_l9_p20;
spec_l9_p20.set_max_length(9u);
spec_l9_p20.set_priority(20);
autofill::PasswordRequirementsSpec spec_l10_p30;
spec_l10_p30.set_max_length(10u);
spec_l10_p30.set_priority(30);
struct {
const char* test_name;
autofill::PasswordRequirementsSpec* spec_for_signature = nullptr;
autofill::PasswordRequirementsSpec* spec_for_domain = nullptr;
autofill::PasswordRequirementsSpec* expected;
} tests[] = {
{
.test_name = "No data prefechted", .expected = &spec_l0_p0,
},
{
.test_name = "Only domain wide spec",
.spec_for_domain = &spec_l7_p0,
.expected = &spec_l7_p0,
},
{
.test_name = "Only signature based spec",
.spec_for_signature = &spec_l7_p0,
.expected = &spec_l7_p0,
},
{
.test_name = "Domain spec can override spec based on signature",
.spec_for_signature = &spec_l8_p10,
.spec_for_domain = &spec_l9_p20,
.expected = &spec_l9_p20, // priority 20 trumps priority 10.
},
{
.test_name = "Signature spec can override spec based on domain",
.spec_for_signature = &spec_l10_p30,
.spec_for_domain = &spec_l9_p20,
.expected = &spec_l10_p30, // priority 30 trumps priority 20.
},
{
.test_name = "Dealing with unset priority in domain",
.spec_for_signature = &spec_l8_p10,
.spec_for_domain = &spec_l7_p0, // No prioritiy specified.
.expected = &spec_l8_p10,
},
{
.test_name = "Dealing with unset priority in signature",
.spec_for_signature = &spec_l7_p0, // No prioritiy specified.
.spec_for_domain = &spec_l8_p10,
.expected = &spec_l8_p10,
},
};
for (const auto& test : tests) {
SCOPED_TRACE(test.test_name);
service_.ClearDataForTesting();
// Populate the service with data.
if (test.spec_for_domain) {
fetcher_ptr_->SetDataToReturn(test_origin_, *(test.spec_for_domain));
service_.PrefetchSpec(test_origin_);
}
if (test.spec_for_signature) {
service_.AddSpec(test_form_signature_, test_field_signature_,
*(test.spec_for_signature));
}
// Perform lookup.
auto result = service_.GetSpec(test_origin_, test_form_signature_,
test_field_signature_);
// Validate answer.
EXPECT_EQ(test.expected->has_priority(), result.has_priority());
if (test.expected->has_priority()) {
EXPECT_EQ(test.expected->priority(), result.priority());
}
EXPECT_EQ(test.expected->has_max_length(), result.has_max_length());
if (test.expected->has_max_length()) {
EXPECT_EQ(test.expected->max_length(), result.max_length());
}
}
}
} // namespace
} // namespace password_manager