blob: 3ac48cbf15640228d17613aa403bc71bccfa8f14 [file] [log] [blame]
Mike Frysingerd13faeb2013-09-05 16:00:46 -04001# Copyright (c) 2013 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"""Unittests for pushimage.py"""
6
Mike Frysingerd7c93092019-10-14 00:12:50 -04007import collections
Mike Frysingerd13faeb2013-09-05 16:00:46 -04008import os
Mike Frysinger166fea02021-02-12 05:30:33 -05009from unittest import mock
Mike Frysingerd13faeb2013-09-05 16:00:46 -040010
Mike Frysinger6791b1d2014-03-04 20:52:22 -050011from chromite.lib import cros_build_lib
Mike Frysingerd13faeb2013-09-05 16:00:46 -040012from chromite.lib import cros_test_lib
Don Garrett9fd20a82014-09-04 11:37:22 -070013from chromite.lib import gs
Mike Frysingerd13faeb2013-09-05 16:00:46 -040014from chromite.lib import gs_unittest
15from chromite.lib import osutils
Mike Frysinger4495b032014-03-05 17:24:03 -050016from chromite.lib import partial_mock
Mike Frysingerd13faeb2013-09-05 16:00:46 -040017from chromite.lib import signing
18from chromite.scripts import pushimage
19
20
Greg Edelstona4c9b3b2020-01-07 17:51:13 -070021# Use our local copy of insns for testing as the main one is not available in
22# the public manifest. Even though _REL is a relative path, this works because
23# os.join leaves absolute paths on the right hand side alone.
24signing.INPUT_INSN_DIR_REL = signing.TEST_INPUT_INSN_DIR
25
26
Mike Frysingerd13faeb2013-09-05 16:00:46 -040027class InputInsnsTest(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -060028 """Tests for InputInsns"""
Mike Frysingerd13faeb2013-09-05 16:00:46 -040029
Alex Klein1699fab2022-09-08 08:46:06 -060030 def setUp(self):
31 self.StartPatcher(gs_unittest.GSContextMock())
Don Garrettac529772015-04-29 15:09:26 -070032
Alex Klein1699fab2022-09-08 08:46:06 -060033 def testBasic(self):
34 """Simple smoke test"""
35 insns = pushimage.InputInsns("test.board")
36 insns.GetInsnFile("recovery")
37 self.assertEqual(insns.GetChannels(), ["dev", "canary"])
38 self.assertEqual(insns.GetKeysets(), ["stumpy-mp-v3"])
Mike Frysingerd13faeb2013-09-05 16:00:46 -040039
Alex Klein1699fab2022-09-08 08:46:06 -060040 def testGetInsnFile(self):
41 """Verify various inputs result in right insns path"""
42 testdata = (
43 ("UPPER_CAPS", "UPPER_CAPS"),
44 ("recovery", "test.board"),
45 ("firmware", "test.board.firmware"),
46 ("factory", "test.board.factory"),
47 )
48 insns = pushimage.InputInsns("test.board")
49 for image_type, filename in testdata:
50 ret = insns.GetInsnFile(image_type)
51 self.assertEqual(
52 os.path.basename(ret), "%s.instructions" % (filename)
53 )
Mike Frysingerd13faeb2013-09-05 16:00:46 -040054
Alex Klein1699fab2022-09-08 08:46:06 -060055 def testSplitCfgField(self):
56 """Verify splitting behavior behaves"""
57 testdata = (
58 ("", []),
59 ("a b c", ["a", "b", "c"]),
60 ("a, b", ["a", "b"]),
61 ("a,b", ["a", "b"]),
62 ("a,\tb", ["a", "b"]),
63 ("a\tb", ["a", "b"]),
64 )
65 for val, exp in testdata:
66 ret = pushimage.InputInsns.SplitCfgField(val)
67 self.assertEqual(ret, exp)
Mike Frysingerd13faeb2013-09-05 16:00:46 -040068
Alex Klein1699fab2022-09-08 08:46:06 -060069 def testOutputInsnsBasic(self):
70 """Verify output instructions are correct"""
71 exp_content = """[insns]
Mike Frysingerd13faeb2013-09-05 16:00:46 -040072channel = dev canary
Mike Frysingerd84d91e2015-11-05 18:02:24 -050073keyset = stumpy-mp-v3
Mike Frysingerd13faeb2013-09-05 16:00:46 -040074chromeos_shell = false
75ensure_no_password = true
76firmware_update = true
77security_checks = true
78create_nplusone = true
79
80[general]
81"""
82
Alex Klein1699fab2022-09-08 08:46:06 -060083 insns = pushimage.InputInsns("test.board")
84 self.assertEqual(insns.GetAltInsnSets(), [None])
85 m = self.PatchObject(osutils, "WriteFile")
86 insns.OutputInsns("/bogus", {}, {})
87 self.assertTrue(m.called)
88 content = m.call_args_list[0][0][1]
89 self.assertEqual(content.rstrip(), exp_content.rstrip())
Mike Frysingerd13faeb2013-09-05 16:00:46 -040090
Alex Klein1699fab2022-09-08 08:46:06 -060091 def testOutputInsnsReplacements(self):
92 """Verify output instructions can be updated"""
93 exp_content = """[insns]
Mike Frysingerd13faeb2013-09-05 16:00:46 -040094channel = dev
Mike Frysingerd84d91e2015-11-05 18:02:24 -050095keyset = batman
Mike Frysingerd13faeb2013-09-05 16:00:46 -040096chromeos_shell = false
97ensure_no_password = true
98firmware_update = true
99security_checks = true
100create_nplusone = true
101
102[general]
103board = board
104config_board = test.board
105"""
Alex Klein1699fab2022-09-08 08:46:06 -0600106 sect_insns = {
107 "channel": "dev",
108 "keyset": "batman",
109 }
110 sect_general = collections.OrderedDict(
111 (
112 ("board", "board"),
113 ("config_board", "test.board"),
114 )
115 )
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400116
Alex Klein1699fab2022-09-08 08:46:06 -0600117 insns = pushimage.InputInsns("test.board")
118 m = self.PatchObject(osutils, "WriteFile")
119 insns.OutputInsns("/a/file", sect_insns, sect_general)
120 self.assertTrue(m.called)
121 content = m.call_args_list[0][0][1]
122 self.assertEqual(content.rstrip(), exp_content.rstrip())
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400123
Alex Klein1699fab2022-09-08 08:46:06 -0600124 def testOutputInsnsMergeAlts(self):
125 """Verify handling of alternative insns.xxx sections"""
126 TEMPLATE_CONTENT = """[insns]
Mike Frysinger37ccc2b2015-11-11 17:16:51 -0500127channel = %(channel)s
128chromeos_shell = false
129ensure_no_password = true
130firmware_update = true
131security_checks = true
132create_nplusone = true
133override = sect_insns
134keyset = %(keyset)s
135%(extra)s
136[general]
137board = board
138config_board = test.board
139"""
140
Alex Klein1699fab2022-09-08 08:46:06 -0600141 exp_alts = ["insns.one", "insns.two", "insns.hotsoup"]
142 exp_fields = {
143 "one": {
144 "channel": "dev canary",
145 "keyset": "OneKeyset",
146 "extra": "",
147 },
148 "two": {"channel": "best", "keyset": "TwoKeyset", "extra": ""},
149 "hotsoup": {
150 "channel": "dev canary",
151 "keyset": "ColdKeyset",
152 "extra": "soup = cheddar\n",
153 },
154 }
Mike Frysinger37ccc2b2015-11-11 17:16:51 -0500155
Alex Klein1699fab2022-09-08 08:46:06 -0600156 # Make sure this overrides the insn sections.
157 sect_insns = {
158 "override": "sect_insns",
159 }
160 sect_insns_copy = sect_insns.copy()
161 sect_general = collections.OrderedDict(
162 (
163 ("board", "board"),
164 ("config_board", "test.board"),
165 )
166 )
Mike Frysinger37ccc2b2015-11-11 17:16:51 -0500167
Alex Klein1699fab2022-09-08 08:46:06 -0600168 insns = pushimage.InputInsns("test.multi")
169 self.assertEqual(insns.GetAltInsnSets(), exp_alts)
170 m = self.PatchObject(osutils, "WriteFile")
Mike Frysinger37ccc2b2015-11-11 17:16:51 -0500171
Alex Klein1699fab2022-09-08 08:46:06 -0600172 for alt in exp_alts:
173 m.reset_mock()
174 insns.OutputInsns(
175 "/a/file", sect_insns, sect_general, insns_merge=alt
176 )
177 self.assertEqual(sect_insns, sect_insns_copy)
178 self.assertTrue(m.called)
179 content = m.call_args_list[0][0][1]
180 exp_content = TEMPLATE_CONTENT % exp_fields[alt[6:]]
181 self.assertEqual(content.rstrip(), exp_content.rstrip())
Mike Frysinger37ccc2b2015-11-11 17:16:51 -0500182
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400183
Mike Frysinger4495b032014-03-05 17:24:03 -0500184class MarkImageToBeSignedTest(gs_unittest.AbstractGSContextTest):
Alex Klein1699fab2022-09-08 08:46:06 -0600185 """Tests for MarkImageToBeSigned()"""
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400186
Alex Klein1699fab2022-09-08 08:46:06 -0600187 def setUp(self):
188 # Minor optimization -- we call this for logging purposes in the main
189 # code, but don't really care about it for testing. It just slows us.
190 self.PatchObject(
191 cros_build_lib, "MachineDetails", return_value="1234\n"
192 )
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400193
Alex Klein1699fab2022-09-08 08:46:06 -0600194 def testBasic(self):
195 """Simple smoke test"""
196 tbs_base = "gs://some-bucket"
197 insns_path = "chan/board/ver/file.instructions"
198 tbs_file = (
199 "%s/tobesigned/90,chan,board,ver,file.instructions" % tbs_base
200 )
201 ret = pushimage.MarkImageToBeSigned(self.ctx, tbs_base, insns_path, 90)
202 self.assertEqual(ret, tbs_file)
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400203
Alex Klein1699fab2022-09-08 08:46:06 -0600204 def testPriority(self):
205 """Verify diff priority values get used correctly"""
206 for prio, sprio in ((0, "00"), (9, "09"), (35, "35"), (99, "99")):
207 ret = pushimage.MarkImageToBeSigned(self.ctx, "", "", prio)
208 self.assertEqual(ret, "/tobesigned/%s," % sprio)
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400209
Alex Klein1699fab2022-09-08 08:46:06 -0600210 def testBadPriority(self):
211 """Verify we reject bad priority values"""
212 for prio in (-10, -1, 100, 91239):
213 self.assertRaises(
214 ValueError,
215 pushimage.MarkImageToBeSigned,
216 self.ctx,
217 "",
218 "",
219 prio,
220 )
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400221
Alex Klein1699fab2022-09-08 08:46:06 -0600222 def testTbsUpload(self):
223 """Make sure we actually try to upload the file"""
224 pushimage.MarkImageToBeSigned(self.ctx, "", "", 50)
225 self.gs_mock.assertCommandContains(["cp", "--"])
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400226
227
Mike Frysinger4495b032014-03-05 17:24:03 -0500228class PushImageTests(gs_unittest.AbstractGSContextTest):
Alex Klein1699fab2022-09-08 08:46:06 -0600229 """Tests for PushImage()"""
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400230
Alex Klein1699fab2022-09-08 08:46:06 -0600231 def setUp(self):
232 self.mark_mock = self.PatchObject(pushimage, "MarkImageToBeSigned")
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400233
Alex Klein1699fab2022-09-08 08:46:06 -0600234 def testBasic(self):
235 """Simple smoke test"""
236 EXPECTED = {
237 "canary": [
238 (
239 "gs://chromeos-releases/canary-channel/test.board-hi/5126.0.0/"
240 "ChromeOS-recovery-R34-5126.0.0-test.board-hi.instructions"
241 )
242 ],
243 "dev": [
244 (
245 "gs://chromeos-releases/dev-channel/test.board-hi/5126.0.0/"
246 "ChromeOS-recovery-R34-5126.0.0-test.board-hi.instructions"
247 )
248 ],
249 }
250 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
251 urls = pushimage.PushImage(
252 "/src", "test.board", "R34-5126.0.0", profile="hi"
253 )
Don Garrett9459c2f2014-01-22 18:20:24 -0800254
Alex Klein1699fab2022-09-08 08:46:06 -0600255 self.assertEqual(urls, EXPECTED)
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400256
Alex Klein1699fab2022-09-08 08:46:06 -0600257 def testBasic_SignTypesEmptyList(self):
258 """Tests PushImage behavior when |sign_types| is empty instead of None.
Amey Deshpande3c487952015-09-03 12:11:13 -0700259
Alex Klein1699fab2022-09-08 08:46:06 -0600260 As part of the buildbots, PushImage function always receives a tuple for
261 |sign_types| argument. This test checks the behavior for empty tuple.
262 """
263 EXPECTED = {
264 "canary": [
265 (
266 "gs://chromeos-releases/canary-channel/test.board-hi/5126.0.0/"
267 "ChromeOS-recovery-R34-5126.0.0-test.board-hi.instructions"
268 )
269 ],
270 "dev": [
271 (
272 "gs://chromeos-releases/dev-channel/test.board-hi/5126.0.0/"
273 "ChromeOS-recovery-R34-5126.0.0-test.board-hi.instructions"
274 )
275 ],
276 }
277 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
278 urls = pushimage.PushImage(
279 "/src",
280 "test.board",
281 "R34-5126.0.0",
282 profile="hi",
283 sign_types=(),
284 )
Amey Deshpande3c487952015-09-03 12:11:13 -0700285
Alex Klein1699fab2022-09-08 08:46:06 -0600286 self.assertEqual(urls, EXPECTED)
Amey Deshpande3c487952015-09-03 12:11:13 -0700287
Alex Klein1699fab2022-09-08 08:46:06 -0600288 def testBasic_RealBoardName(self):
289 """Runs a simple smoke test using a real board name."""
290 EXPECTED = {
291 "canary": [
292 (
293 "gs://chromeos-releases/canary-channel/x86-alex/5126.0.0/"
294 "ChromeOS-recovery-R34-5126.0.0-x86-alex.instructions"
295 )
296 ],
297 "dev": [
298 (
299 "gs://chromeos-releases/dev-channel/x86-alex/5126.0.0/"
300 "ChromeOS-recovery-R34-5126.0.0-x86-alex.instructions"
301 )
302 ],
303 }
304 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
305 urls = pushimage.PushImage("/src", "x86-alex", "R34-5126.0.0")
Amey Deshpandea936c622015-08-12 17:27:54 -0700306
Alex Klein1699fab2022-09-08 08:46:06 -0600307 self.assertEqual(urls, EXPECTED)
Amey Deshpandea936c622015-08-12 17:27:54 -0700308
Alex Klein1699fab2022-09-08 08:46:06 -0600309 def testBasicMock(self):
310 """Simple smoke test in mock mode"""
311 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
312 pushimage.PushImage(
313 "/src", "test.board", "R34-5126.0.0", dry_run=True, mock=True
314 )
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400315
Alex Klein1699fab2022-09-08 08:46:06 -0600316 def testBadVersion(self):
317 """Make sure we barf on bad version strings"""
318 self.assertRaises(ValueError, pushimage.PushImage, "", "", "asdf")
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400319
Alex Klein1699fab2022-09-08 08:46:06 -0600320 def testNoInsns(self):
321 """Boards w/out insn files should get skipped"""
322 urls = pushimage.PushImage("/src", "a bad bad board", "R34-5126.0.0")
323 self.assertEqual(self.gs_mock.call_count, 0)
324 self.assertEqual(urls, None)
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400325
Alex Klein1699fab2022-09-08 08:46:06 -0600326 def testSignTypesRecovery(self):
327 """Only sign the requested recovery type"""
328 EXPECTED = {
329 "canary": [
330 (
331 "gs://chromeos-releases/canary-channel/test.board/5126.0.0/"
332 "ChromeOS-recovery-R34-5126.0.0-test.board.instructions"
333 )
334 ],
335 "dev": [
336 (
337 "gs://chromeos-releases/dev-channel/test.board/5126.0.0/"
338 "ChromeOS-recovery-R34-5126.0.0-test.board.instructions"
339 )
340 ],
341 }
Don Garrett9459c2f2014-01-22 18:20:24 -0800342
Alex Klein1699fab2022-09-08 08:46:06 -0600343 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
344 urls = pushimage.PushImage(
345 "/src", "test.board", "R34-5126.0.0", sign_types=["recovery"]
346 )
347 self.assertEqual(self.gs_mock.call_count, 34)
348 self.assertTrue(self.mark_mock.called)
349 self.assertEqual(urls, EXPECTED)
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400350
Alex Klein1699fab2022-09-08 08:46:06 -0600351 def testSignTypesBase(self):
352 """Only sign the requested recovery type"""
353 EXPECTED = {
354 "canary": [
355 (
356 "gs://chromeos-releases/canary-channel/test.board/5126.0.0/"
357 "ChromeOS-base-R34-5126.0.0-test.board.instructions"
358 )
359 ],
360 "dev": [
361 (
362 "gs://chromeos-releases/dev-channel/test.board/5126.0.0/"
363 "ChromeOS-base-R34-5126.0.0-test.board.instructions"
364 )
365 ],
366 }
Amey Deshpandea936c622015-08-12 17:27:54 -0700367
Alex Klein1699fab2022-09-08 08:46:06 -0600368 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
369 urls = pushimage.PushImage(
370 "/src", "test.board", "R34-5126.0.0", sign_types=["base"]
371 )
372 self.assertEqual(self.gs_mock.call_count, 36)
373 self.assertTrue(self.mark_mock.called)
374 self.assertEqual(urls, EXPECTED)
LaMont Jones7d6c98f2019-09-27 12:37:33 -0600375
Alex Klein1699fab2022-09-08 08:46:06 -0600376 def testSignTypesGscFirmware(self):
377 """Only sign the requested type"""
378 EXPECTED = {
379 "canary": [
380 (
381 "gs://chromeos-releases/canary-channel/board2/5126.0.0/"
382 "ChromeOS-gsc_firmware-R34-5126.0.0-board2.instructions"
383 )
384 ],
385 "dev": [
386 (
387 "gs://chromeos-releases/dev-channel/board2/5126.0.0/"
388 "ChromeOS-gsc_firmware-R34-5126.0.0-board2.instructions"
389 )
390 ],
391 }
LaMont Jones7d6c98f2019-09-27 12:37:33 -0600392
Alex Klein1699fab2022-09-08 08:46:06 -0600393 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
394 urls = pushimage.PushImage(
395 "/src", "board2", "R34-5126.0.0", sign_types=["gsc_firmware"]
396 )
397 self.assertEqual(self.gs_mock.call_count, 34)
398 self.assertTrue(self.mark_mock.called)
399 self.assertEqual(urls, EXPECTED)
Amey Deshpandea936c622015-08-12 17:27:54 -0700400
Alex Klein1699fab2022-09-08 08:46:06 -0600401 def testSignTypesNone(self):
402 """Verify nothing is signed when we request an unavailable type"""
403 urls = pushimage.PushImage(
404 "/src", "test.board", "R34-5126.0.0", sign_types=["nononononono"]
405 )
406 self.assertEqual(self.gs_mock.call_count, 32)
407 self.assertFalse(self.mark_mock.called)
408 self.assertEqual(urls, {})
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400409
Alex Klein1699fab2022-09-08 08:46:06 -0600410 def testGsError(self):
411 """Verify random GS errors don't make us blow up entirely"""
412 self.gs_mock.AddCmdResult(
413 partial_mock.In("stat"), returncode=1, stdout="gobblety gook\n"
414 )
415 with cros_test_lib.LoggingCapturer("chromite"):
416 self.assertRaises(
417 pushimage.PushError,
418 pushimage.PushImage,
419 "/src",
420 "test.board",
421 "R34-5126.0.0",
422 )
Mike Frysinger4495b032014-03-05 17:24:03 -0500423
Alex Klein1699fab2022-09-08 08:46:06 -0600424 def testMultipleKeysets(self):
425 """Verify behavior when processing an insn w/multiple keysets"""
426 EXPECTED = {
427 "canary": [
428 (
429 "gs://chromeos-releases/canary-channel/test.board/5126.0.0/"
430 "ChromeOS-recovery-R34-5126.0.0-test.board.instructions"
431 ),
432 (
433 "gs://chromeos-releases/canary-channel/test.board/5126.0.0/"
434 "ChromeOS-recovery-R34-5126.0.0-test.board-key2.instructions"
435 ),
436 (
437 "gs://chromeos-releases/canary-channel/test.board/5126.0.0/"
438 "ChromeOS-recovery-R34-5126.0.0-test.board-key3.instructions"
439 ),
440 ],
441 "dev": [
442 (
443 "gs://chromeos-releases/dev-channel/test.board/5126.0.0/"
444 "ChromeOS-recovery-R34-5126.0.0-test.board.instructions"
445 ),
446 (
447 "gs://chromeos-releases/dev-channel/test.board/5126.0.0/"
448 "ChromeOS-recovery-R34-5126.0.0-test.board-key2.instructions"
449 ),
450 (
451 "gs://chromeos-releases/dev-channel/test.board/5126.0.0/"
452 "ChromeOS-recovery-R34-5126.0.0-test.board-key3.instructions"
453 ),
454 ],
455 }
456 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
457 urls = pushimage.PushImage(
458 "/src",
459 "test.board",
460 "R34-5126.0.0",
461 force_keysets=("key1", "key2", "key3"),
462 )
463 self.assertEqual(urls, EXPECTED)
Mike Frysingerd84d91e2015-11-05 18:02:24 -0500464
Alex Klein1699fab2022-09-08 08:46:06 -0600465 def testForceChannel(self):
466 """Verify behavior when user has specified custom channel"""
467 EXPECTED = {
468 "meep": [
469 (
470 "gs://chromeos-releases/meep-channel/test.board/5126.0.0/"
471 "ChromeOS-recovery-R34-5126.0.0-test.board.instructions"
472 ),
473 ],
474 }
475 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
476 urls = pushimage.PushImage(
477 "/src", "test.board", "R34-5126.0.0", force_channels=("meep",)
478 )
479 self.assertEqual(urls, EXPECTED)
Mike Frysinger77912102017-08-30 18:35:46 -0400480
Alex Klein1699fab2022-09-08 08:46:06 -0600481 def testMultipleAltInsns(self):
482 """Verify behavior when processing an insn w/multiple insn overlays"""
483 EXPECTED = {
484 "canary": [
485 (
486 "gs://chromeos-releases/canary-channel/test.multi/1.0.0/"
487 "ChromeOS-recovery-R1-1.0.0-test.multi.instructions"
488 ),
489 (
490 "gs://chromeos-releases/canary-channel/test.multi/1.0.0/"
491 "ChromeOS-recovery-R1-1.0.0-test.multi-TwoKeyset.instructions"
492 ),
493 (
494 "gs://chromeos-releases/canary-channel/test.multi/1.0.0/"
495 "ChromeOS-recovery-R1-1.0.0-test.multi-ColdKeyset.instructions"
496 ),
497 ],
498 "dev": [
499 (
500 "gs://chromeos-releases/dev-channel/test.multi/1.0.0/"
501 "ChromeOS-recovery-R1-1.0.0-test.multi.instructions"
502 ),
503 (
504 "gs://chromeos-releases/dev-channel/test.multi/1.0.0/"
505 "ChromeOS-recovery-R1-1.0.0-test.multi-TwoKeyset.instructions"
506 ),
507 (
508 "gs://chromeos-releases/dev-channel/test.multi/1.0.0/"
509 "ChromeOS-recovery-R1-1.0.0-test.multi-ColdKeyset.instructions"
510 ),
511 ],
512 }
513 with mock.patch.object(gs.GSContext, "Exists", return_value=True):
514 urls = pushimage.PushImage("/src", "test.multi", "R1-1.0.0")
515 self.assertEqual(urls, EXPECTED)
Mike Frysinger37ccc2b2015-11-11 17:16:51 -0500516
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400517
518class MainTests(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600519 """Tests for main()"""
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400520
Alex Klein1699fab2022-09-08 08:46:06 -0600521 def setUp(self):
522 self.PatchObject(pushimage, "PushImage")
Mike Frysingerd13faeb2013-09-05 16:00:46 -0400523
Alex Klein1699fab2022-09-08 08:46:06 -0600524 def testBasic(self):
525 """Simple smoke test"""
526 pushimage.main(["--board", "test.board", "/src", "--yes"])