blob: 042d991968996407d05e0fe82e38c55bb6d1edeb [file] [log] [blame]
Amin Hassani7fca2862019-03-28 16:09:22 -07001//
2// Copyright (C) 2019 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/omaha_request_builder_xml.h"
18
19#include <string>
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070020#include <utility>
21#include <vector>
Amin Hassani7fca2862019-03-28 16:09:22 -070022
Jae Hoon Kim6ada5912019-06-14 10:11:34 -070023#include <base/guid.h>
Amin Hassani7fca2862019-03-28 16:09:22 -070024#include <gtest/gtest.h>
25
Jae Hoon Kim6ada5912019-06-14 10:11:34 -070026#include "update_engine/fake_system_state.h"
27
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070028using std::pair;
Amin Hassani7fca2862019-03-28 16:09:22 -070029using std::string;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070030using std::vector;
Amin Hassani7fca2862019-03-28 16:09:22 -070031
32namespace chromeos_update_engine {
33
Jae Hoon Kim6ada5912019-06-14 10:11:34 -070034namespace {
35// Helper to find key and extract value from the given string |xml|, instead
36// of using a full parser. The attribute key will be followed by "=\"" as xml
37// attribute values must be within double quotes (not single quotes).
38static string FindAttributeKeyValueInXml(const string& xml,
39 const string& key,
40 const size_t val_size) {
41 string key_with_quotes = key + "=\"";
42 const size_t val_start_pos = xml.find(key);
43 if (val_start_pos == string::npos)
44 return "";
45 return xml.substr(val_start_pos + key_with_quotes.size(), val_size);
46}
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -080047// Helper to find the count of substring in a string.
48static size_t CountSubstringInString(const string& str, const string& substr) {
49 size_t count = 0, pos = 0;
50 while ((pos = str.find(substr, pos ? pos + 1 : 0)) != string::npos)
51 ++count;
52 return count;
53}
Jae Hoon Kim6ada5912019-06-14 10:11:34 -070054} // namespace
55
56class OmahaRequestBuilderXmlTest : public ::testing::Test {
57 protected:
58 void SetUp() override {}
59 void TearDown() override {}
60
61 FakeSystemState fake_system_state_;
62 static constexpr size_t kGuidSize = 36;
63};
Amin Hassani7fca2862019-03-28 16:09:22 -070064
65TEST_F(OmahaRequestBuilderXmlTest, XmlEncodeTest) {
66 string output;
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070067 vector<pair<string, string>> xml_encode_pairs = {
68 {"ab", "ab"},
69 {"a<b", "a&lt;b"},
70 {"<&>\"\'\\", "&lt;&amp;&gt;&quot;&apos;\\"},
71 {"&lt;&amp;&gt;", "&amp;lt;&amp;amp;&amp;gt;"}};
72 for (const auto& xml_encode_pair : xml_encode_pairs) {
73 const auto& before_encoding = xml_encode_pair.first;
74 const auto& after_encoding = xml_encode_pair.second;
75 EXPECT_TRUE(XmlEncode(before_encoding, &output));
76 EXPECT_EQ(after_encoding, output);
77 }
Amin Hassani7fca2862019-03-28 16:09:22 -070078 // Check that unterminated UTF-8 strings are handled properly.
79 EXPECT_FALSE(XmlEncode("\xc2", &output));
80 // Fail with invalid ASCII-7 chars.
81 EXPECT_FALSE(XmlEncode("This is an 'n' with a tilde: \xc3\xb1", &output));
82}
83
84TEST_F(OmahaRequestBuilderXmlTest, XmlEncodeWithDefaultTest) {
Jae Hoon Kimb7ee3872019-06-06 14:59:03 -070085 EXPECT_EQ("", XmlEncodeWithDefault(""));
Amin Hassani7fca2862019-03-28 16:09:22 -070086 EXPECT_EQ("&lt;&amp;&gt;", XmlEncodeWithDefault("<&>", "something else"));
87 EXPECT_EQ("<not escaped>", XmlEncodeWithDefault("\xc2", "<not escaped>"));
88}
89
Jae Hoon Kim37d15372020-01-08 18:11:26 -080090TEST_F(OmahaRequestBuilderXmlTest, PlatformGetAppTest) {
91 OmahaRequestParams omaha_request_params{&fake_system_state_};
92 omaha_request_params.set_device_requisition("device requisition");
93 OmahaRequestBuilderXml omaha_request{nullptr,
94 &omaha_request_params,
95 false,
96 false,
97 0,
98 0,
99 0,
100 fake_system_state_.prefs(),
101 ""};
Amin Hassani2b68e6b2020-04-17 10:49:12 -0700102 OmahaAppData dlc_app_data = {.id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
103 .version = "",
104 .skip_update = false,
105 .is_dlc = false};
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800106
107 // Verify that the attributes that shouldn't be missing for Platform AppID are
108 // in fact present in the <app ...></app>.
Amin Hassani2b68e6b2020-04-17 10:49:12 -0700109 const string app = omaha_request.GetApp(dlc_app_data);
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800110 EXPECT_NE(string::npos, app.find("lang="));
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800111 EXPECT_NE(string::npos, app.find("requisition="));
112}
113
114TEST_F(OmahaRequestBuilderXmlTest, DlcGetAppTest) {
115 OmahaRequestParams omaha_request_params{&fake_system_state_};
116 omaha_request_params.set_device_requisition("device requisition");
117 OmahaRequestBuilderXml omaha_request{nullptr,
118 &omaha_request_params,
119 false,
120 false,
121 0,
122 0,
123 0,
124 fake_system_state_.prefs(),
125 ""};
Amin Hassani2b68e6b2020-04-17 10:49:12 -0700126 OmahaAppData dlc_app_data = {
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800127 .id = "_dlc_id", .version = "", .skip_update = false, .is_dlc = true};
128
129 // Verify that the attributes that should be missing for DLC AppIDs are in
130 // fact not present in the <app ...></app>.
Amin Hassani2b68e6b2020-04-17 10:49:12 -0700131 const string app = omaha_request.GetApp(dlc_app_data);
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800132 EXPECT_EQ(string::npos, app.find("lang="));
Jae Hoon Kim37d15372020-01-08 18:11:26 -0800133 EXPECT_EQ(string::npos, app.find("requisition="));
134}
135
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700136TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlRequestIdTest) {
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700137 OmahaRequestParams omaha_request_params{&fake_system_state_};
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800138 OmahaRequestBuilderXml omaha_request{nullptr,
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700139 &omaha_request_params,
140 false,
141 false,
142 0,
143 0,
144 0,
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700145 fake_system_state_.prefs(),
146 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700147 const string kRequestXml = omaha_request.GetRequest();
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700148 const string key = "requestid";
149 const string request_id =
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700150 FindAttributeKeyValueInXml(kRequestXml, key, kGuidSize);
Jae Hoon Kim6ada5912019-06-14 10:11:34 -0700151 // A valid |request_id| is either a GUID version 4 or empty string.
152 if (!request_id.empty())
153 EXPECT_TRUE(base::IsValidGUID(request_id));
154}
155
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700156TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlSessionIdTest) {
157 const string gen_session_id = base::GenerateGUID();
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700158 OmahaRequestParams omaha_request_params{&fake_system_state_};
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800159 OmahaRequestBuilderXml omaha_request{nullptr,
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700160 &omaha_request_params,
161 false,
162 false,
163 0,
164 0,
165 0,
166 fake_system_state_.prefs(),
167 gen_session_id};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700168 const string kRequestXml = omaha_request.GetRequest();
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700169 const string key = "sessionid";
170 const string session_id =
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700171 FindAttributeKeyValueInXml(kRequestXml, key, kGuidSize);
Jae Hoon Kimedb65502019-06-14 11:52:17 -0700172 // A valid |session_id| is either a GUID version 4 or empty string.
173 if (!session_id.empty()) {
174 EXPECT_TRUE(base::IsValidGUID(session_id));
175 }
176 EXPECT_EQ(gen_session_id, session_id);
177}
178
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800179TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlPlatformUpdateTest) {
180 OmahaRequestParams omaha_request_params{&fake_system_state_};
181 OmahaRequestBuilderXml omaha_request{nullptr,
182 &omaha_request_params,
183 false,
184 false,
185 0,
186 0,
187 0,
188 fake_system_state_.prefs(),
189 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700190 const string kRequestXml = omaha_request.GetRequest();
191 EXPECT_EQ(1, CountSubstringInString(kRequestXml, "<updatecheck"))
192 << kRequestXml;
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800193}
194
195TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlPlatformUpdateWithDlcsTest) {
196 OmahaRequestParams omaha_request_params{&fake_system_state_};
Andrewe045aef2020-01-08 16:29:22 -0800197 omaha_request_params.set_dlc_apps_params(
198 {{omaha_request_params.GetDlcAppId("dlc_no_0"), {.name = "dlc_no_0"}},
199 {omaha_request_params.GetDlcAppId("dlc_no_1"), {.name = "dlc_no_1"}}});
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800200 OmahaRequestBuilderXml omaha_request{nullptr,
201 &omaha_request_params,
202 false,
203 false,
204 0,
205 0,
206 0,
207 fake_system_state_.prefs(),
208 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700209 const string kRequestXml = omaha_request.GetRequest();
210 EXPECT_EQ(3, CountSubstringInString(kRequestXml, "<updatecheck"))
211 << kRequestXml;
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800212}
213
214TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcInstallationTest) {
215 OmahaRequestParams omaha_request_params{&fake_system_state_};
Andrewe045aef2020-01-08 16:29:22 -0800216 const std::map<std::string, OmahaRequestParams::AppParams> dlcs = {
217 {omaha_request_params.GetDlcAppId("dlc_no_0"), {.name = "dlc_no_0"}},
218 {omaha_request_params.GetDlcAppId("dlc_no_1"), {.name = "dlc_no_1"}}};
219 omaha_request_params.set_dlc_apps_params(dlcs);
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800220 omaha_request_params.set_is_install(true);
221 OmahaRequestBuilderXml omaha_request{nullptr,
222 &omaha_request_params,
223 false,
224 false,
225 0,
226 0,
227 0,
228 fake_system_state_.prefs(),
229 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700230 const string kRequestXml = omaha_request.GetRequest();
231 EXPECT_EQ(2, CountSubstringInString(kRequestXml, "<updatecheck"))
232 << kRequestXml;
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800233
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700234 auto FindAppId = [kRequestXml](size_t pos) -> size_t {
235 return kRequestXml.find("<app appid", pos);
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800236 };
237 // Skip over the Platform AppID, which is always first.
238 size_t pos = FindAppId(0);
239 for (auto&& _ : dlcs) {
240 (void)_;
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700241 EXPECT_NE(string::npos, (pos = FindAppId(pos + 1))) << kRequestXml;
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800242 const string dlc_app_id_version = FindAttributeKeyValueInXml(
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700243 kRequestXml.substr(pos), "version", string(kNoVersion).size());
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800244 EXPECT_EQ(kNoVersion, dlc_app_id_version);
245
246 const string false_str = "false";
247 const string dlc_app_id_delta_okay = FindAttributeKeyValueInXml(
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700248 kRequestXml.substr(pos), "delta_okay", false_str.length());
Jae Hoon Kim5fc00a22020-01-08 20:15:42 -0800249 EXPECT_EQ(false_str, dlc_app_id_delta_okay);
250 }
251}
252
Andrewe045aef2020-01-08 16:29:22 -0800253TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcNoPing) {
254 OmahaRequestParams omaha_request_params{&fake_system_state_};
255 omaha_request_params.set_dlc_apps_params(
256 {{omaha_request_params.GetDlcAppId("dlc_no_0"), {.name = "dlc_no_0"}}});
257 OmahaRequestBuilderXml omaha_request{nullptr,
258 &omaha_request_params,
259 false,
260 false,
261 0,
262 0,
263 0,
264 fake_system_state_.prefs(),
265 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700266 const string kRequestXml = omaha_request.GetRequest();
267 EXPECT_EQ(0, CountSubstringInString(kRequestXml, "<ping")) << kRequestXml;
Andrewe045aef2020-01-08 16:29:22 -0800268}
269
270TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcPingRollCallNoActive) {
271 OmahaRequestParams omaha_request_params{&fake_system_state_};
272 omaha_request_params.set_dlc_apps_params(
273 {{omaha_request_params.GetDlcAppId("dlc_no_0"),
274 {.active_counting_type = OmahaRequestParams::kDateBased,
275 .name = "dlc_no_0",
276 .ping_date_last_active = 25,
277 .ping_date_last_rollcall = 36,
278 .send_ping = true}}});
279 OmahaRequestBuilderXml omaha_request{nullptr,
280 &omaha_request_params,
281 false,
282 false,
283 0,
284 0,
285 0,
286 fake_system_state_.prefs(),
287 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700288 const string kRequestXml = omaha_request.GetRequest();
289 EXPECT_EQ(1, CountSubstringInString(kRequestXml, "<ping rd=\"36\""))
290 << kRequestXml;
Andrewe045aef2020-01-08 16:29:22 -0800291}
292
293TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcPingRollCallAndActive) {
294 OmahaRequestParams omaha_request_params{&fake_system_state_};
295 omaha_request_params.set_dlc_apps_params(
296 {{omaha_request_params.GetDlcAppId("dlc_no_0"),
297 {.active_counting_type = OmahaRequestParams::kDateBased,
298 .name = "dlc_no_0",
299 .ping_active = 1,
300 .ping_date_last_active = 25,
301 .ping_date_last_rollcall = 36,
302 .send_ping = true}}});
303 OmahaRequestBuilderXml omaha_request{nullptr,
304 &omaha_request_params,
305 false,
306 false,
307 0,
308 0,
309 0,
310 fake_system_state_.prefs(),
311 ""};
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700312 const string kRequestXml = omaha_request.GetRequest();
Andrewe045aef2020-01-08 16:29:22 -0800313 EXPECT_EQ(1,
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700314 CountSubstringInString(kRequestXml,
Andrewe045aef2020-01-08 16:29:22 -0800315 "<ping active=\"1\" ad=\"25\" rd=\"36\""))
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700316 << kRequestXml;
317}
318
319TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlUpdateCompleteEvent) {
320 OmahaRequestParams omaha_request_params{&fake_system_state_};
321 OmahaEvent event(OmahaEvent::kTypeUpdateComplete);
322 OmahaRequestBuilderXml omaha_request{&event,
323 &omaha_request_params,
324 false,
325 false,
326 0,
327 0,
328 0,
329 fake_system_state_.prefs(),
330 ""};
331 const string kRequestXml = omaha_request.GetRequest();
332 LOG(INFO) << kRequestXml;
333 EXPECT_EQ(
334 1,
335 CountSubstringInString(
336 kRequestXml, "<event eventtype=\"3\" eventresult=\"1\"></event>"))
337 << kRequestXml;
338}
339
340TEST_F(OmahaRequestBuilderXmlTest,
341 GetRequestXmlUpdateCompleteEventSomeDlcsExcluded) {
342 OmahaRequestParams omaha_request_params{&fake_system_state_};
343 omaha_request_params.set_dlc_apps_params({
344 {omaha_request_params.GetDlcAppId("dlc_1"), {.updated = true}},
345 {omaha_request_params.GetDlcAppId("dlc_2"), {.updated = false}},
346 });
347 OmahaEvent event(OmahaEvent::kTypeUpdateComplete);
348 OmahaRequestBuilderXml omaha_request{&event,
349 &omaha_request_params,
350 false,
351 false,
352 0,
353 0,
354 0,
355 fake_system_state_.prefs(),
356 ""};
357 const string kRequestXml = omaha_request.GetRequest();
358 EXPECT_EQ(
359 2,
360 CountSubstringInString(
361 kRequestXml, "<event eventtype=\"3\" eventresult=\"1\"></event>"))
362 << kRequestXml;
363 EXPECT_EQ(
364 1,
365 CountSubstringInString(
366 kRequestXml,
Amin Hassanie53b39b2020-09-16 11:19:28 -0700367 "<event eventtype=\"3\" eventresult=\"0\" errorcode=\"62\"></event>"))
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700368 << kRequestXml;
369}
370
371TEST_F(OmahaRequestBuilderXmlTest,
372 GetRequestXmlUpdateCompleteEventAllDlcsExcluded) {
373 OmahaRequestParams omaha_request_params{&fake_system_state_};
374 omaha_request_params.set_dlc_apps_params({
375 {omaha_request_params.GetDlcAppId("dlc_1"), {.updated = false}},
376 {omaha_request_params.GetDlcAppId("dlc_2"), {.updated = false}},
377 });
378 OmahaEvent event(OmahaEvent::kTypeUpdateComplete);
379 OmahaRequestBuilderXml omaha_request{&event,
380 &omaha_request_params,
381 false,
382 false,
383 0,
384 0,
385 0,
386 fake_system_state_.prefs(),
387 ""};
388 const string kRequestXml = omaha_request.GetRequest();
389 EXPECT_EQ(
390 1,
391 CountSubstringInString(
392 kRequestXml, "<event eventtype=\"3\" eventresult=\"1\"></event>"))
393 << kRequestXml;
394 EXPECT_EQ(
395 2,
396 CountSubstringInString(
397 kRequestXml,
Amin Hassanie53b39b2020-09-16 11:19:28 -0700398 "<event eventtype=\"3\" eventresult=\"0\" errorcode=\"62\"></event>"))
Jae Hoon Kim3e69b4c2020-06-16 09:23:39 -0700399 << kRequestXml;
Andrewe045aef2020-01-08 16:29:22 -0800400}
Amin Hassani7fca2862019-03-28 16:09:22 -0700401} // namespace chromeos_update_engine