Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / chromite / scripts / pushimage_unittest.py
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
6 """Unittests for pushimage.py"""
7
8 from __future__ import print_function
9
10 import logging
11 import mock
12 import os
13 import sys
14
15 sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)),
16                                 '..', '..'))
17 from chromite.lib import cros_build_lib
18 from chromite.lib import cros_test_lib
19 from chromite.lib import git
20 from chromite.lib import gs
21 from chromite.lib import gs_unittest
22 from chromite.lib import osutils
23 from chromite.lib import partial_mock
24 from chromite.lib import signing
25 from chromite.scripts import pushimage
26
27
28 class InputInsnsTest(cros_test_lib.MockTestCase):
29   """Tests for InputInsns"""
30
31   def testBasic(self):
32     """Simple smoke test"""
33     with mock.patch.object(gs.GSContext, 'Exists', return_value=False):
34       insns = pushimage.InputInsns('test.board')
35       insns.GetInsnFile('recovery')
36       self.assertEqual(insns.GetChannels(), ['dev', 'canary'])
37       self.assertEqual(insns.GetKeysets(), ['stumpy-mp-v3'])
38
39   def testGetInsnFile(self):
40     """Verify various inputs result in right insns path"""
41     testdata = (
42         ('UPPER_CAPS', 'UPPER_CAPS'),
43         ('recovery', 'test.board'),
44         ('firmware', 'test.board.firmware'),
45         ('factory', 'test.board.factory'),
46     )
47     insns = pushimage.InputInsns('test.board')
48     for image_type, filename in testdata:
49       ret = insns.GetInsnFile(image_type)
50       self.assertEqual(os.path.basename(ret), '%s.instructions' % (filename))
51
52   def testSplitCfgField(self):
53     """Verify splitting behavior behaves"""
54     testdata = (
55         ('', []),
56         ('a b c', ['a', 'b', 'c']),
57         ('a, b', ['a', 'b']),
58         ('a,b', ['a', 'b']),
59         ('a,\tb', ['a', 'b']),
60         ('a\tb', ['a', 'b']),
61     )
62     for val, exp in testdata:
63       ret = pushimage.InputInsns.SplitCfgField(val)
64       self.assertEqual(ret, exp)
65
66   def testOutputInsnsBasic(self):
67     """Verify output instructions are sane"""
68     exp_content = """[insns]
69 keyset = stumpy-mp-v3
70 channel = dev canary
71 chromeos_shell = false
72 ensure_no_password = true
73 firmware_update = true
74 security_checks = true
75 create_nplusone = true
76
77 [general]
78 """
79
80     insns = pushimage.InputInsns('test.board')
81     m = self.PatchObject(osutils, 'WriteFile')
82     insns.OutputInsns('recovery', '/bogus', {}, {})
83     self.assertTrue(m.called)
84     content = m.call_args_list[0][0][1]
85     self.assertEqual(content.rstrip(), exp_content.rstrip())
86
87   def testOutputInsnsReplacements(self):
88     """Verify output instructions can be updated"""
89     exp_content = """[insns]
90 keyset = batman
91 channel = dev
92 chromeos_shell = false
93 ensure_no_password = true
94 firmware_update = true
95 security_checks = true
96 create_nplusone = true
97
98 [general]
99 board = board
100 config_board = test.board
101 """
102     sect_insns = {
103         'channel': 'dev',
104         'keyset': 'batman',
105     }
106     sect_general = {
107         'config_board': 'test.board',
108         'board': 'board',
109     }
110
111     insns = pushimage.InputInsns('test.board')
112     m = self.PatchObject(osutils, 'WriteFile')
113     insns.OutputInsns('recovery', '/a/file', sect_insns, sect_general)
114     self.assertTrue(m.called)
115     content = m.call_args_list[0][0][1]
116     self.assertEqual(content.rstrip(), exp_content.rstrip())
117
118
119 class MarkImageToBeSignedTest(gs_unittest.AbstractGSContextTest):
120   """Tests for MarkImageToBeSigned()"""
121
122   def setUp(self):
123     # Minor optimization -- we call this for logging purposes in the main
124     # code, but don't really care about it for testing.  It just slows us.
125     self.PatchObject(git, 'RunGit',
126                      return_value=cros_build_lib.CommandResult(output='1234\n'))
127
128   def testBasic(self):
129     """Simple smoke test"""
130     tbs_base = 'gs://some-bucket'
131     insns_path = 'chan/board/ver/file.instructions'
132     tbs_file = '%s/tobesigned/90,chan,board,ver,file.instructions' % tbs_base
133     ret = pushimage.MarkImageToBeSigned(self.ctx, tbs_base, insns_path, 90)
134     self.assertEqual(ret, tbs_file)
135
136   def testPriority(self):
137     """Verify diff priority values get used correctly"""
138     for prio, sprio in ((0, '00'), (9, '09'), (35, '35'), (99, '99')):
139       ret = pushimage.MarkImageToBeSigned(self.ctx, '', '', prio)
140       self.assertEquals(ret, '/tobesigned/%s,' % sprio)
141
142   def testBadPriority(self):
143     """Verify we reject bad priority values"""
144     for prio in (-10, -1, 100, 91239):
145       self.assertRaises(ValueError, pushimage.MarkImageToBeSigned, self.ctx,
146                         '', '', prio)
147
148   def testTbsFile(self):
149     """Make sure the tbs file we write has useful data"""
150     WriteFile = osutils.WriteFile
151     def _write_check(*args, **kwargs):
152       # We can't mock every call, so do the actual write for most.
153       WriteFile(*args, **kwargs)
154
155     m = self.PatchObject(osutils, 'WriteFile')
156     m.side_effect = _write_check
157     pushimage.MarkImageToBeSigned(self.ctx, '', '', 50)
158     # We assume the first call is the one we care about.
159     self.assertTrue(m.called)
160     content = m.call_args_list[0][0][1]
161     self.assertIn('USER=', content)
162     self.assertIn('HOSTNAME=', content)
163     self.assertIn('GIT_REV=1234', content)
164     self.assertIn('\n', content)
165
166   def testTbsUpload(self):
167     """Make sure we actually try to upload the file"""
168     pushimage.MarkImageToBeSigned(self.ctx, '', '', 50)
169     self.gs_mock.assertCommandContains(['cp', '--'])
170
171
172 class PushImageTests(gs_unittest.AbstractGSContextTest):
173   """Tests for PushImage()"""
174
175   def setUp(self):
176     self.mark_mock = self.PatchObject(pushimage, 'MarkImageToBeSigned')
177
178   def testBasic(self):
179     """Simple smoke test"""
180     EXPECTED = {
181         'canary': [
182             'gs://chromeos-releases/canary-channel/test.board-hi/5126.0.0/'
183               'ChromeOS-recovery-R34-5126.0.0-test.board-hi.instructions'],
184         'dev': [
185             'gs://chromeos-releases/dev-channel/test.board-hi/5126.0.0/'
186               'ChromeOS-recovery-R34-5126.0.0-test.board-hi.instructions'],
187     }
188     with mock.patch.object(gs.GSContext, 'Exists', return_value=True):
189       urls = pushimage.PushImage('/src', 'test.board', 'R34-5126.0.0',
190                                  profile='hi')
191
192     self.assertEqual(urls, EXPECTED)
193
194   def testBasicMock(self):
195     """Simple smoke test in mock mode"""
196     with mock.patch.object(gs.GSContext, 'Exists', return_value=True):
197       pushimage.PushImage('/src', 'test.board', 'R34-5126.0.0',
198                           dry_run=True, mock=True)
199
200   def testBadVersion(self):
201     """Make sure we barf on bad version strings"""
202     self.assertRaises(ValueError, pushimage.PushImage, '', '', 'asdf')
203
204   def testNoInsns(self):
205     """Boards w/out insn files should get skipped"""
206     urls = pushimage.PushImage('/src', 'a bad bad board', 'R34-5126.0.0')
207     self.assertEqual(self.gs_mock.call_count, 0)
208     self.assertEqual(urls, None)
209
210   def testSignTypesRecovery(self):
211     """Only sign the requested recovery type"""
212     EXPECTED = {
213         'canary': [
214             'gs://chromeos-releases/canary-channel/test.board/5126.0.0/'
215               'ChromeOS-recovery-R34-5126.0.0-test.board.instructions'],
216         'dev': [
217             'gs://chromeos-releases/dev-channel/test.board/5126.0.0/'
218               'ChromeOS-recovery-R34-5126.0.0-test.board.instructions'],
219     }
220
221     urls = pushimage.PushImage('/src', 'test.board', 'R34-5126.0.0',
222                                sign_types=['recovery'])
223     self.assertEqual(self.gs_mock.call_count, 18)
224     self.assertTrue(self.mark_mock.called)
225     self.assertEqual(urls, EXPECTED)
226
227   def testSignTypesNone(self):
228     """Verify nothing is signed when we request an unavailable type"""
229     urls = pushimage.PushImage('/src', 'test.board', 'R34-5126.0.0',
230                                sign_types=['nononononono'])
231     self.assertEqual(self.gs_mock.call_count, 16)
232     self.assertFalse(self.mark_mock.called)
233     self.assertEqual(urls, {})
234
235   def testGsError(self):
236     """Verify random GS errors don't make us blow up entirely"""
237     self.gs_mock.AddCmdResult(partial_mock.In('stat'), returncode=1,
238                               output='gobblety gook\n')
239     with cros_test_lib.LoggingCapturer('chromite'):
240       self.assertRaises(pushimage.PushError, pushimage.PushImage, '/src',
241                         'test.board', 'R34-5126.0.0')
242
243
244 class MainTests(cros_test_lib.MockTestCase):
245   """Tests for main()"""
246
247   def setUp(self):
248     self.PatchObject(pushimage, 'PushImage')
249
250   def testBasic(self):
251     """Simple smoke test"""
252     pushimage.main(['--board', 'test.board', '/src', '--yes'])
253
254
255 if __name__ == '__main__':
256   # Use our local copy of insns for testing as the main one is not
257   # available in the public manifest.
258   signing.INPUT_INSN_DIR = signing.TEST_INPUT_INSN_DIR
259
260   # Run the tests.
261   cros_test_lib.main(level=logging.INFO)