blob: fc8321b6ba2c787dc3ce2b55fbfa756e54b9dd3c [file] [log] [blame]
// Copyright 2016 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 "chrome/browser/component_updater/sw_reporter_installer_win.h"
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h"
#include "components/chrome_cleaner/public/constants/constants.h"
#include "components/variations/variations_params_manager.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace component_updater {
namespace {
constexpr char kExperimentGroupName[] = "my_test_engine_group";
constexpr char kErrorHistogramName[] = "SoftwareReporter.ExperimentErrors";
constexpr char kExperimentTag[] = "experiment_tag";
constexpr char kMissingTag[] = "missing_tag";
using safe_browsing::SwReporterInvocation;
} // namespace
class SwReporterInstallerTest : public ::testing::Test {
public:
SwReporterInstallerTest()
: launched_callback_(
base::Bind(&SwReporterInstallerTest::SwReporterLaunched,
base::Unretained(this))),
default_version_("1.2.3"),
default_path_(L"C:\\full\\path\\to\\download"),
launched_version_("0.0.0") {}
~SwReporterInstallerTest() override {}
protected:
void SwReporterLaunched(const safe_browsing::SwReporterQueue& invocations,
const base::Version& version) {
ASSERT_TRUE(launched_invocations_.empty());
launched_invocations_ = invocations;
launched_version_ = version;
}
base::FilePath MakeTestFilePath(const base::FilePath& path) const {
return path.Append(L"software_reporter_tool.exe");
}
void ExpectEmptyAttributes(const SwReporterInstallerPolicy& policy) const {
update_client::InstallerAttributes attributes =
policy.GetInstallerAttributes();
EXPECT_TRUE(attributes.empty());
}
// Expects that the SwReporter was launched exactly once, with a session-id
// switch.
void ExpectDefaultInvocation() const {
EXPECT_EQ(default_version_, launched_version_);
ASSERT_EQ(1U, launched_invocations_.size());
const SwReporterInvocation& invocation = launched_invocations_.front();
EXPECT_EQ(MakeTestFilePath(default_path_),
invocation.command_line.GetProgram());
EXPECT_EQ(1U, invocation.command_line.GetSwitches().size());
EXPECT_EQ(40U, invocation.command_line
.GetSwitchValueASCII(chrome_cleaner::kSessionIdSwitch)
.size());
EXPECT_TRUE(invocation.command_line.GetArgs().empty());
EXPECT_TRUE(invocation.suffix.empty());
EXPECT_EQ(SwReporterInvocation::BEHAVIOUR_LOG_EXIT_CODE_TO_PREFS |
SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT |
SwReporterInvocation::BEHAVIOUR_ALLOW_SEND_REPORTER_LOGS,
invocation.supported_behaviours);
}
// |ComponentReady| asserts that it is run on the UI thread, so we must
// create test threads before calling it.
content::TestBrowserThreadBundle threads_;
// Bound callback to the |SwReporterLaunched| method.
SwReporterRunner launched_callback_;
// Default parameters for |ComponentReady|.
base::Version default_version_;
base::FilePath default_path_;
// Results of running |ComponentReady|.
safe_browsing::SwReporterQueue launched_invocations_;
base::Version launched_version_;
private:
DISALLOW_COPY_AND_ASSIGN(SwReporterInstallerTest);
};
// This class contains extended setup that is only used for tests of the
// experimental reporter.
class ExperimentalSwReporterInstallerTest : public SwReporterInstallerTest {
public:
ExperimentalSwReporterInstallerTest() {}
~ExperimentalSwReporterInstallerTest() override {}
protected:
void CreateFeatureWithoutTag() {
std::map<std::string, std::string> params;
CreateFeatureWithParams(params);
}
void CreateFeatureWithTag(const std::string& tag) {
std::map<std::string, std::string> params;
params["tag"] = tag;
CreateFeatureWithParams(params);
}
void CreateFeatureWithParams(
const std::map<std::string, std::string>& params) {
constexpr char kFeatureAndTrialName[] = "ExperimentalSwReporterEngine";
std::map<std::string, std::string> params_with_group = params;
params_with_group["experiment_group_for_reporting"] = kExperimentGroupName;
// Assign the given variation params to the experiment group until
// |variations_| goes out of scope when the test exits. This will also
// create a FieldTrial for this group and associate the params with the
// feature.
variations_ = std::make_unique<variations::testing::VariationParamsManager>(
kFeatureAndTrialName, // trial_name
params_with_group,
std::set<std::string>{kFeatureAndTrialName}); // associated_features
}
void ExpectAttributesWithTag(const SwReporterInstallerPolicy& policy,
const std::string& tag) {
update_client::InstallerAttributes attributes =
policy.GetInstallerAttributes();
EXPECT_EQ(1U, attributes.size());
EXPECT_EQ(tag, attributes["tag"]);
}
// Expects that the SwReporter was launched exactly once, with the given
// |expected_suffix|, an experiment group, a session-id, and one
// |expected_additional_argument| on the command-line.
// (|expected_additional_argument| mainly exists to test that arguments are
// included at all, so there is no need to test for combinations of multiple
// arguments and switches in this function.)
void ExpectExperimentalInvocation(
const std::string& expected_suffix,
const base::string16& expected_additional_argument) {
EXPECT_EQ(default_version_, launched_version_);
ASSERT_EQ(1U, launched_invocations_.size());
const SwReporterInvocation& invocation = launched_invocations_.front();
EXPECT_EQ(MakeTestFilePath(default_path_),
invocation.command_line.GetProgram());
EXPECT_EQ(40U, invocation.command_line
.GetSwitchValueASCII(chrome_cleaner::kSessionIdSwitch)
.size());
EXPECT_EQ(kExperimentGroupName,
invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kEngineExperimentGroupSwitch));
if (expected_suffix.empty()) {
EXPECT_EQ(2U, invocation.command_line.GetSwitches().size());
EXPECT_TRUE(invocation.suffix.empty());
} else {
EXPECT_EQ(3U, invocation.command_line.GetSwitches().size());
EXPECT_EQ(expected_suffix, invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kRegistrySuffixSwitch));
EXPECT_EQ(expected_suffix, invocation.suffix);
}
if (expected_additional_argument.empty()) {
EXPECT_TRUE(invocation.command_line.GetArgs().empty());
} else {
EXPECT_EQ(1U, invocation.command_line.GetArgs().size());
EXPECT_EQ(expected_additional_argument,
invocation.command_line.GetArgs()[0]);
}
EXPECT_EQ(0U, invocation.supported_behaviours);
histograms_.ExpectTotalCount(kErrorHistogramName, 0);
}
// Expects that the SwReporter was launched with the given |expected_suffix|,
// |expected_engine|, and |expected_behaviours|, as part of a series of
// multiple invocations.
void ExpectExperimentalInvocationInSeries(
const std::string& expected_suffix,
const std::string& expected_engine,
SwReporterInvocation::Behaviours expected_behaviours,
std::string* out_session_id) {
SCOPED_TRACE("Invocation with suffix " + expected_suffix);
SwReporterInvocation invocation = launched_invocations_.front();
launched_invocations_.pop();
EXPECT_EQ(MakeTestFilePath(default_path_),
invocation.command_line.GetProgram());
// There should be one switch added from the manifest, plus registry-suffix
// added automatically.
EXPECT_EQ(4U, invocation.command_line.GetSwitches().size());
EXPECT_EQ(expected_engine,
invocation.command_line.GetSwitchValueASCII("engine"));
EXPECT_EQ(expected_suffix, invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kRegistrySuffixSwitch));
*out_session_id = invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kSessionIdSwitch);
EXPECT_EQ(40U, out_session_id->size());
EXPECT_EQ(kExperimentGroupName,
invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kEngineExperimentGroupSwitch));
ASSERT_TRUE(invocation.command_line.GetArgs().empty());
EXPECT_EQ(expected_suffix, invocation.suffix);
EXPECT_EQ(expected_behaviours, invocation.supported_behaviours);
}
void ExpectLaunchError() {
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
std::unique_ptr<variations::testing::VariationParamsManager> variations_;
base::test::ScopedFeatureList scoped_feature_list_;
base::HistogramTester histograms_;
private:
DISALLOW_COPY_AND_ASSIGN(ExperimentalSwReporterInstallerTest);
};
TEST_F(SwReporterInstallerTest, Default) {
SwReporterInstallerPolicy policy(launched_callback_, false);
ExpectEmptyAttributes(policy);
policy.ComponentReady(default_version_, default_path_,
std::make_unique<base::DictionaryValue>());
ExpectDefaultInvocation();
}
TEST_F(ExperimentalSwReporterInstallerTest, NoExperimentConfig) {
// Even if the experiment is supported on this hardware, the user shouldn't
// be enrolled unless enabled through variations.
SwReporterInstallerPolicy policy(launched_callback_, true);
ExpectEmptyAttributes(policy);
policy.ComponentReady(default_version_, default_path_,
std::make_unique<base::DictionaryValue>());
ExpectDefaultInvocation();
}
TEST_F(ExperimentalSwReporterInstallerTest, ExperimentUnsupported) {
// Even if the experiment config is enabled in variations, the user shouldn't
// be enrolled if the hardware doesn't support it.
SwReporterInstallerPolicy policy(launched_callback_, false);
CreateFeatureWithTag(kExperimentTag);
ExpectEmptyAttributes(policy);
policy.ComponentReady(default_version_, default_path_,
std::make_unique<base::DictionaryValue>());
ExpectDefaultInvocation();
}
TEST_F(ExperimentalSwReporterInstallerTest, ExperimentMissingTag) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithoutTag();
ExpectAttributesWithTag(policy, kMissingTag);
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_TAG, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, ExperimentInvalidTag) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag("tag with invalid whitespace chars");
ExpectAttributesWithTag(policy, kMissingTag);
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_TAG, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, ExperimentTagTooLong) {
SwReporterInstallerPolicy policy(launched_callback_, true);
std::string tag_too_long(500, 'x');
CreateFeatureWithTag(tag_too_long);
ExpectAttributesWithTag(policy, kMissingTag);
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_TAG, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, ExperimentEmptyTag) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag("");
ExpectAttributesWithTag(policy, kMissingTag);
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_TAG, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, SingleInvocation) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
ExpectAttributesWithTag(policy, kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"--engine=experimental\", \"random argument\"],"
" \"suffix\": \"TestSuffix\","
" \"prompt\": false"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should be launched once with the given arguments.
EXPECT_EQ(default_version_, launched_version_);
ASSERT_EQ(1U, launched_invocations_.size());
const SwReporterInvocation& invocation = launched_invocations_.front();
EXPECT_EQ(MakeTestFilePath(default_path_),
invocation.command_line.GetProgram());
EXPECT_EQ(4U, invocation.command_line.GetSwitches().size());
EXPECT_EQ("experimental",
invocation.command_line.GetSwitchValueASCII("engine"));
EXPECT_EQ("TestSuffix", invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kRegistrySuffixSwitch));
EXPECT_EQ(40U, invocation.command_line
.GetSwitchValueASCII(chrome_cleaner::kSessionIdSwitch)
.size());
EXPECT_EQ(kExperimentGroupName,
invocation.command_line.GetSwitchValueASCII(
chrome_cleaner::kEngineExperimentGroupSwitch));
ASSERT_EQ(1U, invocation.command_line.GetArgs().size());
EXPECT_EQ(L"random argument", invocation.command_line.GetArgs()[0]);
EXPECT_EQ("TestSuffix", invocation.suffix);
EXPECT_EQ(0U, invocation.supported_behaviours);
histograms_.ExpectTotalCount(kErrorHistogramName, 0);
}
TEST_F(ExperimentalSwReporterInstallerTest, MultipleInvocations) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
ExpectAttributesWithTag(policy, kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"--engine=experimental\"],"
" \"suffix\": \"TestSuffix\","
" \"prompt\": false,"
" \"allow-reporter-logs\": true"
" },"
" {"
" \"arguments\": [\"--engine=second\"],"
" \"suffix\": \"SecondSuffix\","
" \"prompt\": true,"
" \"allow-reporter-logs\": false"
" },"
" {"
" \"arguments\": [\"--engine=third\"],"
" \"suffix\": \"ThirdSuffix\""
" },"
" {"
" \"arguments\": [\"--engine=fourth\"],"
" \"suffix\": \"FourthSuffix\","
" \"prompt\": true,"
" \"allow-reporter-logs\": true"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should be launched four times with the given arguments.
EXPECT_EQ(default_version_, launched_version_);
ASSERT_EQ(4U, launched_invocations_.size());
std::string out_session_id;
ExpectExperimentalInvocationInSeries(
"TestSuffix", "experimental",
SwReporterInvocation::BEHAVIOUR_ALLOW_SEND_REPORTER_LOGS,
&out_session_id);
const std::string first_session_id(out_session_id);
ExpectExperimentalInvocationInSeries(
"SecondSuffix", "second", SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT,
&out_session_id);
EXPECT_EQ(first_session_id, out_session_id);
ExpectExperimentalInvocationInSeries("ThirdSuffix", "third", 0U,
&out_session_id);
EXPECT_EQ(first_session_id, out_session_id);
ExpectExperimentalInvocationInSeries(
"FourthSuffix", "fourth",
SwReporterInvocation::BEHAVIOUR_ALLOW_SEND_REPORTER_LOGS |
SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT,
&out_session_id);
EXPECT_EQ(first_session_id, out_session_id);
histograms_.ExpectTotalCount(kErrorHistogramName, 0);
}
TEST_F(ExperimentalSwReporterInstallerTest, MissingSuffix) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"random argument\"]"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectLaunchError();
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptySuffix) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"suffix\": \"\","
" \"arguments\": [\"random argument\"]"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectExperimentalInvocation("", L"random argument");
}
TEST_F(ExperimentalSwReporterInstallerTest, MissingSuffixAndArgs) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectLaunchError();
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptySuffixAndArgs) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"suffix\": \"\","
" \"arguments\": []"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectExperimentalInvocation("", L"");
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptySuffixAndArgs2) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"suffix\": \"\","
" \"arguments\": [\"\"]"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectExperimentalInvocation("", L"");
}
TEST_F(ExperimentalSwReporterInstallerTest, MissingArguments) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"suffix\": \"TestSuffix\""
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectLaunchError();
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptyArguments) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"suffix\": \"TestSuffix\","
" \"arguments\": []"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectExperimentalInvocation("TestSuffix", L"");
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptyArguments2) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"suffix\": \"TestSuffix\","
" \"arguments\": [\"\"]"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
ExpectExperimentalInvocation("TestSuffix", L"");
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptyManifest) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] = "{}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(
kErrorHistogramName, SW_REPORTER_EXPERIMENT_ERROR_MISSING_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptyLaunchParams) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] = "{\"launch_params\": []}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, EmptyLaunchParams2) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] = "{\"launch_params\": {}}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, BadSuffix) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"--engine=experimental\"],"
" \"suffix\": \"invalid whitespace characters\""
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, SuffixTooLong) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"--engine=experimental\"],"
" \"suffix\": \"%s\""
" }"
"]}";
std::string suffix_too_long(500, 'x');
std::string manifest =
base::StringPrintf(kTestManifest, suffix_too_long.c_str());
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(manifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, BadTypesInManifest) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
// This has a string instead of a list for "arguments".
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": \"--engine=experimental\","
" \"suffix\": \"TestSuffix\""
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, BadTypesInManifest2) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
// This has the invocation parameters as direct children of "launch_params",
// instead of using a list.
static constexpr char kTestManifest[] =
"{\"launch_params\": "
" {"
" \"arguments\": [\"--engine=experimental\"],"
" \"suffix\": \"TestSuffix\""
" }"
"}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, BadTypesInManifest3) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
// This has a list for suffix as well as for arguments.
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"--engine=experimental\"],"
" \"suffix\": [\"TestSuffix\"]"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
TEST_F(ExperimentalSwReporterInstallerTest, BadTypesInManifest4) {
SwReporterInstallerPolicy policy(launched_callback_, true);
CreateFeatureWithTag(kExperimentTag);
// This has an int instead of a bool for prompt.
static constexpr char kTestManifest[] =
"{\"launch_params\": ["
" {"
" \"arguments\": [\"--engine=experimental\"],"
" \"suffix\": \"TestSuffix\","
" \"prompt\": 1"
" }"
"]}";
policy.ComponentReady(
default_version_, default_path_,
base::DictionaryValue::From(base::JSONReader::Read(kTestManifest)));
// The SwReporter should not be launched, and an error should be logged.
EXPECT_TRUE(launched_invocations_.empty());
histograms_.ExpectUniqueSample(kErrorHistogramName,
SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
}
} // namespace component_updater