Sorin Jianu | 55587d3 | 2018-11-14 21:43:27 | [diff] [blame] | 1 | // Copyright 2018 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include <memory> |
| 6 | #include <string> |
| 7 | #include <utility> |
| 8 | #include <vector> |
| 9 | |
| 10 | #include "base/optional.h" |
| 11 | #include "base/values.h" |
| 12 | #include "base/version.h" |
| 13 | #include "components/prefs/testing_pref_service.h" |
| 14 | #include "components/update_client/activity_data_service.h" |
| 15 | #include "components/update_client/persisted_data.h" |
| 16 | #include "components/update_client/protocol_definition.h" |
| 17 | #include "components/update_client/protocol_serializer.h" |
| 18 | #include "components/update_client/protocol_serializer_json.h" |
| 19 | #include "components/update_client/updater_state.h" |
| 20 | #include "testing/gtest/include/gtest/gtest.h" |
| 21 | #include "third_party/re2/src/re2/re2.h" |
| 22 | |
| 23 | using base::Value; |
| 24 | using std::string; |
| 25 | |
| 26 | namespace update_client { |
| 27 | |
| 28 | TEST(SerializeRequestJSON, Serialize) { |
| 29 | // When no updater state is provided, then check that the elements and |
| 30 | // attributes related to the updater state are not serialized. |
| 31 | |
| 32 | std::vector<base::Value> events; |
| 33 | events.push_back(Value(Value::Type::DICTIONARY)); |
| 34 | events.push_back(Value(Value::Type::DICTIONARY)); |
| 35 | events[0].SetKey("a", Value(1)); |
| 36 | events[0].SetKey("b", Value("2")); |
| 37 | events[1].SetKey("error", Value(0)); |
| 38 | |
| 39 | auto pref = std::make_unique<TestingPrefServiceSimple>(); |
| 40 | PersistedData::RegisterPrefs(pref->registry()); |
| 41 | auto metadata = std::make_unique<PersistedData>(pref.get(), nullptr); |
| 42 | std::vector<std::string> items = {"id1"}; |
| 43 | metadata->SetDateLastRollCall(items, 1234); |
| 44 | |
| 45 | std::vector<protocol_request::App> apps; |
| 46 | apps.push_back(MakeProtocolApp( |
| 47 | "id1", base::Version("1.0"), "brand1", "source1", "location1", "fp1", |
| 48 | {{"attr1", "1"}, {"attr2", "2"}}, "c1", "ch1", "cn1", {0, 1}, |
| 49 | MakeProtocolUpdateCheck(true), MakeProtocolPing("id1", metadata.get()))); |
| 50 | apps.push_back( |
| 51 | MakeProtocolApp("id2", base::Version("2.0"), std::move(events))); |
| 52 | |
| 53 | const auto request = std::make_unique<ProtocolSerializerJSON>()->Serialize( |
Sorin Jianu | c9d642e | 2018-12-18 19:38:36 | [diff] [blame] | 54 | MakeProtocolRequest("{15160585-8ADE-4D3C-839B-1281A6035D1F}", "prod_id", |
Sorin Jianu | 55587d3 | 2018-11-14 21:43:27 | [diff] [blame] | 55 | "1.0", "lang", "channel", "OS", "cacheable", |
| 56 | {{"extra", "params"}}, nullptr, std::move(apps))); |
| 57 | constexpr char regex[] = |
| 58 | R"({"request":{"@os":"\w+","@updater":"prod_id",)" |
| 59 | R"("acceptformat":"crx2,crx3",)" |
| 60 | R"("app":\[{"appid":"id1","attr1":"1","attr2":"2","brand":"brand1",)" |
| 61 | R"("cohort":"c1","cohorthint":"ch1","cohortname":"cn1",)" |
| 62 | R"("disabled":\[{"reason":0},{"reason":1}],"enabled":false,)" |
| 63 | R"("installedby":"location1","installsource":"source1",)" |
| 64 | R"("packages":{"package":\[{"fp":"fp1"}]},)" |
| 65 | R"("ping":{"ping_freshness":"{[-\w]{36}}","rd":1234},)" |
| 66 | R"("updatecheck":{"updatedisabled":true},"version":"1.0"},)" |
| 67 | R"({"appid":"id2","event":\[{"a":1,"b":"2"},{"error":0}],)" |
| 68 | R"("version":"2.0"}],"arch":"\w+","dedup":"cr","dlpref":"cacheable",)" |
| 69 | R"("extra":"params","hw":{"physmemory":\d+},"lang":"lang",)" |
| 70 | R"("nacl_arch":"[-\w]+","os":{"arch":"[_,-.\w]+","platform":"OS",)" |
| 71 | R"(("sp":"[\s\w]+",)?"version":"[-.\w]+"},"prodchannel":"channel",)" |
| 72 | R"("prodversion":"1.0","protocol":"3.1","requestid":"{[-\w]{36}}",)" |
| 73 | R"("sessionid":"{[-\w]{36}}","updaterchannel":"channel",)" |
| 74 | R"("updaterversion":"1.0"(,"wow64":true)?}})"; |
| 75 | EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; |
| 76 | } |
| 77 | |
| 78 | TEST(SerializeRequestJSON, DownloadPreference) { |
| 79 | // Verifies that an empty |download_preference| is not serialized. |
| 80 | const auto serializer = std::make_unique<ProtocolSerializerJSON>(); |
| 81 | auto request = serializer->Serialize( |
Sorin Jianu | c9d642e | 2018-12-18 19:38:36 | [diff] [blame] | 82 | MakeProtocolRequest("{15160585-8ADE-4D3C-839B-1281A6035D1F}", "", "", "", |
Sorin Jianu | 55587d3 | 2018-11-14 21:43:27 | [diff] [blame] | 83 | "", "", "", {}, nullptr, {})); |
| 84 | EXPECT_FALSE(RE2::PartialMatch(request, R"("dlpref":)")) << request; |
| 85 | |
| 86 | // Verifies that |download_preference| is serialized. |
| 87 | request = serializer->Serialize( |
Sorin Jianu | c9d642e | 2018-12-18 19:38:36 | [diff] [blame] | 88 | MakeProtocolRequest("{15160585-8ADE-4D3C-839B-1281A6035D1F}", "", "", "", |
Sorin Jianu | 55587d3 | 2018-11-14 21:43:27 | [diff] [blame] | 89 | "", "", "cacheable", {}, nullptr, {})); |
| 90 | EXPECT_TRUE(RE2::PartialMatch(request, R"("dlpref":"cacheable")")) << request; |
| 91 | } |
| 92 | |
| 93 | // When present, updater state attributes are only serialized for Google builds, |
| 94 | // except the |domainjoined| attribute, which is serialized in all cases. |
| 95 | TEST(SerializeRequestJSON, UpdaterStateAttributes) { |
| 96 | const auto serializer = std::make_unique<ProtocolSerializerJSON>(); |
| 97 | UpdaterState::Attributes attributes; |
| 98 | attributes["ismachine"] = "1"; |
| 99 | attributes["domainjoined"] = "1"; |
| 100 | attributes["name"] = "Omaha"; |
| 101 | attributes["version"] = "1.2.3.4"; |
| 102 | attributes["laststarted"] = "1"; |
| 103 | attributes["lastchecked"] = "2"; |
| 104 | attributes["autoupdatecheckenabled"] = "0"; |
| 105 | attributes["updatepolicy"] = "-1"; |
| 106 | const auto request = serializer->Serialize(MakeProtocolRequest( |
Sorin Jianu | c9d642e | 2018-12-18 19:38:36 | [diff] [blame] | 107 | "{15160585-8ADE-4D3C-839B-1281A6035D1F}", "prod_id", "1.0", "lang", |
Sorin Jianu | 55587d3 | 2018-11-14 21:43:27 | [diff] [blame] | 108 | "channel", "OS", "cacheable", {{"extra", "params"}}, &attributes, {})); |
| 109 | constexpr char regex[] = |
| 110 | R"({"request":{"@os":"\w+","@updater":"prod_id",)" |
| 111 | R"("acceptformat":"crx2,crx3","arch":"\w+","dedup":"cr",)" |
| 112 | R"("dlpref":"cacheable","domainjoined":true,"extra":"params",)" |
| 113 | R"("hw":{"physmemory":\d+},"lang":"lang","nacl_arch":"[-\w]+",)" |
| 114 | R"("os":{"arch":"[,-.\w]+","platform":"OS",("sp":"[\s\w]+",)?)" |
| 115 | R"("version":"[-.\w]+"},"prodchannel":"channel","prodversion":"1.0",)" |
| 116 | R"("protocol":"3.1","requestid":"{[-\w]{36}}","sessionid":"{[-\w]{36}}",)" |
| 117 | #if defined(GOOGLE_CHROME_BUILD) |
| 118 | R"("updater":{"autoupdatecheckenabled":false,"ismachine":true,)" |
| 119 | R"("lastchecked":2,"laststarted":1,"name":"Omaha","updatepolicy":-1,)" |
| 120 | R"("version":"1\.2\.3\.4"},)" |
| 121 | #endif // GOOGLE_CHROME_BUILD |
| 122 | R"("updaterchannel":"channel","updaterversion":"1.0"(,"wow64":true)?}})"; |
| 123 | EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; |
| 124 | } |
| 125 | |
| 126 | } // namespace update_client |