| // Copyright 2020 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/updater/tag.h" |
| |
| #include "base/strings/string_piece.h" |
| #include "chrome/updater/unittest_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| using updater::tagging::AppArgs; |
| using updater::tagging::ErrorCode; |
| using updater::tagging::TagArgs; |
| |
| // Builder pattern helper to construct the TagArgs struct. |
| class TagArgsBuilder { |
| public: |
| TagArgs&& Build() { return std::move(inner_); } |
| |
| TagArgsBuilder& WithBundleName(const std::string bundle_name) { |
| this->inner_.bundle_name = bundle_name; |
| return *this; |
| } |
| TagArgsBuilder& WithInstallationId(const std::string installation_id) { |
| this->inner_.installation_id = installation_id; |
| return *this; |
| } |
| TagArgsBuilder& WithBrandCode(const std::string brand_code) { |
| this->inner_.brand_code = brand_code; |
| return *this; |
| } |
| TagArgsBuilder& WithClientId(const std::string client_id) { |
| this->inner_.client_id = client_id; |
| return *this; |
| } |
| TagArgsBuilder& WithExperimentLabels(const std::string experiment_labels) { |
| this->inner_.experiment_labels = experiment_labels; |
| return *this; |
| } |
| TagArgsBuilder& WithReferralId(const std::string referral_id) { |
| this->inner_.referral_id = referral_id; |
| return *this; |
| } |
| TagArgsBuilder& WithLanguage(const std::string language) { |
| this->inner_.language = language; |
| return *this; |
| } |
| TagArgsBuilder& WithFlighting(const bool flighting) { |
| this->inner_.flighting = flighting; |
| return *this; |
| } |
| TagArgsBuilder& WithBrowserType(const TagArgs::BrowserType browser_type) { |
| this->inner_.browser_type = browser_type; |
| return *this; |
| } |
| TagArgsBuilder& WithUsageStatsEnable(const bool usage_stats_enable) { |
| this->inner_.usage_stats_enable = usage_stats_enable; |
| return *this; |
| } |
| TagArgsBuilder& WithApp(AppArgs&& app) { |
| this->inner_.apps.push_back(std::move(app)); |
| return *this; |
| } |
| |
| private: |
| TagArgs inner_; |
| }; |
| |
| // Builder pattern helper to construct the AppArgs struct. |
| class AppArgsBuilder { |
| public: |
| explicit AppArgsBuilder(const std::string app_id) : inner_(app_id) {} |
| |
| AppArgs&& Build() { return std::move(inner_); } |
| |
| AppArgsBuilder& WithAppName(const std::string app_name) { |
| this->inner_.app_name = app_name; |
| return *this; |
| } |
| AppArgsBuilder& WithNeedsAdmin(const AppArgs::NeedsAdmin needs_admin) { |
| this->inner_.needs_admin = needs_admin; |
| return *this; |
| } |
| AppArgsBuilder& WithAp(const std::string ap) { |
| this->inner_.ap = ap; |
| return *this; |
| } |
| AppArgsBuilder& WithEncodedInstallerData( |
| const std::string encoded_installer_data) { |
| this->inner_.encoded_installer_data = encoded_installer_data; |
| return *this; |
| } |
| AppArgsBuilder& WithInstallDataIndex(const std::string install_data_index) { |
| this->inner_.install_data_index = install_data_index; |
| return *this; |
| } |
| AppArgsBuilder& WithExperimentLabels(const std::string experiment_labels) { |
| this->inner_.experiment_labels = experiment_labels; |
| return *this; |
| } |
| AppArgsBuilder& WithUntrustedData(const std::string untrusted_data) { |
| this->inner_.untrusted_data = untrusted_data; |
| return *this; |
| } |
| |
| private: |
| AppArgs inner_; |
| }; |
| |
| void VerifyTagParseSuccess( |
| base::StringPiece tag, |
| base::Optional<base::StringPiece> app_installer_data_args, |
| const TagArgs& expected) { |
| TagArgs actual; |
| ASSERT_EQ(ErrorCode::kSuccess, Parse(tag, app_installer_data_args, &actual)); |
| |
| EXPECT_EQ(expected.bundle_name, actual.bundle_name); |
| EXPECT_EQ(expected.installation_id, actual.installation_id); |
| EXPECT_EQ(expected.brand_code, actual.brand_code); |
| EXPECT_EQ(expected.client_id, actual.client_id); |
| EXPECT_EQ(expected.experiment_labels, actual.experiment_labels); |
| EXPECT_EQ(expected.referral_id, actual.referral_id); |
| EXPECT_EQ(expected.language, actual.language); |
| EXPECT_EQ(expected.browser_type, actual.browser_type); |
| EXPECT_EQ(expected.usage_stats_enable, actual.usage_stats_enable); |
| |
| EXPECT_EQ(expected.apps.size(), actual.apps.size()); |
| for (size_t i = 0; i < actual.apps.size(); ++i) { |
| const AppArgs& app_expected = expected.apps[i]; |
| const AppArgs& app_actual = actual.apps[i]; |
| |
| EXPECT_EQ(app_expected.app_id, app_actual.app_id); |
| EXPECT_EQ(app_expected.app_name, app_actual.app_name); |
| EXPECT_EQ(app_expected.needs_admin, app_actual.needs_admin); |
| EXPECT_EQ(app_expected.ap, app_actual.ap); |
| EXPECT_EQ(app_expected.encoded_installer_data, |
| app_actual.encoded_installer_data); |
| EXPECT_EQ(app_expected.install_data_index, app_actual.install_data_index); |
| EXPECT_EQ(app_expected.experiment_labels, app_actual.experiment_labels); |
| } |
| } |
| |
| void VerifyTagParseFail( |
| base::StringPiece tag, |
| base::Optional<base::StringPiece> app_installer_data_args, |
| ErrorCode expected) { |
| TagArgs args; |
| ASSERT_EQ(expected, Parse(tag, app_installer_data_args, &args)); |
| } |
| |
| } // namespace |
| |
| namespace updater { |
| |
| using tagging::AppArgs; |
| using tagging::ErrorCode; |
| using tagging::Parse; |
| using tagging::TagArgs; |
| |
| TEST(TagParserTest, InvalidValueNameIsSupersetOfValidName) { |
| VerifyTagParseFail( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname1=Hello", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, AppNameSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname= ", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, AppNameEncodedSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname=%20", |
| base::nullopt, ErrorCode::kApp_AppNameCannotBeWhitespace); |
| } |
| |
| TEST(TagParserTest, AppNameValid) { |
| VerifyTagParseSuccess( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname=Test", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName("Test") |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName("Test") |
| .Build()) |
| .Build()); |
| } |
| |
| // This must work because the enterprise MSI code assumes spaces are allowed. |
| TEST(TagParserTest, AppNameWithSpace) { |
| VerifyTagParseSuccess( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname=Test App", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName("Test App") |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName("Test App") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppNameWithSpaceAtEnd) { |
| VerifyTagParseSuccess( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname= T Ap p ", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName("T Ap p") |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName("T Ap p") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppNameWithEncodedSpacesAtEnd) { |
| VerifyTagParseSuccess( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname=%20T%20Ap%20p%20", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName("T Ap p") |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName("T Ap p") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppNameWithMultipleSpaces) { |
| VerifyTagParseSuccess( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname= T Ap p", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName("T Ap p") |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName("T Ap p") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppNameUnicode) { |
| std::string non_ascii_name = "रहा"; |
| VerifyTagParseSuccess( |
| "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&" |
| "appname=%E0%A4%B0%E0%A4%B9%E0%A4%BE", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName(non_ascii_name) |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName(non_ascii_name) |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppNameUnicode2) { |
| std::string non_ascii_name = "स्थापित कर रहा है।"; |
| std::string escaped( |
| "%E0%A4%B8%E0%A5%8D%E0%A4%A5%E0%A4%BE%E0%A4%AA%E0%A4%BF" |
| "%E0%A4%A4%20%E0%A4%95%E0%A4%B0%20%E0%A4%B0%E0%A4%B9%E0" |
| "%A4%BE%20%E0%A4%B9%E0%A5%88%E0%A5%A4"); |
| |
| std::stringstream tag; |
| tag << "appguid=D0324988-DA8A-49e5-BCE5-925FCD04EAB7&"; |
| tag << "appname=" << escaped; |
| VerifyTagParseSuccess( |
| tag.str(), base::nullopt, |
| TagArgsBuilder() |
| .WithBundleName(non_ascii_name) |
| .WithApp(AppArgsBuilder("d0324988-da8a-49e5-bce5-925fcd04eab7") |
| .WithAppName(non_ascii_name) |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppIdValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B", base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppIdNotASCII) { |
| VerifyTagParseFail("appguid=रहा", base::nullopt, |
| ErrorCode::kApp_AppIdIsNotValid); |
| } |
| |
| // Most tests here do not reflect this, but appids can be non-GUID ASCII |
| // strings. |
| TEST(TagParserTest, AppIdNotAGuid) { |
| VerifyTagParseSuccess( |
| "appguid=non-guid-id", base::nullopt, |
| TagArgsBuilder().WithApp(AppArgsBuilder("non-guid-id").Build()).Build()); |
| } |
| |
| TEST(TagParserTest, AppIdCaseInsensitive) { |
| VerifyTagParseSuccess( |
| "appguid=ShouldBeCaseInsensitive", base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("shouldbecaseinsensitive").Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, NeedsAdminInvalid) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin=Hello", |
| base::nullopt, ErrorCode::kApp_NeedsAdminValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, NeedsAdminSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin= ", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, NeedsAdminTrueUpperCaseT) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin=True", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kYes) |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, NeedsAdminTrueLowerCaseT) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin=true", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kYes) |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, NeedsFalseUpperCaseF) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin=False", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kNo) |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, NeedsAdminFalseLowerCaseF) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin=false", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kNo) |
| .Build()) |
| .Build()); |
| } |
| |
| // |
| // Test the handling of the contents of the extra arguments. |
| // |
| |
| TEST(TagParserTest, AssignmentOnly) { |
| VerifyTagParseFail("=", base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, ExtraAssignment1) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1=", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, ExtraAssignment2) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "=usagestats=1", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, ExtraAssignment3) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1&=", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, ExtraAssignment4) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "=&usagestats=1", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, ValueWithoutName) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "=hello", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| // Also tests ending extra arguments with '='. |
| TEST(TagParserTest, NameWithoutValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, NameWithoutValueBeforeNextArgument) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=&client=hello", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, NameWithoutArgumentSeparatorAfterIntValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1client=hello", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, NameWithoutArgumentSeparatorAfterStringValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=yesclient=hello", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, TagHasDoubleAmpersand) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1&&client=hello", |
| {"appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "installerdata=foobar"}, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithEncodedInstallerData("foobar") |
| .Build()) |
| .WithUsageStatsEnable(true) |
| .WithClientId("hello") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, TagAmpersandOnly) { |
| VerifyTagParseSuccess("&", base::nullopt, TagArgsBuilder().Build()); |
| } |
| |
| TEST(TagParserTest, TagBeginsInAmpersand) { |
| VerifyTagParseSuccess( |
| "&appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, TagEndsInAmpersand) { |
| VerifyTagParseSuccess( |
| "&appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1&", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, WhitespaceOnly) { |
| for (const auto* whitespace : {"", " ", "\t", "\r", "\n", "\r\n"}) { |
| VerifyTagParseSuccess(whitespace, base::nullopt, TagArgsBuilder().Build()); |
| } |
| } |
| |
| // |
| // Test the parsing of the extra command and its arguments into a string. |
| // |
| |
| TEST(TagParserTest, OneValidAttribute) { |
| VerifyTagParseSuccess( |
| "&appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, TwoValidAttributes) { |
| VerifyTagParseSuccess( |
| "&appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1&client=hello", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithUsageStatsEnable(true) |
| .WithClientId("hello") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, TagHasSwitchInTheMiddle) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1/other_value=9", |
| base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, TagHasDoubleQuoteInTheMiddle) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1\"/other_value=9", |
| base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, TagHasDoubleQuoteInTheMiddleAndNoForwardSlash) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1\"other_value=9", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, TagHasSpaceAndForwardSlashBeforeQuote) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1 /other_value=9", |
| base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, TagHasForwardSlashBeforeQuote) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1/other_value=9", |
| base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, AttributeSpecifiedTwice) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1\" \"client=10", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, WhiteSpaceBeforeArgs1) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| " usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617EE50-F91C-4DC1-B937-0969EEF59B0B").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, WhiteSpaceBeforeArgs2) { |
| VerifyTagParseSuccess( |
| "\tappguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617EE50-F91C-4DC1-B937-0969EEF59B0B").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, WhiteSpaceBeforeArgs3) { |
| VerifyTagParseSuccess( |
| "\rappguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617EE50-F91C-4DC1-B937-0969EEF59B0B").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, WhiteSpaceBeforeArgs4) { |
| VerifyTagParseSuccess( |
| "\nappguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B" |
| "&usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617EE50-F91C-4DC1-B937-0969EEF59B0B").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, WhiteSpaceBeforeArgs5) { |
| VerifyTagParseSuccess("\r\nusagestats=1", base::nullopt, |
| TagArgsBuilder().WithUsageStatsEnable(true).Build()); |
| } |
| |
| TEST(TagParserTest, ForwardSlash1) { |
| VerifyTagParseFail("/", base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, ForwardSlash2) { |
| VerifyTagParseFail("/ appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B", |
| base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, BackwardSlash1) { |
| VerifyTagParseFail("\\", base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, BackwardSlash2) { |
| VerifyTagParseFail("\\appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, BackwardSlash3) { |
| VerifyTagParseFail("\\ appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, AppArgsMustHaveValue) { |
| for (const auto* tag : |
| {"appguid", "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&ap", |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&experiments", |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&appname", |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&needsadmin", |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&installdataindex", |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&untrusteddata"}) { |
| VerifyTagParseFail(tag, base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| } |
| |
| // |
| // Test specific extra commands. |
| // |
| |
| TEST(TagParserTest, UsageStatsOutsideExtraCommand) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "/usagestats", |
| base::nullopt, ErrorCode::kTagIsInvalid); |
| } |
| |
| TEST(TagParserTest, UsageStatsOn) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=1", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithUsageStatsEnable(true) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, UsageStatsOff) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=0", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithUsageStatsEnable(false) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, UsageStatsNone) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=2", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, UsageStatsInvalidPositiveValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=3", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, UsageStatsInvalidNegativeValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=-1", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, UsageStatsValueIsString) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "usagestats=true", |
| base::nullopt, ErrorCode::kGlobal_UsageStatsValueIsInvalid); |
| } |
| |
| TEST(TagParserTest, BundleNameValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "bundlename=Google%20Bundle", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithBundleName("Google Bundle") |
| |
| .Build()); |
| } |
| |
| TEST(TagParserTest, BundleNameSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "bundlename= ", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, BundleNameEncodedSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "bundlename=%20", |
| base::nullopt, ErrorCode::kGlobal_BundleNameCannotBeWhitespace); |
| } |
| |
| TEST(TagParserTest, BundleNameNotPresentButAppNameIs) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "appname=Google%20Chrome", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithAppName("Google Chrome") |
| .Build()) |
| .WithBundleName("Google Chrome") |
| .Build()); |
| } |
| TEST(TagParserTest, BundleNameNorAppNamePresent) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&", base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, BundleNameNotPresentAndNoApp) { |
| VerifyTagParseSuccess( |
| "browser=0", base::nullopt, |
| TagArgsBuilder().WithBrowserType(TagArgs::BrowserType::kUnknown).Build()); |
| } |
| |
| TEST(TagParserTest, InstallationIdValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "iid=98CEC468-9429-4984-AEDE-4F53C6A14869", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithInstallationId("98CEC468-9429-4984-AEDE-4F53C6A14869") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, InstallationIdContainsNonASCII) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "iid=रहा", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithInstallationId("रहा") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, BrandCodeValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "brand=GOOG", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithBrandCode("GOOG") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, ClientIdValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "client=some_partner", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithClientId("some_partner") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, UpdaterExperimentIdValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "omahaexperiments=experiment%3DgroupA%7Cexpir", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithExperimentLabels("experiment=groupA|expir") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, UpdaterExperimentIdSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "omahaexperiments= ", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, UpdaterExperimentIdEncodedSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "omahaexperiments=%20", |
| base::nullopt, ErrorCode::kGlobal_ExperimentLabelsCannotBeWhitespace); |
| } |
| |
| TEST(TagParserTest, AppExperimentIdValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "experiments=experiment%3DgroupA%7Cexpir", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithExperimentLabels("experiment=groupA|expir") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppExperimentIdSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "experiments= ", |
| base::nullopt, ErrorCode::kAttributeMustHaveValue); |
| } |
| |
| TEST(TagParserTest, AppExperimentIdEncodedSpaceForValue) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "experiments=%20", |
| base::nullopt, ErrorCode::kApp_ExperimentLabelsCannotBeWhitespace); |
| } |
| |
| TEST(TagParserTest, ReferralIdValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "referral=ABCD123", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithReferralId("ABCD123") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, ApValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "ap=developer", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithAp("developer") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppInstallerDataArgsValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&", |
| {"appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "installerdata=%E0%A4foobar"}, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithEncodedInstallerData("%E0%A4foobar") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppInstallerDataArgsInvalidAppId) { |
| VerifyTagParseFail("appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&", |
| {"appguid=E135384F-85A2-4328-B07D-2CF70313D505&" |
| "installerdata=%E0%A4foobar"}, |
| ErrorCode::kAppInstallerData_AppIdNotFound); |
| } |
| |
| TEST(TagParserTest, AppInstallerDataArgsInvalidAttribute) { |
| VerifyTagParseFail("appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&", |
| {"appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "needsadmin=true&"}, |
| ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, InstallerDataNotAllowedInTag) { |
| VerifyTagParseFail( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "appname=TestApp2&" |
| "needsadmin=true&" |
| "installerdata=Hello%20World", |
| base::nullopt, ErrorCode::kUnrecognizedName); |
| } |
| |
| TEST(TagParserTest, InstallDataIndexValid) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "installdataindex=foobar", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithInstallDataIndex("foobar") |
| .Build()) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, BrowserTypeValid) { |
| std::tuple<base::StringPiece, TagArgs::BrowserType> |
| pairs[static_cast<int>(TagArgs::BrowserType::kMax)] = { |
| {"0", TagArgs::BrowserType::kUnknown}, |
| {"1", TagArgs::BrowserType::kDefault}, |
| {"2", TagArgs::BrowserType::kInternetExplorer}, |
| {"3", TagArgs::BrowserType::kFirefox}, |
| {"4", TagArgs::BrowserType::kChrome}, |
| }; |
| |
| for (const auto& pair : pairs) { |
| std::stringstream tag; |
| tag << "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&"; |
| tag << "browser=" << std::get<0>(pair); |
| VerifyTagParseSuccess( |
| tag.str(), base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithBrowserType(std::get<1>(pair)) |
| .Build()); |
| } |
| } |
| |
| TEST(TagParserTest, BrowserTypeInvalid) { |
| EXPECT_EQ(5, int(TagArgs::BrowserType::kMax)) |
| << "Browser type may have been added. Update the BrowserTypeValid test " |
| "and change browser values in tag strings below."; |
| |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "browser=5", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithBrowserType(TagArgs::BrowserType::kUnknown) |
| .Build()); |
| |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "browser=9", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithBrowserType(TagArgs::BrowserType::kUnknown) |
| .Build()); |
| } |
| |
| TEST(TagParserTest, ValidLang) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "lang=en", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithLanguage("en") |
| .Build()); |
| } |
| |
| // Language must be passed even if not supported. See http://b/1336966. |
| TEST(TagParserTest, UnsupportedLang) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "lang=foobar", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp( |
| AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b").Build()) |
| .WithLanguage("foobar") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, AppNameSpecifiedTwice) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "appname=TestApp&" |
| "appname=TestApp2&", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617EE50-F91C-4DC1-B937-0969EEF59B0B") |
| .WithAppName("TestApp2") |
| .Build()) |
| .WithBundleName("TestApp2") |
| .Build()); |
| } |
| |
| TEST(TagParserTest, CaseInsensitiveAttributeNames) { |
| VerifyTagParseSuccess( |
| "APPguID=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "APPNAME=TestApp&", |
| base::nullopt, |
| TagArgsBuilder() |
| .WithApp(AppArgsBuilder("8617EE50-F91C-4DC1-B937-0969EEF59B0B") |
| .WithAppName("TestApp") |
| .Build()) |
| .WithBundleName("TestApp") |
| .Build()); |
| } |
| |
| // |
| // Test multiple applications in the extra arguments |
| // |
| TEST(TagParserTestMultipleEntries, TestNotStartingWithAppId) { |
| VerifyTagParseFail( |
| "appname=TestApp&" |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "appname=TestApp&" |
| "appname=false&" |
| "iid=98CEC468-9429-4984-AEDE-4F53C6A14869&" |
| "ap=test_ap&" |
| "usagestats=1&" |
| "browser=2&", |
| base::nullopt, ErrorCode::kApp_AppIdNotSpecified); |
| } |
| |
| // This also tests that the last occurrence of a global extra arg is the one |
| // that is saved. |
| TEST(TagParserTestMultipleEntries, ThreeApplications) { |
| VerifyTagParseSuccess( |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "appname=TestApp&" |
| "needsadmin=false&" |
| "iid=98CEC468-9429-4984-AEDE-4F53C6A14869&" |
| "ap=test_ap&" |
| "usagestats=1&" |
| "browser=2&" |
| "brand=GOOG&" |
| "client=_some_client&" |
| "experiments=_experiment_a&" |
| "untrusteddata=ABCDEFG&" |
| "referral=A123456789&" |
| "appguid=5E46DE36-737D-4271-91C1-C062F9FE21D9&" |
| "appname=TestApp2&" |
| "needsadmin=true&" |
| "experiments=_experiment_b&" |
| "untrusteddata=1234567&" |
| "iid=98CEC468-9429-4984-AEDE-4F53C6A14869&" |
| "ap=test_ap2&" |
| "usagestats=0&" |
| "browser=3&" |
| "brand=g00g&" |
| "client=_different_client&" |
| "appguid=5F46DE36-737D-4271-91C1-C062F9FE21D9&" |
| "appname=TestApp3&" |
| "needsadmin=prefers&", |
| {"appguid=5F46DE36-737D-4271-91C1-C062F9FE21D9&" |
| "installerdata=installerdata_app3&" |
| "appguid=8617EE50-F91C-4DC1-B937-0969EEF59B0B&" |
| "installerdata=installerdata_app1"}, |
| TagArgsBuilder() |
| .WithBundleName("TestApp") |
| .WithInstallationId("98CEC468-9429-4984-AEDE-4F53C6A14869") |
| .WithBrandCode("g00g") |
| .WithClientId("_different_client") |
| .WithReferralId("A123456789") |
| .WithBrowserType(TagArgs::BrowserType::kFirefox) |
| .WithUsageStatsEnable(false) |
| .WithApp(AppArgsBuilder("8617ee50-f91c-4dc1-b937-0969eef59b0b") |
| .WithAppName("TestApp") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kNo) |
| .WithAp("test_ap") |
| .WithEncodedInstallerData("installerdata_app1") |
| .WithExperimentLabels("_experiment_a") |
| .WithUntrustedData("A=3&Message=Hello,%20World!") |
| .Build()) |
| .WithApp(AppArgsBuilder("5e46de36-737d-4271-91c1-c062f9fe21d9") |
| .WithAppName("TestApp2") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kYes) |
| .WithAp("test_ap2") |
| .WithExperimentLabels("_experiment_b") |
| .WithUntrustedData("X=5") |
| .Build()) |
| .WithApp(AppArgsBuilder("5f46de36-737d-4271-91c1-c062f9fe21d9") |
| .WithAppName("TestApp3") |
| .WithEncodedInstallerData("installerdata_app3") |
| .WithNeedsAdmin(AppArgs::NeedsAdmin::kPrefers) |
| .Build()) |
| .Build()); |
| } |
| |
| } // namespace updater |