Skip to content

Commit

Permalink
Reland "[Autofill] Add tests for parsing patterns."
Browse files Browse the repository at this point in the history
This is a reland of commit 6177ea7

Original change's description:
> [Autofill] Add tests for parsing patterns.
>
> This CL adds unit tests for
> FormStructure::ParseFieldTypesWithPatterns() and a test for the
> dereferencing operator of MatchPatternRef.
>
> Bug: 1312026
> Change-Id: I776c9a382593c1324762949cdba9cdb6a2d058a8
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3632551
> Reviewed-by: Christos Froussios <cfroussios@chromium.org>
> Commit-Queue: Christoph Schwering <schwering@google.com>
> Cr-Commit-Position: refs/heads/main@{#1001546}

Bug: 1312026, 1324385
Change-Id: I61bc05e61ce49e316ad835279828bb783e0a884e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3640957
Auto-Submit: Christoph Schwering <schwering@google.com>
Reviewed-by: Christos Froussios <cfroussios@chromium.org>
Commit-Queue: Christoph Schwering <schwering@google.com>
Cr-Commit-Position: refs/heads/main@{#1002561}
  • Loading branch information
schwering authored and Chromium LUCI CQ committed May 12, 2022
1 parent 892e2b5 commit 78990b1
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
#include "base/logging.h"
#include "base/ranges/ranges.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_regexes.h"
#include "components/autofill/core/browser/form_parsing/buildflags.h"
#include "components/autofill/core/browser/form_parsing/regex_patterns_inl.h"
#include "components/autofill/core/common/autofill_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::Contains;
using ::testing::Each;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::IsSupersetOf;
using ::testing::Not;
Expand All @@ -34,6 +35,8 @@ namespace autofill {

class MatchPatternRefTestApi {
public:
using UnderlyingType = MatchPatternRef::UnderlyingType;

explicit MatchPatternRefTestApi(MatchPatternRef p) : p_(p) {}

absl::optional<MatchPatternRef> MakeSupplementary() const {
Expand All @@ -42,11 +45,9 @@ class MatchPatternRefTestApi {
return MatchPatternRef(true, index());
}

MatchPatternRef::UnderlyingType is_supplementary() const {
return p_.is_supplementary();
}
UnderlyingType is_supplementary() const { return p_.is_supplementary(); }

MatchPatternRef::UnderlyingType index() const { return p_.index(); }
UnderlyingType index() const { return p_.index(); }

private:
MatchPatternRef p_;
Expand Down Expand Up @@ -93,10 +94,14 @@ bool IsEmpty(const char* s) {
} // namespace

bool operator==(MatchPatternRef a, MatchPatternRef b) {
return test_api(a).is_supplementary() == test_api(b).is_supplementary() ||
return test_api(a).is_supplementary() == test_api(b).is_supplementary() &&
test_api(a).index() == test_api(b).index();
}

bool operator!=(MatchPatternRef a, MatchPatternRef b) {
return !(a == b);
}

void PrintTo(MatchPatternRef p, std::ostream* os) {
*os << "MatchPatternRef(" << test_api(p).is_supplementary() << ","
<< test_api(p).index() << ")";
Expand All @@ -121,6 +126,51 @@ INSTANTIATE_TEST_SUITE_P(RegexPatternsTest,
#endif
));

// The parameter is the index of a MatchPatternRef.
class MatchPatternRefInternalsTest
: public ::testing::TestWithParam<MatchPatternRefTestApi::UnderlyingType> {
public:
MatchPatternRefTestApi::UnderlyingType index() const { return GetParam(); }
};

INSTANTIATE_TEST_SUITE_P(RegexPatternsTest,
MatchPatternRefInternalsTest,
::testing::Values(0, 1, 2, 123, 1000, 2000));

// Tests MatchPatternRef's index() and is_supplementary().
TEST_P(MatchPatternRefInternalsTest, MatchPatternRef) {
MatchPatternRef a = MakeMatchPatternRef(false, index());
MatchPatternRef b = MakeMatchPatternRef(true, index());
EXPECT_EQ(a, a);
EXPECT_EQ(b, b);
EXPECT_NE(a, b);
EXPECT_EQ(test_api(a).index(), index());
EXPECT_EQ(test_api(b).index(), index());
EXPECT_FALSE(test_api(a).is_supplementary());
EXPECT_TRUE(test_api(b).is_supplementary());
}

// Tests MatchPatternRef's dereference operator.
//
// Since we want to test that supplementary patterns only contain
// MatchAttribute::kName, choose `index` such that `kPatterns[0]` contains
// MatchAttribute::kLabel.
TEST_F(RegexPatternsTest, MatchPatternRefDereference) {
MatchPatternRefTestApi::UnderlyingType index = 0;
ASSERT_TRUE(
kPatterns[0].match_field_attributes.contains(MatchAttribute::kLabel));
MatchPatternRef a = MakeMatchPatternRef(false, index);
MatchPatternRef b = MakeMatchPatternRef(true, index);
EXPECT_TRUE((*a).positive_pattern);
EXPECT_TRUE((*a).negative_pattern);
EXPECT_EQ((*a).positive_pattern, (*b).positive_pattern);
EXPECT_EQ((*a).negative_pattern, (*b).negative_pattern);
EXPECT_EQ((*a).positive_score, (*b).positive_score);
EXPECT_EQ((*a).match_field_input_types, (*b).match_field_input_types);
EXPECT_THAT((*a).match_field_attributes, Contains(MatchAttribute::kLabel));
EXPECT_THAT((*b).match_field_attributes, ElementsAre(MatchAttribute::kName));
}

// Tests that for a given pattern name, the pseudo-language-code "" contains the
// patterns of all real languages.
TEST_P(RegexPatternsTest, PseudoLanguageIsUnionOfLanguages) {
Expand Down
1 change: 1 addition & 0 deletions components/autofill/core/browser/form_structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ class FormStructure {
std::vector<std::unique_ptr<AutofillField>>::const_iterator begin() const {
return fields_.begin();
}

std::vector<std::unique_ptr<AutofillField>>::const_iterator end() const {
return fields_.end();
}
Expand Down
9 changes: 9 additions & 0 deletions components/autofill/core/browser/form_structure_test_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class FormStructureTestApi {
DCHECK(form_structure_);
}

const std::vector<std::unique_ptr<AutofillField>>& fields() {
return form_structure_->fields_;
}

void IdentifySections(bool has_author_specified_sections) {
form_structure_->IdentifySections(has_author_specified_sections);
}
Expand All @@ -50,6 +54,11 @@ class FormStructureTestApi {
return it != form_structure_->phone_rationalized_.end() && it->second;
}

void ParseFieldTypesWithPatterns(PatternSource pattern_source) {
return form_structure_->ParseFieldTypesWithPatterns(pattern_source,
nullptr);
}

private:
FormStructure* form_structure_;
};
Expand Down
94 changes: 89 additions & 5 deletions components/autofill/core/browser/form_structure_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "components/autofill/core/browser/autofill_form_test_utils.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_parsing/buildflags.h"
#include "components/autofill/core/browser/form_structure_test_api.h"
#include "components/autofill/core/browser/proto/api_v1.pb.h"
#include "components/autofill/core/browser/randomized_encoder.h"
Expand All @@ -36,18 +37,23 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using base::ASCIIToUTF16;
using ::base::ASCIIToUTF16;
using ::testing::AllOf;
using ::testing::Each;
using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::Not;
using ::testing::Pointee;
using ::testing::ResultOf;
using ::testing::Truly;
using ::testing::UnorderedElementsAre;
using version_info::GetProductNameAndVersionForUserAgent;
using ::version_info::GetProductNameAndVersionForUserAgent;

namespace autofill {

using features::kAutofillLabelAffixRemoval;
using mojom::SubmissionIndicatorEvent;
using mojom::SubmissionSource;
using autofill::features::kAutofillLabelAffixRemoval;
using autofill::mojom::SubmissionIndicatorEvent;
using autofill::mojom::SubmissionSource;

namespace {

Expand Down Expand Up @@ -114,6 +120,15 @@ FormStructureTestApi test_api(FormStructure* form_structure) {
return FormStructureTestApi(form_structure);
}

constexpr DenseSet<PatternSource> kAllPatternSources {
#if !BUILDFLAG(USE_INTERNAL_AUTOFILL_HEADERS)
PatternSource::kLegacy
#else
PatternSource::kLegacy, PatternSource::kDefault, PatternSource::kExperimental,
PatternSource::kNextGen
#endif
};

} // namespace

class FormStructureTestImpl : public test::FormStructureTest {
Expand Down Expand Up @@ -158,6 +173,49 @@ class ParameterizedFormStructureTest
: public FormStructureTestImpl,
public testing::WithParamInterface<bool> {};

class FormStructureTest_ForPatternSource
: public FormStructureTestImpl,
public testing::WithParamInterface<PatternSource> {
public:
FormStructureTest_ForPatternSource() {
scoped_feature_list_.InitWithFeaturesAndParameters(
{base::test::ScopedFeatureList::FeatureAndParams(
features::kAutofillParsingPatternProvider,
{{"prediction_source", pattern_source_as_string()}})},
{});
}

PatternSource pattern_source() const { return GetParam(); }

std::string pattern_source_as_string() const {
switch (pattern_source()) {
case PatternSource::kLegacy:
return "legacy";
#if BUILDFLAG(USE_INTERNAL_AUTOFILL_HEADERS)
case PatternSource::kDefault:
return "default";
case PatternSource::kExperimental:
return "experimental";
case PatternSource::kNextGen:
return "nextgen";
#endif
}
}

DenseSet<PatternSource> other_pattern_sources() const {
DenseSet<PatternSource> patterns = kAllPatternSources;
patterns.erase(pattern_source());
return patterns;
}

private:
base::test::ScopedFeatureList scoped_feature_list_;
};

INSTANTIATE_TEST_SUITE_P(FormStructureTest,
FormStructureTest_ForPatternSource,
::testing::ValuesIn(kAllPatternSources));

TEST_F(FormStructureTestImpl, FieldCount) {
CheckFormStructureTestData({{{.description_for_logging = "FieldCount",
.fields = {{.role = ServerFieldType::USERNAME},
Expand Down Expand Up @@ -8548,4 +8606,30 @@ TEST_F(FormStructureTestImpl, FindFieldsEligibleForManualFilling) {
FormStructure::FindFieldsEligibleForManualFilling(forms));
}

// Tests that ParseFieldTypesWithPatterns() sets (only) the PatternSource.
TEST_P(FormStructureTest_ForPatternSource, ParseFieldTypesWithPatterns) {
FormData form;
test::CreateTestAddressFormData(&form);
FormStructure form_structure(form);
test_api(&form_structure).ParseFieldTypesWithPatterns(pattern_source());
ASSERT_THAT(test_api(&form_structure).fields(), Not(IsEmpty()));

auto get_heuristic_type = [&](const AutofillField& field) {
return field.heuristic_type(pattern_source());
};
EXPECT_THAT(
test_api(&form_structure).fields(),
Each(Pointee(ResultOf(get_heuristic_type,
AllOf(Not(NO_SERVER_DATA), Not(UNKNOWN_TYPE))))));

for (PatternSource other_pattern_source : other_pattern_sources()) {
auto get_heuristic_type = [&](const AutofillField& field) {
return field.heuristic_type(other_pattern_source);
};
EXPECT_THAT(test_api(&form_structure).fields(),
Each(Pointee(ResultOf(get_heuristic_type, NO_SERVER_DATA))))
<< "PatternSource = " << static_cast<int>(other_pattern_source);
}
}

} // namespace autofill

0 comments on commit 78990b1

Please sign in to comment.