blob: 74c545d59bde7fc37b4a11954b2172c151721631 [file] [log] [blame]
// Copyright 2021 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/autofill_assistant/browser/script_parameters.h"
#include "base/containers/flat_map.h"
#include "components/autofill_assistant/browser/test_util.h"
#include "components/autofill_assistant/browser/user_data.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::UnorderedElementsAreArray;
TEST(ScriptParametersTest, Create) {
ScriptParameters parameters = {{{"key_a", "value_a"}, {"key_b", "value_b"}}};
EXPECT_THAT(
parameters.ToProto(),
UnorderedElementsAreArray(base::flat_map<std::string, std::string>(
{{"key_a", "value_a"}, {"key_b", "value_b"}})));
}
TEST(ScriptParametersTest, MergeEmpty) {
ScriptParameters merged;
EXPECT_THAT(merged.ToProto(), IsEmpty());
merged.MergeWith(ScriptParameters());
EXPECT_THAT(merged.ToProto(), IsEmpty());
}
TEST(ScriptParametersTest, MergeEmptyWithNonEmpty) {
ScriptParameters empty;
empty.MergeWith({{{"key_a", "value_a"}}});
EXPECT_THAT(
empty.ToProto(),
UnorderedElementsAreArray(
base::flat_map<std::string, std::string>({{"key_a", "value_a"}})));
}
TEST(ScriptParametersTest, MergeNonEmptyWithEmpty) {
ScriptParameters parameters = {{{"key_a", "value_a"}}};
parameters.MergeWith(ScriptParameters());
EXPECT_THAT(
parameters.ToProto(),
UnorderedElementsAreArray(
base::flat_map<std::string, std::string>({{"key_a", "value_a"}})));
}
TEST(ScriptParametersTest, MergeNonEmptyWithNonEmpty) {
ScriptParameters parameters_a = {{{"key_a", "value_a"}}};
ScriptParameters parameters_b = {
{{"key_a", "value_a_changed"}, {"key_b", "value_b"}}};
parameters_a.MergeWith(parameters_b);
EXPECT_THAT(
parameters_a.ToProto(),
UnorderedElementsAreArray(base::flat_map<std::string, std::string>(
{{"key_a", "value_a"}, {"key_b", "value_b"}})));
}
TEST(ScriptParametersTest, TriggerScriptAllowList) {
ScriptParameters parameters = {{{"DEBUG_BUNDLE_ID", "12345"},
{"key_a", "value_a"},
{"DEBUG_BUNDLE_VERSION", "version"},
{"DEBUG_SOCKET_ID", "678"},
{"FALLBACK_BUNDLE_ID", "fallback_id"},
{"key_b", "value_b"},
{"FALLBACK_BUNDLE_VERSION", "fallback_ver"},
{"INTENT", "FAKE_INTENT"},
{"CAPABILITIES_REQUEST_ID", "123456789"}}};
EXPECT_THAT(
parameters.ToProto(/* only_non_sensitive_allowlisted = */ false),
UnorderedElementsAreArray(base::flat_map<std::string, std::string>(
{{"DEBUG_BUNDLE_ID", "12345"},
{"key_a", "value_a"},
{"DEBUG_BUNDLE_VERSION", "version"},
{"DEBUG_SOCKET_ID", "678"},
{"FALLBACK_BUNDLE_ID", "fallback_id"},
{"key_b", "value_b"},
{"FALLBACK_BUNDLE_VERSION", "fallback_ver"},
{"INTENT", "FAKE_INTENT"},
{"CAPABILITIES_REQUEST_ID", "123456789"}})));
EXPECT_THAT(
parameters.ToProto(/* only_non_sensitive_allowlisted = */ true),
UnorderedElementsAreArray(base::flat_map<std::string, std::string>(
{{"DEBUG_BUNDLE_ID", "12345"},
{"DEBUG_BUNDLE_VERSION", "version"},
{"DEBUG_SOCKET_ID", "678"},
{"FALLBACK_BUNDLE_ID", "fallback_id"},
{"FALLBACK_BUNDLE_VERSION", "fallback_ver"},
{"INTENT", "FAKE_INTENT"},
{"CAPABILITIES_REQUEST_ID", "123456789"}})));
}
TEST(ScriptParametersTest, SpecialScriptParameters) {
ScriptParameters parameters = {
{{"ENABLED", "true"},
{"USER_EMAIL", "example@chromium.org"},
{"ORIGINAL_DEEPLINK", "https://www.example.com"},
{"TRIGGER_SCRIPT_EXPERIMENT", "true"},
{"START_IMMEDIATELY", "false"},
{"REQUEST_TRIGGER_SCRIPT", "true"},
{"PASSWORD_CHANGE_USERNAME", "fake_username"},
{"OVERLAY_COLORS", "#123456"},
{"ENABLE_TTS", "true"},
{"CALLER", "3"},
{"SOURCE", "4"},
{"EXPERIMENT_IDS", "123,456,789"},
{"FIELD_TRIAL_1", "1234"},
{"FIELD_TRIAL_3", "5555"},
{"RUN_HEADLESS", "true"},
{"USE_ASSISTANT_UI", "false"},
{"DISABLE_RPC_SIGNING", "true"},
{"DETAILS_SHOW_INITIAL", "true"},
{"DETAILS_TITLE", "title"},
{"DETAILS_DESCRIPTION_LINE_1", "line1"},
{"DETAILS_DESCRIPTION_LINE_2", "line2"},
{"DETAILS_DESCRIPTION_LINE_3", "line3"},
{"DETAILS_IMAGE_URL", "image"},
{"DETAILS_IMAGE_ACCESSIBILITY_HINT", "hint"},
{"DETAILS_IMAGE_CLICKTHROUGH_URL", "clickthrough"},
{"DETAILS_TOTAL_PRICE_LABEL", "total"},
{"DETAILS_TOTAL_PRICE", "12"}}};
EXPECT_THAT(parameters.GetEnabled(), Eq(true));
EXPECT_THAT(parameters.GetCallerEmail(), Eq("example@chromium.org"));
EXPECT_THAT(parameters.GetOriginalDeeplink(), Eq("https://www.example.com"));
EXPECT_THAT(parameters.GetTriggerScriptExperiment(), Eq(true));
EXPECT_THAT(parameters.GetStartImmediately(), Eq(false));
EXPECT_THAT(parameters.GetRequestsTriggerScript(), Eq(true));
EXPECT_THAT(parameters.GetPasswordChangeUsername(), Eq("fake_username"));
EXPECT_THAT(parameters.GetOverlayColors(), Eq("#123456"));
EXPECT_THAT(parameters.GetEnableTts(), Eq(true));
EXPECT_THAT(parameters.GetCaller(), Eq(3));
EXPECT_THAT(parameters.GetSource(), Eq(4));
EXPECT_THAT(
parameters.GetExperiments(),
UnorderedElementsAreArray(std::vector<std::string>{"123", "456", "789"}));
EXPECT_THAT(parameters.GetFieldTrialGroup(1), Eq("1234"));
EXPECT_THAT(parameters.GetFieldTrialGroup(3), Eq("5555"));
EXPECT_THAT(parameters.GetFieldTrialGroup(2).has_value(), Eq(false));
EXPECT_THAT(parameters.GetRunHeadless(), Eq(true));
EXPECT_THAT(parameters.GetUseAssistantUi(), Eq(false));
EXPECT_THAT(parameters.GetDisableRpcSigning(), Eq(true));
EXPECT_THAT(parameters.GetDetailsShowInitial(), Eq(true));
EXPECT_THAT(parameters.GetDetailsTitle(), Eq("title"));
EXPECT_THAT(parameters.GetDetailsDescriptionLine1(), Eq("line1"));
EXPECT_THAT(parameters.GetDetailsDescriptionLine2(), Eq("line2"));
EXPECT_THAT(parameters.GetDetailsDescriptionLine3(), Eq("line3"));
EXPECT_THAT(parameters.GetDetailsImageUrl(), Eq("image"));
EXPECT_THAT(parameters.GetDetailsImageAccessibilityHint(), Eq("hint"));
EXPECT_THAT(parameters.GetDetailsImageClickthroughUrl(), Eq("clickthrough"));
EXPECT_THAT(parameters.GetDetailsTotalPriceLabel(), Eq("total"));
EXPECT_THAT(parameters.GetDetailsTotalPrice(), Eq("12"));
}
TEST(ScriptParametersTest, ScriptParameterMatch) {
ScriptParameters parameters = {{{"must_exist_and_exists", "exists"},
{"must_not_exist_and_exists", "exists"},
{"must_match", "matching_value"},
{"must_match_empty", ""}}};
ScriptParameterMatchProto must_exist;
must_exist.set_name("must_exist_and_exists");
must_exist.set_exists(true);
EXPECT_TRUE(parameters.Matches(must_exist));
must_exist.set_name("must_exist_and_doesnt_exist");
EXPECT_FALSE(parameters.Matches(must_exist));
ScriptParameterMatchProto must_not_exist;
must_not_exist.set_name("must_not_exist_and_doesnt_exist");
must_not_exist.set_exists(false);
EXPECT_TRUE(parameters.Matches(must_not_exist));
must_not_exist.set_name("must_not_exist_and_exists");
EXPECT_FALSE(parameters.Matches(must_not_exist));
ScriptParameterMatchProto must_match;
must_match.set_name("must_match");
must_match.set_value_equals("matching_value");
EXPECT_TRUE(parameters.Matches(must_match));
must_match.set_value_equals("not_matching_value");
EXPECT_FALSE(parameters.Matches(must_match));
must_match.set_value_equals("");
EXPECT_FALSE(parameters.Matches(must_match));
must_match.set_name("must_match_doesnt_exist");
EXPECT_FALSE(parameters.Matches(must_match));
ScriptParameterMatchProto must_match_empty;
must_match_empty.set_name("must_match_empty");
must_match_empty.set_value_equals("");
EXPECT_TRUE(parameters.Matches(must_match_empty));
must_match_empty.set_value_equals("not_empty");
EXPECT_FALSE(parameters.Matches(must_match_empty));
}
TEST(ScriptParametersTest, ToProtoRemovesEnabled) {
ScriptParameters parameters = {{{"key_a", "value_a"}, {"ENABLED", "true"}}};
EXPECT_THAT(
parameters.ToProto(/* only_non_sensitive_allowlisted = */ false),
UnorderedElementsAreArray(
base::flat_map<std::string, std::string>({{"key_a", "value_a"}})));
EXPECT_THAT(parameters.ToProto(/* only_non_sensitive_allowlisted = */ true),
IsEmpty());
}
TEST(ScriptParametersTest, ToProtoDoesNotAddDeviceOnlyParameters) {
ScriptParameters parameters = {};
parameters.UpdateDeviceOnlyParameters(
base::flat_map<std::string, std::string>({{"device_only", "secret"}}));
EXPECT_THAT(parameters.ToProto(/* only_non_sensitive_allowlisted = */ false),
IsEmpty());
}
TEST(ScriptParametersTest, WriteToUserDataAddsAllParameters) {
UserData user_data;
ScriptParameters parameters = {{{"key_a", "a"}}};
parameters.UpdateDeviceOnlyParameters(
base::flat_map<std::string, std::string>({{"key_b", "b"}}));
parameters.WriteToUserData(&user_data);
EXPECT_EQ(user_data.GetAdditionalValue("param:key_a")->strings().values(0),
"a");
EXPECT_FALSE(
user_data.GetAdditionalValue("param:key_a")->is_client_side_only());
EXPECT_EQ(user_data.GetAdditionalValue("param:key_b")->strings().values(0),
"b");
EXPECT_TRUE(
user_data.GetAdditionalValue("param:key_b")->is_client_side_only());
}
TEST(ScriptParametersTest,
UpdateDeviceOnlyParametersOverwritesExistingEntries) {
UserData user_data;
ScriptParameters parameters;
parameters.UpdateDeviceOnlyParameters(
base::flat_map<std::string, std::string>(
{{"key_a", "a"}, {"key_b", "b"}}));
parameters.WriteToUserData(&user_data);
EXPECT_EQ(user_data.GetAdditionalValue("param:key_a")->strings().values(0),
"a");
EXPECT_EQ(user_data.GetAdditionalValue("param:key_b")->strings().values(0),
"b");
parameters.UpdateDeviceOnlyParameters(
base::flat_map<std::string, std::string>(
{{"key_a", "new"}, {"key_c", "c"}}));
parameters.WriteToUserData(&user_data);
EXPECT_EQ(user_data.GetAdditionalValue("param:key_a")->strings().values(0),
"new");
EXPECT_EQ(user_data.GetAdditionalValue("param:key_b")->strings().values(0),
"b");
EXPECT_EQ(user_data.GetAdditionalValue("param:key_c")->strings().values(0),
"c");
}
TEST(ScriptParametersTest, InvalidFormat) {
ScriptParameters parameters = {
{{"ENABLED", "not_a_boolean"}, {"CALLER", "not_an_integer"}}};
EXPECT_THAT(parameters.GetEnabled(), Eq(absl::nullopt));
EXPECT_THAT(parameters.GetCaller(), Eq(absl::nullopt));
}
TEST(ScriptParametersTest, MissingValues) {
ScriptParameters parameters;
// Just one test per data type here for brevity.
EXPECT_THAT(parameters.GetEnabled(), Eq(absl::nullopt));
EXPECT_THAT(parameters.GetIntent(), Eq(absl::nullopt));
EXPECT_THAT(parameters.GetCaller(), Eq(absl::nullopt));
EXPECT_THAT(parameters.GetExperiments(), IsEmpty());
}
TEST(ScriptParametersTest, ExperimentIdParsing) {
{
ScriptParameters parameters = {{{"EXPERIMENT_IDS", ""}}};
EXPECT_THAT(parameters.GetExperiments(), IsEmpty());
}
{
ScriptParameters parameters = {{{"EXPERIMENT_IDS", ","}}};
EXPECT_THAT(parameters.GetExperiments(), IsEmpty());
}
{
ScriptParameters parameters = {{{"EXPERIMENT_IDS", ",123,"}}};
EXPECT_THAT(parameters.GetExperiments(),
UnorderedElementsAreArray(std::vector<std::string>{"123"}));
}
{
ScriptParameters parameters = {{{"EXPERIMENT_IDS", "not_an_integer"}}};
EXPECT_THAT(
parameters.GetExperiments(),
UnorderedElementsAreArray(std::vector<std::string>{"not_an_integer"}));
}
}
TEST(ScriptParametersTest, HasExperimentId) {
ScriptParameters parameters = {{{"EXPERIMENT_IDS", "13,123,778"}}};
EXPECT_THAT(
parameters.GetExperiments(),
UnorderedElementsAreArray(std::vector<std::string>{"13", "123", "778"}));
EXPECT_TRUE(parameters.HasExperimentId("13"));
EXPECT_TRUE(parameters.HasExperimentId("123"));
EXPECT_TRUE(parameters.HasExperimentId("778"));
EXPECT_FALSE(parameters.HasExperimentId("1"));
EXPECT_FALSE(parameters.HasExperimentId("42"));
}
} // namespace autofill_assistant