blob: f1d586a27395275c3a409d986b07451417842880 [file] [log] [blame]
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001// Copyright (c) 2012 The Chromium OS 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 <glib.h>
6
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08007#include "base/stringprintf.h"
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08008#include "gmock/gmock.h"
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08009#include "gtest/gtest.h"
10
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080011#include "update_engine/omaha_request_action.h"
12#include "update_engine/payload_state.h"
13#include "update_engine/prefs_mock.h"
14#include "update_engine/test_utils.h"
15#include "update_engine/utils.h"
16
17using std::string;
18using testing::_;
19using testing::NiceMock;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080020using testing::Return;
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080021using testing::SetArgumentPointee;
22
23namespace chromeos_update_engine {
24
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080025static void SetupPayloadStateWith2Urls(string hash,
26 PayloadState* payload_state,
27 OmahaResponse* response) {
28 response->payload_urls.clear();
29 response->payload_urls.push_back("http://test");
30 response->payload_urls.push_back("https://test");
31 response->size = 523456789;
32 response->hash = hash;
33 response->metadata_size = 558123;
34 response->metadata_signature = "metasign";
35 response->max_failure_count_per_url = 3;
36 payload_state->SetResponse(*response);
37 string stored_response = payload_state->GetResponse();
38 string expected_response = StringPrintf(
39 "NumURLs = 2\n"
40 "Url0 = http://test\n"
41 "Url1 = https://test\n"
42 "Payload Size = 523456789\n"
43 "Payload Sha256 Hash = %s\n"
44 "Metadata Size = 558123\n"
45 "Metadata Signature = metasign\n",
46 hash.c_str());
47 EXPECT_EQ(expected_response, stored_response);
48}
49
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080050class PayloadStateTest : public ::testing::Test { };
51
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080052TEST(PayloadStateTest, DidYouAddANewActionExitCode) {
53 if (kActionCodeUmaReportedMax != 40) {
54 LOG(ERROR) << "The following failure is intentional. If you added a new "
55 << "ActionExitCode enum value, make sure to add it to the "
56 << "PayloadState::UpdateFailed method and then update this test "
57 << "to the new value of kActionCodeUmaReportedMax, which is "
58 << kActionCodeUmaReportedMax;
59 EXPECT_FALSE("Please see the log line above");
60 }
61}
62
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080063TEST(PayloadStateTest, SetResponseWorksWithEmptyResponse) {
64 OmahaResponse response;
65 NiceMock<PrefsMock> prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080066 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0));
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080067 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0));
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080068 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0));
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080069 PayloadState payload_state;
70 EXPECT_TRUE(payload_state.Initialize(&prefs));
71 payload_state.SetResponse(response);
72 string stored_response = payload_state.GetResponse();
73 string expected_response = "NumURLs = 0\n"
74 "Payload Size = 0\n"
75 "Payload Sha256 Hash = \n"
76 "Metadata Size = 0\n"
77 "Metadata Signature = \n";
78 EXPECT_EQ(expected_response, stored_response);
79 EXPECT_EQ(0, payload_state.GetUrlIndex());
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080080 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080081}
82
83TEST(PayloadStateTest, SetResponseWorksWithSingleUrl) {
84 OmahaResponse response;
85 response.payload_urls.push_back("http://single.url.test");
86 response.size = 123456789;
87 response.hash = "hash";
88 response.metadata_size = 58123;
89 response.metadata_signature = "msign";
90 NiceMock<PrefsMock> prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080091 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0));
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080092 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0));
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080093 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0));
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080094 PayloadState payload_state;
95 EXPECT_TRUE(payload_state.Initialize(&prefs));
96 payload_state.SetResponse(response);
97 string stored_response = payload_state.GetResponse();
98 string expected_response = "NumURLs = 1\n"
99 "Url0 = http://single.url.test\n"
100 "Payload Size = 123456789\n"
101 "Payload Sha256 Hash = hash\n"
102 "Metadata Size = 58123\n"
103 "Metadata Signature = msign\n";
104 EXPECT_EQ(expected_response, stored_response);
105 EXPECT_EQ(0, payload_state.GetUrlIndex());
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800106 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800107}
108
109TEST(PayloadStateTest, SetResponseWorksWithMultipleUrls) {
110 OmahaResponse response;
111 response.payload_urls.push_back("http://multiple.url.test");
112 response.payload_urls.push_back("https://multiple.url.test");
113 response.size = 523456789;
114 response.hash = "rhash";
115 response.metadata_size = 558123;
116 response.metadata_signature = "metasign";
117 NiceMock<PrefsMock> prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800118 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0));
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800119 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0));
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800120 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0));
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800121 PayloadState payload_state;
122 EXPECT_TRUE(payload_state.Initialize(&prefs));
123 payload_state.SetResponse(response);
124 string stored_response = payload_state.GetResponse();
125 string expected_response = "NumURLs = 2\n"
126 "Url0 = http://multiple.url.test\n"
127 "Url1 = https://multiple.url.test\n"
128 "Payload Size = 523456789\n"
129 "Payload Sha256 Hash = rhash\n"
130 "Metadata Size = 558123\n"
131 "Metadata Signature = metasign\n";
132 EXPECT_EQ(expected_response, stored_response);
133 EXPECT_EQ(0, payload_state.GetUrlIndex());
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800134 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800135}
136
137TEST(PayloadStateTest, CanAdvanceUrlIndexCorrectly) {
138 OmahaResponse response;
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800139 NiceMock<PrefsMock> prefs;
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800140 PayloadState payload_state;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800141
142 // Payload attempt should start with 0 and then advance to 1.
143 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0)).Times(1);
144 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 1)).Times(1);
145
146 // Url index should go from 0 to 1 twice.
147 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(2);
148 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(2);
149
150 // Failure count should be called each times url index is set, so that's
151 // 4 times for this test.
152 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0)).Times(4);
153
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800154 EXPECT_TRUE(payload_state.Initialize(&prefs));
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800155
156 // This does a SetResponse which causes all the states to be set to 0 for
157 // the first time.
158 SetupPayloadStateWith2Urls("Hash1235", &payload_state, &response);
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800159 EXPECT_EQ(0, payload_state.GetUrlIndex());
160
161 // Verify that on the first error, the URL index advances to 1.
162 ActionExitCode error = kActionCodeDownloadMetadataSignatureMismatch;
163 payload_state.UpdateFailed(error);
164 EXPECT_EQ(1, payload_state.GetUrlIndex());
165
166 // Verify that on the next error, the URL index wraps around to 0.
167 payload_state.UpdateFailed(error);
168 EXPECT_EQ(0, payload_state.GetUrlIndex());
169
170 // Verify that on the next error, it again advances to 1.
171 payload_state.UpdateFailed(error);
172 EXPECT_EQ(1, payload_state.GetUrlIndex());
173}
174
175TEST(PayloadStateTest, NewResponseResetsPayloadState) {
176 OmahaResponse response;
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800177 NiceMock<PrefsMock> prefs;
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800178 PayloadState payload_state;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800179
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800180 EXPECT_TRUE(payload_state.Initialize(&prefs));
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800181
182 // Set the first response.
183 SetupPayloadStateWith2Urls("Hash5823", &payload_state, &response);
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800184
185 // Advance the URL index to 1 by faking an error.
186 ActionExitCode error = kActionCodeDownloadMetadataSignatureMismatch;
187 payload_state.UpdateFailed(error);
188 EXPECT_EQ(1, payload_state.GetUrlIndex());
189
190 // Now, slightly change the response and set it again.
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800191 SetupPayloadStateWith2Urls("Hash8225", &payload_state, &response);
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800192
193 // Make sure the url index was reset to 0 because of the new response.
194 EXPECT_EQ(0, payload_state.GetUrlIndex());
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800195 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800196}
197
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800198TEST(PayloadStateTest, AllCountersGetUpdatedProperlyOnErrorCodesAndEvents) {
199 OmahaResponse response;
200 PayloadState payload_state;
201 NiceMock<PrefsMock> prefs;
202
203 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0)).Times(2);
204 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 1)).Times(1);
205 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 2)).Times(1);
206
207 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(4);
208 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(2);
209
210 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0)).Times(7);
211 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 1)).Times(2);
212 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 2)).Times(1);
213
214 EXPECT_TRUE(payload_state.Initialize(&prefs));
215
216 SetupPayloadStateWith2Urls("Hash5873", &payload_state, &response);
217
218 // This should advance the URL index.
219 payload_state.UpdateFailed(kActionCodeDownloadMetadataSignatureMismatch);
220 EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
221 EXPECT_EQ(1, payload_state.GetUrlIndex());
222 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
223
224 // This should advance the failure count only.
225 payload_state.UpdateFailed(kActionCodeDownloadTransferError);
226 EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
227 EXPECT_EQ(1, payload_state.GetUrlIndex());
228 EXPECT_EQ(1, payload_state.GetUrlFailureCount());
229
230 // This should advance the failure count only.
231 payload_state.UpdateFailed(kActionCodeDownloadTransferError);
232 EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
233 EXPECT_EQ(1, payload_state.GetUrlIndex());
234 EXPECT_EQ(2, payload_state.GetUrlFailureCount());
235
236 // This should advance the URL index as we've reached the
237 // max failure count and reset the failure count for the new URL index.
238 // This should also wrap around the URL index and thus cause the payload
239 // attempt number to be incremented.
240 payload_state.UpdateFailed(kActionCodeDownloadTransferError);
241 EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
242 EXPECT_EQ(0, payload_state.GetUrlIndex());
243 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
244
245 // This should advance the URL index.
246 payload_state.UpdateFailed(kActionCodePayloadHashMismatchError);
247 EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
248 EXPECT_EQ(1, payload_state.GetUrlIndex());
249 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
250
251 // This should advance the URL index and payload attempt number due to
252 // wrap-around of URL index.
253 payload_state.UpdateFailed(kActionCodeDownloadMetadataSignatureMissingError);
254 EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
255 EXPECT_EQ(0, payload_state.GetUrlIndex());
256 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
257
258 // This HTTP error code should only increase the failure count.
259 payload_state.UpdateFailed(static_cast<ActionExitCode>(
260 kActionCodeOmahaRequestHTTPResponseBase + 404));
261 EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
262 EXPECT_EQ(0, payload_state.GetUrlIndex());
263 EXPECT_EQ(1, payload_state.GetUrlFailureCount());
264
265 // And that failure count should be reset when we download some bytes
266 // afterwards.
267 payload_state.DownloadProgress(100);
268 EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
269 EXPECT_EQ(0, payload_state.GetUrlIndex());
270 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
271
272 // Now, slightly change the response and set it again.
273 SetupPayloadStateWith2Urls("Hash8532", &payload_state, &response);
274
275 // Make sure the url index was reset to 0 because of the new response.
276 EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
277 EXPECT_EQ(0, payload_state.GetUrlIndex());
278 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
279}
280
281TEST(PayloadStateTest, PayloadAttemptNumberIncreasesOnSuccessfulDownload) {
282 OmahaResponse response;
283 PayloadState payload_state;
284 NiceMock<PrefsMock> prefs;
285
286 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0)).Times(1);
287 EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 1)).Times(1);
288
289 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(1);
290 EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0)).Times(1);
291
292 EXPECT_TRUE(payload_state.Initialize(&prefs));
293
294 SetupPayloadStateWith2Urls("Hash8593", &payload_state, &response);
295
296 // This should just advance the payload attempt number;
297 EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
298 payload_state.DownloadComplete();
299 EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
300 EXPECT_EQ(0, payload_state.GetUrlIndex());
301 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
302}
303
304TEST(PayloadStateTest, SetResponseResetsInvalidUrlIndex) {
305 OmahaResponse response;
306 PayloadState payload_state;
307 NiceMock<PrefsMock> prefs;
308
309 EXPECT_TRUE(payload_state.Initialize(&prefs));
310 SetupPayloadStateWith2Urls("Hash4427", &payload_state, &response);
311
312 // Generate enough events to advance URL index, failure count and
313 // payload attempt number all to 1.
314 payload_state.DownloadComplete();
315 payload_state.UpdateFailed(kActionCodeDownloadMetadataSignatureMismatch);
316 payload_state.UpdateFailed(kActionCodeDownloadTransferError);
317 EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
318 EXPECT_EQ(1, payload_state.GetUrlIndex());
319 EXPECT_EQ(1, payload_state.GetUrlFailureCount());
320
321 // Now, simulate a corrupted url index on persisted store which gets
322 // loaded when update_engine restarts. Using a different prefs object
323 // so as to not bother accounting for the uninteresting calls above.
324 NiceMock<PrefsMock> prefs2;
325 EXPECT_CALL(prefs2, Exists(_)).WillRepeatedly(Return(true));
326 EXPECT_CALL(prefs2, GetInt64(kPrefsPayloadAttemptNumber, _));
327 EXPECT_CALL(prefs2, GetInt64(kPrefsCurrentUrlIndex, _))
328 .WillOnce(DoAll(SetArgumentPointee<1>(2), Return(true)));
329 EXPECT_CALL(prefs2, GetInt64(kPrefsCurrentUrlFailureCount, _));
330
331 // Note: This will be a different payload object, but the response should
332 // have the same hash as before so as to not trivially reset because the
333 // response was different. We want to specifically test that even if the
334 // response is same, we should reset the state if we find it corrupted.
335 EXPECT_TRUE(payload_state.Initialize(&prefs2));
336 SetupPayloadStateWith2Urls("Hash4427", &payload_state, &response);
337
338 // Make sure all counters get reset to 0 because of the corrupted URL index
339 // we supplied above.
340 EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
341 EXPECT_EQ(0, payload_state.GetUrlIndex());
342 EXPECT_EQ(0, payload_state.GetUrlFailureCount());
343}
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800344}