1#!/usr/bin/python
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import mox
7import unittest
8
9import common
10
11import autoupdater
12from autotest_lib.client.common_lib import error
13
14class TestAutoUpdater(mox.MoxTestBase):
15    """Test autoupdater module."""
16
17
18    def testParseBuildFromUpdateUrlwithUpdate(self):
19        """Test that we properly parse the build from an update_url."""
20        update_url = ('http://172.22.50.205:8082/update/lumpy-release/'
21                      'R27-3837.0.0')
22        expected_value = 'lumpy-release/R27-3837.0.0'
23        self.assertEqual(autoupdater.url_to_image_name(update_url),
24                         expected_value)
25
26
27    def testCheckVersion_1(self):
28        """Test version check methods work for any build.
29
30        Test two methods used to check version, check_version and
31        check_version_to_confirm_install, for:
32        1. trybot paladin build.
33        update version: trybot-lumpy-paladin/R27-3837.0.0-b123
34        booted version: 3837.0.2013_03_21_1340
35
36        """
37        update_url = ('http://172.22.50.205:8082/update/trybot-lumpy-paladin/'
38                      'R27-1111.0.0-b123')
39        updater = autoupdater.ChromiumOSUpdater(
40                update_url, host=self.mox.CreateMockAnything())
41
42        self.mox.UnsetStubs()
43        self.mox.StubOutWithMock(updater.host, 'get_release_version')
44        updater.host.get_release_version().MultipleTimes().AndReturn(
45                                                    '1111.0.2013_03_21_1340')
46        self.mox.ReplayAll()
47
48        self.assertFalse(updater.check_version())
49        self.assertTrue(updater.check_version_to_confirm_install())
50
51        self.mox.UnsetStubs()
52        self.mox.StubOutWithMock(updater.host, 'get_release_version')
53        updater.host.get_release_version().MultipleTimes().AndReturn(
54                '1111.0.0-rc1')
55        self.mox.ReplayAll()
56
57        self.assertFalse(updater.check_version())
58        self.assertFalse(updater.check_version_to_confirm_install())
59
60        self.mox.UnsetStubs()
61        self.mox.StubOutWithMock(updater.host, 'get_release_version')
62        updater.host.get_release_version().MultipleTimes().AndReturn('1111.0.0')
63        self.mox.ReplayAll()
64
65        self.assertFalse(updater.check_version())
66        self.assertFalse(updater.check_version_to_confirm_install())
67
68        self.mox.UnsetStubs()
69        self.mox.StubOutWithMock(updater.host, 'get_release_version')
70        updater.host.get_release_version().MultipleTimes().AndReturn(
71                                                    '4444.0.0-pgo-generate')
72        self.mox.ReplayAll()
73
74        self.assertFalse(updater.check_version())
75        self.assertFalse(updater.check_version_to_confirm_install())
76
77
78    def testCheckVersion_2(self):
79        """Test version check methods work for any build.
80
81        Test two methods used to check version, check_version and
82        check_version_to_confirm_install, for:
83        2. trybot release build.
84        update version: trybot-lumpy-release/R27-3837.0.0-b456
85        booted version: 3837.0.0
86
87        """
88        update_url = ('http://172.22.50.205:8082/update/trybot-lumpy-release/'
89                      'R27-2222.0.0-b456')
90        updater = autoupdater.ChromiumOSUpdater(
91                update_url, host=self.mox.CreateMockAnything())
92
93        self.mox.UnsetStubs()
94        self.mox.StubOutWithMock(updater.host, 'get_release_version')
95        updater.host.get_release_version().MultipleTimes().AndReturn(
96                                                    '2222.0.2013_03_21_1340')
97        self.mox.ReplayAll()
98
99        self.assertFalse(updater.check_version())
100        self.assertFalse(updater.check_version_to_confirm_install())
101
102        self.mox.UnsetStubs()
103        self.mox.StubOutWithMock(updater.host, 'get_release_version')
104        updater.host.get_release_version().MultipleTimes().AndReturn(
105                '2222.0.0-rc1')
106        self.mox.ReplayAll()
107
108        self.assertFalse(updater.check_version())
109        self.assertFalse(updater.check_version_to_confirm_install())
110
111        self.mox.UnsetStubs()
112        self.mox.StubOutWithMock(updater.host, 'get_release_version')
113        updater.host.get_release_version().MultipleTimes().AndReturn('2222.0.0')
114        self.mox.ReplayAll()
115
116        self.assertFalse(updater.check_version())
117        self.assertTrue(updater.check_version_to_confirm_install())
118
119        self.mox.UnsetStubs()
120        self.mox.StubOutWithMock(updater.host, 'get_release_version')
121        updater.host.get_release_version().MultipleTimes().AndReturn(
122                                                    '4444.0.0-pgo-generate')
123        self.mox.ReplayAll()
124
125        self.assertFalse(updater.check_version())
126        self.assertFalse(updater.check_version_to_confirm_install())
127
128
129    def testCheckVersion_3(self):
130        """Test version check methods work for any build.
131
132        Test two methods used to check version, check_version and
133        check_version_to_confirm_install, for:
134        3. buildbot official release build.
135        update version: lumpy-release/R27-3837.0.0
136        booted version: 3837.0.0
137
138        """
139        update_url = ('http://172.22.50.205:8082/update/lumpy-release/'
140                      'R27-3333.0.0')
141        updater = autoupdater.ChromiumOSUpdater(
142                update_url, host=self.mox.CreateMockAnything())
143
144        self.mox.UnsetStubs()
145        self.mox.StubOutWithMock(updater.host, 'get_release_version')
146        updater.host.get_release_version().MultipleTimes().AndReturn(
147                                                    '3333.0.2013_03_21_1340')
148        self.mox.ReplayAll()
149
150        self.assertFalse(updater.check_version())
151        self.assertFalse(updater.check_version_to_confirm_install())
152
153        self.mox.UnsetStubs()
154        self.mox.StubOutWithMock(updater.host, 'get_release_version')
155        updater.host.get_release_version().MultipleTimes().AndReturn(
156                '3333.0.0-rc1')
157        self.mox.ReplayAll()
158
159        self.assertFalse(updater.check_version())
160        self.assertFalse(updater.check_version_to_confirm_install())
161
162        self.mox.UnsetStubs()
163        self.mox.StubOutWithMock(updater.host, 'get_release_version')
164        updater.host.get_release_version().MultipleTimes().AndReturn('3333.0.0')
165        self.mox.ReplayAll()
166
167        self.assertTrue(updater.check_version())
168        self.assertTrue(updater.check_version_to_confirm_install())
169
170        self.mox.UnsetStubs()
171        self.mox.StubOutWithMock(updater.host, 'get_release_version')
172        updater.host.get_release_version().MultipleTimes().AndReturn(
173                                                    '4444.0.0-pgo-generate')
174        self.mox.ReplayAll()
175
176        self.assertFalse(updater.check_version())
177        self.assertFalse(updater.check_version_to_confirm_install())
178
179
180    def testCheckVersion_4(self):
181        """Test version check methods work for any build.
182
183        Test two methods used to check version, check_version and
184        check_version_to_confirm_install, for:
185        4. non-official paladin rc build.
186        update version: lumpy-paladin/R27-3837.0.0-rc7
187        booted version: 3837.0.0-rc7
188
189        """
190        update_url = ('http://172.22.50.205:8082/update/lumpy-paladin/'
191                      'R27-4444.0.0-rc7')
192        updater = autoupdater.ChromiumOSUpdater(
193                update_url, host=self.mox.CreateMockAnything())
194
195        self.mox.UnsetStubs()
196        self.mox.StubOutWithMock(updater.host, 'get_release_version')
197        updater.host.get_release_version().MultipleTimes().AndReturn(
198                                                    '4444.0.2013_03_21_1340')
199        self.mox.ReplayAll()
200
201        self.assertFalse(updater.check_version())
202        self.assertFalse(updater.check_version_to_confirm_install())
203
204        self.mox.UnsetStubs()
205        self.mox.StubOutWithMock(updater.host, 'get_release_version')
206        updater.host.get_release_version().MultipleTimes().AndReturn(
207                '4444.0.0-rc7')
208        self.mox.ReplayAll()
209
210        self.assertTrue(updater.check_version())
211        self.assertTrue(updater.check_version_to_confirm_install())
212
213        self.mox.UnsetStubs()
214        self.mox.StubOutWithMock(updater.host, 'get_release_version')
215        updater.host.get_release_version().MultipleTimes().AndReturn('4444.0.0')
216        self.mox.ReplayAll()
217
218        self.assertFalse(updater.check_version())
219        self.assertFalse(updater.check_version_to_confirm_install())
220
221        self.mox.UnsetStubs()
222        self.mox.StubOutWithMock(updater.host, 'get_release_version')
223        updater.host.get_release_version().MultipleTimes().AndReturn(
224                                                    '4444.0.0-pgo-generate')
225        self.mox.ReplayAll()
226
227        self.assertFalse(updater.check_version())
228        self.assertFalse(updater.check_version_to_confirm_install())
229
230
231    def testCheckVersion_5(self):
232        """Test version check methods work for any build.
233
234        Test two methods used to check version, check_version and
235        check_version_to_confirm_install, for:
236        5. chrome-perf build.
237        update version: lumpy-chrome-perf/R28-3837.0.0-b2996
238        booted version: 3837.0.0
239
240        """
241        update_url = ('http://172.22.50.205:8082/update/lumpy-chrome-perf/'
242                      'R28-4444.0.0-b2996')
243        updater = autoupdater.ChromiumOSUpdater(
244                update_url, host=self.mox.CreateMockAnything())
245
246        self.mox.UnsetStubs()
247        self.mox.StubOutWithMock(updater.host, 'get_release_version')
248        updater.host.get_release_version().MultipleTimes().AndReturn(
249                                                    '4444.0.2013_03_21_1340')
250        self.mox.ReplayAll()
251
252        self.assertFalse(updater.check_version())
253        self.assertFalse(updater.check_version_to_confirm_install())
254
255        self.mox.UnsetStubs()
256        self.mox.StubOutWithMock(updater.host, 'get_release_version')
257        updater.host.get_release_version().MultipleTimes().AndReturn(
258                '4444.0.0-rc7')
259        self.mox.ReplayAll()
260
261        self.assertFalse(updater.check_version())
262        self.assertFalse(updater.check_version_to_confirm_install())
263
264        self.mox.UnsetStubs()
265        self.mox.StubOutWithMock(updater.host, 'get_release_version')
266        updater.host.get_release_version().MultipleTimes().AndReturn('4444.0.0')
267        self.mox.ReplayAll()
268
269        self.assertFalse(updater.check_version())
270        self.assertTrue(updater.check_version_to_confirm_install())
271
272        self.mox.UnsetStubs()
273        self.mox.StubOutWithMock(updater.host, 'get_release_version')
274        updater.host.get_release_version().MultipleTimes().AndReturn(
275                                                    '4444.0.0-pgo-generate')
276        self.mox.ReplayAll()
277
278        self.assertFalse(updater.check_version())
279        self.assertFalse(updater.check_version_to_confirm_install())
280
281
282    def testCheckVersion_6(self):
283        """Test version check methods work for any build.
284
285        Test two methods used to check version, check_version and
286        check_version_to_confirm_install, for:
287        6. pgo-generate build.
288        update version: lumpy-release-pgo-generate/R28-3837.0.0-b2996
289        booted version: 3837.0.0-pgo-generate
290
291        """
292        update_url = ('http://172.22.50.205:8082/update/lumpy-release-pgo-'
293                      'generate/R28-4444.0.0-b2996')
294        updater = autoupdater.ChromiumOSUpdater(
295                update_url, host=self.mox.CreateMockAnything())
296
297        self.mox.UnsetStubs()
298        self.mox.StubOutWithMock(updater.host, 'get_release_version')
299        updater.host.get_release_version().MultipleTimes().AndReturn(
300                                                    '4444.0.0-2013_03_21_1340')
301        self.mox.ReplayAll()
302
303        self.assertFalse(updater.check_version())
304        self.assertFalse(updater.check_version_to_confirm_install())
305
306        self.mox.UnsetStubs()
307        self.mox.StubOutWithMock(updater.host, 'get_release_version')
308        updater.host.get_release_version().MultipleTimes().AndReturn(
309                '4444.0.0-rc7')
310        self.mox.ReplayAll()
311
312        self.assertFalse(updater.check_version())
313        self.assertFalse(updater.check_version_to_confirm_install())
314
315        self.mox.UnsetStubs()
316        self.mox.StubOutWithMock(updater.host, 'get_release_version')
317        updater.host.get_release_version().MultipleTimes().AndReturn('4444.0.0')
318        self.mox.ReplayAll()
319
320        self.assertFalse(updater.check_version())
321        self.assertFalse(updater.check_version_to_confirm_install())
322
323        self.mox.UnsetStubs()
324        self.mox.StubOutWithMock(updater.host, 'get_release_version')
325        updater.host.get_release_version().MultipleTimes().AndReturn(
326                                                    '4444.0.0-pgo-generate')
327        self.mox.ReplayAll()
328
329        self.assertFalse(updater.check_version())
330        self.assertTrue(updater.check_version_to_confirm_install())
331
332
333    def testCheckVersion_7(self):
334        """Test version check methods work for a test-ap build.
335
336        Test two methods used to check version, check_version and
337        check_version_to_confirm_install, for:
338        6. test-ap build.
339        update version: trybot-stumpy-test-ap/R46-7298.0.0-b23
340        booted version: 7298.0.0
341
342        """
343        update_url = ('http://100.107.160.2:8082/update/trybot-stumpy-test-api'
344                      '/R46-7298.0.0-b23')
345        updater = autoupdater.ChromiumOSUpdater(
346                update_url, host=self.mox.CreateMockAnything())
347
348        self.mox.UnsetStubs()
349        self.mox.StubOutWithMock(updater.host, 'get_release_version')
350        updater.host.get_release_version().MultipleTimes().AndReturn(
351                '7298.0.2015_07_24_1640')
352        self.mox.ReplayAll()
353
354        self.assertFalse(updater.check_version())
355        self.assertTrue(updater.check_version_to_confirm_install())
356
357        self.mox.UnsetStubs()
358        self.mox.StubOutWithMock(updater.host, 'get_release_version')
359        updater.host.get_release_version().MultipleTimes().AndReturn(
360                '7298.0.2015_07_24_1640')
361        self.mox.ReplayAll()
362
363        self.assertFalse(updater.check_version())
364        self.assertTrue(updater.check_version_to_confirm_install())
365
366        self.mox.UnsetStubs()
367        self.mox.StubOutWithMock(updater.host, 'get_release_version')
368        updater.host.get_release_version().MultipleTimes().AndReturn('7298.0.0')
369        self.mox.ReplayAll()
370
371        self.assertFalse(updater.check_version())
372        self.assertFalse(updater.check_version_to_confirm_install())
373
374        self.mox.UnsetStubs()
375        self.mox.StubOutWithMock(updater.host, 'get_release_version')
376        updater.host.get_release_version().MultipleTimes().AndReturn(
377                '7298.0.0')
378        self.mox.ReplayAll()
379
380        self.assertFalse(updater.check_version())
381        self.assertFalse(updater.check_version_to_confirm_install())
382
383
384    def testTriggerUpdate(self):
385        """Tests that we correctly handle updater errors."""
386        update_url = 'http://server/test/url'
387        host = self.mox.CreateMockAnything()
388        self.mox.StubOutWithMock(host, 'run')
389        host.hostname = 'test_host'
390
391        expected_cmd = ('/usr/bin/update_engine_client --check_for_update '
392                        '--omaha_url=http://server/test/url')
393
394        updater = autoupdater.ChromiumOSUpdater(update_url, host=host)
395
396        # Test with success.
397        host.run(expected_cmd)
398
399        # SSH Timeout
400        host.run(expected_cmd).AndRaise(
401                error.AutoservSSHTimeout("ssh timed out", 255))
402
403        # SSH Permission Error
404        host.run(expected_cmd).AndRaise(
405                error.AutoservSshPermissionDeniedError("ssh timed out", 255))
406
407        # Command Failed Error
408        cmd_result_1 = self.mox.CreateMockAnything()
409        cmd_result_1.exit_status = 1
410
411        host.run(expected_cmd).AndRaise(
412                error.AutoservRunError("ssh timed out", cmd_result_1))
413
414        # Generic SSH Error (maybe)
415        cmd_result_255 = self.mox.CreateMockAnything()
416        cmd_result_255.exit_status = 255
417
418        host.run(expected_cmd).AndRaise(
419                error.AutoservRunError("Sometimes SSH specific result.",
420                                       cmd_result_255))
421
422        self.mox.ReplayAll()
423
424        # Verify Success.
425        updater.trigger_update()
426
427        # Verify each type of error listed above.
428        self.assertRaises(autoupdater.RootFSUpdateError,
429                          updater.trigger_update)
430        self.assertRaises(autoupdater.RootFSUpdateError,
431                          updater.trigger_update)
432        self.assertRaises(autoupdater.RootFSUpdateError,
433                          updater.trigger_update)
434        self.assertRaises(autoupdater.RootFSUpdateError,
435                          updater.trigger_update)
436
437        self.mox.VerifyAll()
438
439
440    def testUpdateStateful(self):
441        """Tests that we call the stateful update script with the correct args.
442        """
443        self.mox.StubOutWithMock(autoupdater.ChromiumOSUpdater, '_run')
444        self.mox.StubOutWithMock(autoupdater.ChromiumOSUpdater,
445                                 'get_stateful_update_script')
446        update_url = ('http://172.22.50.205:8082/update/lumpy-chrome-perf/'
447                      'R28-4444.0.0-b2996')
448        static_update_url = ('http://172.22.50.205:8082/static/'
449                             'lumpy-chrome-perf/R28-4444.0.0-b2996')
450
451        # Test with clobber=False.
452        autoupdater.ChromiumOSUpdater.get_stateful_update_script().AndReturn(
453                autoupdater.ChromiumOSUpdater.REMOTE_STATEUL_UPDATE_PATH)
454        autoupdater.ChromiumOSUpdater._run(
455                mox.And(
456                        mox.StrContains(
457                                autoupdater.ChromiumOSUpdater.
458                                REMOTE_STATEUL_UPDATE_PATH),
459                        mox.StrContains(static_update_url),
460                        mox.Not(mox.StrContains('--stateful_change=clean'))),
461                timeout=mox.IgnoreArg())
462
463        self.mox.ReplayAll()
464        updater = autoupdater.ChromiumOSUpdater(update_url)
465        updater.update_stateful(clobber=False)
466        self.mox.VerifyAll()
467
468        # Test with clobber=True.
469        self.mox.ResetAll()
470        autoupdater.ChromiumOSUpdater.get_stateful_update_script().AndReturn(
471                autoupdater.ChromiumOSUpdater.REMOTE_STATEUL_UPDATE_PATH)
472        autoupdater.ChromiumOSUpdater._run(
473                mox.And(
474                        mox.StrContains(
475                                autoupdater.ChromiumOSUpdater.
476                                REMOTE_STATEUL_UPDATE_PATH),
477                        mox.StrContains(static_update_url),
478                        mox.StrContains('--stateful_change=clean')),
479                timeout=mox.IgnoreArg())
480        self.mox.ReplayAll()
481        updater = autoupdater.ChromiumOSUpdater(update_url)
482        updater.update_stateful(clobber=True)
483        self.mox.VerifyAll()
484
485
486    def testRollbackRootfs(self):
487        """Tests that we correctly rollback the rootfs when requested."""
488        self.mox.StubOutWithMock(autoupdater.ChromiumOSUpdater, '_run')
489        self.mox.StubOutWithMock(autoupdater.ChromiumOSUpdater,
490                                 '_verify_update_completed')
491        host = self.mox.CreateMockAnything()
492        update_url = 'http://server/test/url'
493        host.hostname = 'test_host'
494
495        can_rollback_cmd = ('/usr/bin/update_engine_client --can_rollback')
496        rollback_cmd = ('/usr/bin/update_engine_client --rollback '
497                        '--follow')
498
499        updater = autoupdater.ChromiumOSUpdater(update_url, host=host)
500
501        # Return an old build which shouldn't call can_rollback.
502        updater.host.get_release_version().AndReturn('1234.0.0')
503        autoupdater.ChromiumOSUpdater._run(rollback_cmd)
504        autoupdater.ChromiumOSUpdater._verify_update_completed()
505
506        self.mox.ReplayAll()
507        updater.rollback_rootfs(powerwash=True)
508        self.mox.VerifyAll()
509
510        self.mox.ResetAll()
511        cmd_result_1 = self.mox.CreateMockAnything()
512        cmd_result_1.exit_status = 1
513
514        # Rollback but can_rollback says we can't -- return an error.
515        updater.host.get_release_version().AndReturn('5775.0.0')
516        autoupdater.ChromiumOSUpdater._run(can_rollback_cmd).AndRaise(
517                error.AutoservRunError('can_rollback failed', cmd_result_1))
518        self.mox.ReplayAll()
519        self.assertRaises(autoupdater.RootFSUpdateError,
520                          updater.rollback_rootfs, True)
521        self.mox.VerifyAll()
522
523        self.mox.ResetAll()
524        # Rollback >= version blacklisted.
525        updater.host.get_release_version().AndReturn('5775.0.0')
526        autoupdater.ChromiumOSUpdater._run(can_rollback_cmd)
527        autoupdater.ChromiumOSUpdater._run(rollback_cmd)
528        autoupdater.ChromiumOSUpdater._verify_update_completed()
529        self.mox.ReplayAll()
530        updater.rollback_rootfs(powerwash=True)
531        self.mox.VerifyAll()
532
533
534if __name__ == '__main__':
535  unittest.main()
536