chromium/components/autofill/core/browser/form_forest_unittest.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/autofill/core/browser/form_forest.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/check_deref.h"
#include "base/containers/contains.h"
#include "base/containers/to_vector.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/form_forest_test_api.h"
#include "components/autofill/core/browser/form_forest_util_inl.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/common/form_data_test_api.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

FrameData;
FrameDataSet;

AllOf;
ByRef;
ElementsAre;
ElementsAreArray;
Eq;
Field;
Matcher;
Pointee;
Property;
UnorderedElementsAreArray;

namespace autofill::internal {
namespace {

// Matchers.

auto Equals(const FormFieldData& exp);
auto Equals(const FormData& exp);
auto Equals(const FrameData& exp);

template <typename T>
auto ArrayEquals(const std::vector<T>& exp) {}

template <typename T>
auto UnorderedArrayEquals(const std::vector<T>& exp) {}

// The relevant attributes are FormFieldData::global_id(), FormFieldData::value.
// We additionally compare a few more attributes just for safety.
auto Equals(const FormFieldData& exp) {}

// The relevant attributes are FormData::global_id(), FormData::fields.
// We additionally compare a few more attributes just for safety.
auto Equals(const FormData& exp) {}

// Compares all attributes of FrameData.
auto Equals(const FrameData& exp) {}

// Deep comparison of the unique_ptrs in a FrameDataSet.
auto Equals(const FrameDataSet& exp) {}

// Compares all attributes of FormForest. (Since frame_datas_ is private, we use
// its accessor.)
auto Equals(const FormForest& exp) {}

// Test form.

// The basic test form is a credit card form with six fields: first name, last
// name, number, month, year, CVC.
FormData CreateForm() {}

// Creates a field type map for the form with N >= 0 repetitions of the fields
// from CreateForm().
auto CreateFieldTypeMap(const FormData& form) {}

// A profile is a 6-bit integer, whose bits indicate different values of first
// and last name, credit card number, expiration month, expiration year, CVC.
Profile;
WithoutValues;

// Fills the fields 0..5 of |form| with data according to |profile|, the
// fields 6..11 with |profile|+1, etc.
FormData WithValues(FormData form, Profile profile = Profile(0)) {}

// Utility functions and constants.

url::Origin Origin(const GURL& url) {}

url::Origin Origin(std::string_view url) {}

// Use strings for non-opaque origins and URLs because constructors must not be
// called before the test is set up.
const std::string kMainUrl("https://main.frame.com/");
const std::string kIframeUrl("https://iframe.frame.com/");
const std::string kOtherUrl("https://other.frame.com/");

FrameDataSet& frame_datas(FormForest& ff) {}

// Flattens a vector by concatenating the elements of the outer vector.
template <typename T>
std::vector<T> Flattened(const std::vector<std::vector<T>>& xs) {}

// Computes all permutations of |xs|.
// Intended for testing::ValuesIn().
template <typename T>
std::vector<std::vector<T>> Permutations(const std::vector<T>& xs) {}

// Computes the permutations of |xs| and concatenates each permutation.
// For example,
//   FlattenedPermutations({{"a", "b"}, {"x", "y"}})
// returns
//   { {"a", "b", "x", "y"},
//     {"x", "y", "a", "b"} }
// because
//   Permutations({{"a", "b"}, {"x", "y"}})
// returns
//   { {{"a", "b"}, {"x", "y"}},
//     {{"x", "y"}, {"a", "b"}} }
// and
//   Flatten({{"a", "b"}, {"x", "y"}})
// returns
//   {"a", "b", "x", "y"}.
// Intended for testing::ValuesIn(), in particular for
// FormForestTestUpdateOrder.
template <typename T>
std::vector<std::vector<T>> FlattenedPermutations(
    const std::vector<std::vector<T>>& xs) {}

// Mimics typical //content layer behaviour:
// - A driver identifies
//    - a same-origin child by its LocalFrameToken and
//    - a cross-origin child by a RemoteFrameToken.
// - A parent driver can inherit, enable, or disable the `shared-autofill`
//   permission in each descendant frames.
class FakeAutofillDriver : public TestAutofillDriver {};

// Fundamental test fixtures.

// Test fixture for all FormForest tests.
//
// Within FormForestTest, we use RemoteFrameTokens only to test scenarios where
// the token cannot be resolved to a LocalFrameToken. In any other case, frames
// shall have LocalFrameTokens. This simplifies the mocking machinery needed
// (that is to say, I couldn't figure out how to mock frames with
// RemoteFrameTokens.)
class FormForestTest : public testing::Test {};

// Test fixture with a mocked frame/form tree.
//
// FrameInfo and FormInfo represent mocked forms and can be syntactically
// arranged in a tree structure using designated initializers.
class FormForestTestWithMockedTree : public FormForestTest {};

// Tests of FormForest::UpdateTreeOfRendererForm().

class FormForestTestUpdateTree : public FormForestTestWithMockedTree {};

// Tests that different root forms are not merged.
TEST_F(FormForestTestUpdateTree, MultipleRoots) {}

// Tests that (only) for forms with unseen parent form,
// TriggerFormExtractionInDriverFrame() is called on the parent frame.
TEST_F(FormForestTestUpdateTree, TriggerFormExtractionInDriverFrame) {}

// Tests that at most 64 descendants are flattened into their root.
//
// The test creates a single root form (FormName(0)) with 30 child frames, each
// of which contains 3 forms, so there's a total of 90 forms.
// UpdateTreeOfRendererForm() flattens (only) the first 64 of these descendant
// forms.
TEST_F(FormForestTestUpdateTree, SizeLimit) {}

FormNameVector;

// Parameterized by a list of forms, which in this order are added to the
// FormForest.
// Note that among the forms from the same form, the order of calling
// UpdateTreeOfRendererForm() matters.
// Hence, when generating permutations, use FlattenedPermutations() to keep the
// forms from the same frame in stable order.
class FormForestTestUpdateOrder
    : public FormForestTestUpdateTree,
      public ::testing::WithParamInterface<FormNameVector> {};

class FormForestTestUpdateVerticalOrder : public FormForestTestUpdateOrder {};

// Tests that children and grandchildren are merged into their root form.
TEST_P(FormForestTestUpdateVerticalOrder, Test) {}

INSTANTIATE_TEST_SUITE_P();

class FormForestTestUpdateHorizontalMultiFormSingleFrameOrder
    : public FormForestTestUpdateOrder {};

// Tests that siblings from the same frames are merged into their root form.
TEST_P(FormForestTestUpdateHorizontalMultiFormSingleFrameOrder, Test) {}

INSTANTIATE_TEST_SUITE_P();

class FormForestTestUpdateHorizontalMultiFrameSingleFormOrder
    : public FormForestTestUpdateOrder {};

// Tests that siblings from different frames are merged into their root form.
TEST_P(FormForestTestUpdateHorizontalMultiFrameSingleFormOrder, Test) {}

INSTANTIATE_TEST_SUITE_P();

class FormForestTestUpdateHorizontalMultiFormMultiFrameOrder
    : public FormForestTestUpdateOrder {};

// Tests that siblings from multiple and the same frame are merged into their
// root form.
TEST_P(FormForestTestUpdateHorizontalMultiFormMultiFrameOrder, Test) {}

INSTANTIATE_TEST_SUITE_P();

ChildFramePredecessors;

// Parameterized by the indices of the fields that precede child frames.
class FormForestTestUpdateSplitForm
    : public FormForestTestUpdateTree,
      public ::testing::WithParamInterface<ChildFramePredecessors> {};

// Tests that fields of subforms are inserted into the parent form at the
// index as specified by FormData::child_frame_predecessors.
TEST_P(FormForestTestUpdateSplitForm, Test) {}

INSTANTIATE_TEST_SUITE_P();

class FormForestTestUpdateComplexOrder : public FormForestTestUpdateOrder {};

// Tests for a complex tree that all descendants are merged into their root.
TEST_P(FormForestTestUpdateComplexOrder, Test) {}

INSTANTIATE_TEST_SUITE_P();

// Tests that erasing a form removes the form and its fields.
TEST_F(FormForestTestUpdateTree, EraseForm_FieldRemoval) {}

// Tests that erasing a frame unsets the children's FrameData::parent_form
// pointer.
TEST_F(FormForestTestUpdateTree, EraseForm_ParentReset) {}

class FormForestTestUpdateEraseFrame
    : public FormForestTestUpdateTree,
      public ::testing::WithParamInterface<bool> {};

// Tests that erasing a frame removes its form and fields.
TEST_P(FormForestTestUpdateEraseFrame, EraseFrame_FieldRemoval) {}

// Tests that erasing a frame unsets the children's FrameData::parent_form
// pointer.
TEST_P(FormForestTestUpdateEraseFrame, EraseFrame_ParentReset) {}

INSTANTIATE_TEST_SUITE_P();

// Parameterized with a source and an optional target form and field index.
class FormForestTestUpdateFieldChange : public FormForestTestUpdateTree {};

struct FieldSpec {};

// Removes a field according to the parameter.
class FormForestTestUpdateFieldRemove
    : public FormForestTestUpdateFieldChange,
      public ::testing::WithParamInterface<FieldSpec> {};

// Tests that removing fields from a form is reflected in the form tree.
TEST_P(FormForestTestUpdateFieldRemove, Test) {}

INSTANTIATE_TEST_SUITE_P();

// Adds a new field according to the parameter.
class FormForestTestUpdateFieldAdd
    : public FormForestTestUpdateFieldChange,
      public ::testing::WithParamInterface<FieldSpec> {};

// Tests that adding a field to forms is reflected in the form tree.
TEST_P(FormForestTestUpdateFieldAdd, Test) {}

INSTANTIATE_TEST_SUITE_P();

struct FieldMoveSpec {};

// Moves a field from one form to another according to the parameter.
class FormForestTestUpdateFieldMove
    : public FormForestTestUpdateFieldChange,
      public ::testing::WithParamInterface<FieldMoveSpec> {};

// Tests that moving fields between forms (of the same frame) is reflected in
// the form tree.
TEST_P(FormForestTestUpdateFieldMove, Test) {}

INSTANTIATE_TEST_SUITE_P();

// Tests that UpdateTreeOfRendererForm() converges, that is, multiple calls are
// no-ops.
TEST_F(FormForestTestUpdateTree, Converge) {}

// Tests that removing a frame from FormData::child_frames removes the fields
// (but not the FrameData; this is taken care of by EraseFormsOfFrame()).
TEST_F(FormForestTestUpdateTree, RemoveFrame) {}

// Tests of FormForest::GetBrowserForm().

class FormForestTestFlatten : public FormForestTestWithMockedTree {};

// Tests that flattening a single frame is the identity.
TEST_F(FormForestTestFlatten, SingleFrame) {}

class FormForestTestFlattenHierarchy
    : public FormForestTestFlatten,
      public ::testing::WithParamInterface<std::string> {};

// Tests that a non-trivial tree is flattened into the root.
TEST_P(FormForestTestFlattenHierarchy, TwoFrames) {}

INSTANTIATE_TEST_SUITE_P();

// Tests of FormForest::GetRendererFormsOfBrowserFields().

class FormForestTestUnflatten : public FormForestTestWithMockedTree {};

// Test that solitaire main frame forms are filled as usual.
TEST_F(FormForestTestUnflatten, MainFrame) {}

// Test that child frame forms are filled as usual.
TEST_F(FormForestTestUnflatten, ChildFrame) {}

// Test that a tree of forms is filled (assuming same origins), but other
// neighboring trees are not.
TEST_F(FormForestTestUnflatten, LargeTree) {}

// Tests that (only) frames from the same origin are filled.
TEST_F(FormForestTestUnflatten, SameOriginPolicy) {}

// Tests that (only) frames from the same origin are filled.
TEST_F(FormForestTestUnflatten, SameOriginPolicyNoValuesErased) {}

// Tests that even if a different-origin frame interrupts two same-origin
// frames, they are filled together.
TEST_F(FormForestTestUnflatten, InterruptedSameOriginPolicy) {}

// Tests that (only) non-sensitive fields are filled across origin into the main
// frame's origin (since the main frame has the shared-autofill policy by
// default).
TEST_F(FormForestTestUnflatten, MainOriginPolicy) {}

// Tests that no fields are filled across origin into frames where
// shared-autofill is disabled (not even into non-sensitive fields).
TEST_F(FormForestTestUnflatten, MainOriginPolicyWithoutSharedAutofill) {}

// Fixture for the shared-autofill policy tests.
class FormForestTestUnflattenSharedAutofillPolicy
    : public FormForestTestUnflatten {};

// Tests filling into frames with shared-autofill policy from the main origin.
TEST_F(FormForestTestUnflattenSharedAutofillPolicy, FromMainOrigin) {}

// Tests filling into frames with shared-autofill policy from the main origin.
TEST_F(FormForestTestUnflattenSharedAutofillPolicy, FromOtherOrigin) {}

// Tests irreflexivity, asymmetry, transitivity of FrameData less-than relation.
TEST_F(FormForestTest, FrameDataComparator) {}

// Tests of utility functions.

struct ForEachInSetDifferenceTestParam {};

class ForEachInSetDifferenceTest
    : public ::testing::Test,
      public ::testing::WithParamInterface<ForEachInSetDifferenceTestParam> {};

bool operator==(ForEachInSetDifferenceTest::Dummy x,
                ForEachInSetDifferenceTest::Dummy y) {}

// Tests that for_each_in_set_difference() calls the callback for the expected
// elements and checks its number of comparisons.
TEST_P(ForEachInSetDifferenceTest, Test) {}

INSTANTIATE_TEST_SUITE_P();

}  // namespace
}  // namespace autofill::internal