blob: 7863e0ab22f54ddf3ee27defb39119bff1b53dfa [file] [log] [blame]
Doug Andersonf0c73952011-01-18 13:46:07 -08001#!/usr/bin/python
2#
Doug Andersone91900d2011-01-26 11:37:17 -08003# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Doug Andersonf0c73952011-01-18 13:46:07 -08004# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
Doug Andersone91900d2011-01-26 11:37:17 -08007"""Unit tests for main.py."""
Doug Andersonf0c73952011-01-18 13:46:07 -08008
9import doctest
10import os
11import re
12import unittest
13
Doug Andersona9b10902011-02-01 17:54:31 -080014import chromite.lib.cros_build_lib as cros_lib
Doug Andersone91900d2011-01-26 11:37:17 -080015from chromite.lib import text_menu
16from chromite.shell import main
Doug Andersona9b10902011-02-01 17:54:31 -080017from chromite.shell import utils
Doug Andersonf0c73952011-01-18 13:46:07 -080018import mox
19
20
21class _DeathException(Exception):
Doug Andersona9b10902011-02-01 17:54:31 -080022 """A bogus exception used by the mock out of cros_lib.Die."""
Doug Andersonf0c73952011-01-18 13:46:07 -080023 pass
24
25
26class TestFindCommand(unittest.TestCase):
Doug Andersone91900d2011-01-26 11:37:17 -080027 """Test main._FindCommand."""
28 # TODO(dianders): Add a test where I override main._COMMAND_HANDLERS
29 # and main._COMMAND_STRS so that I can test more of _FindCommand().
Doug Andersonf0c73952011-01-18 13:46:07 -080030
31 def setUp(self):
32 """Test initialization."""
33 # Create our mox and stub out function calls used by _FindCommand()...
34 self.mox = mox.Mox()
Doug Andersona9b10902011-02-01 17:54:31 -080035 self.mox.StubOutWithMock(cros_lib, 'Die')
36 self.mox.StubOutWithMock(cros_lib, 'Info')
Doug Andersonf0c73952011-01-18 13:46:07 -080037 self.mox.StubOutWithMock(text_menu, 'TextMenu')
38
39 def tearDown(self):
40 """Test cleanup."""
41 # Unset stubs...
42 self.mox.UnsetStubs()
43
44 def testInvalidCommand(self):
Doug Andersona9b10902011-02-01 17:54:31 -080045 """Test that _FindCommand('implode') causes cros_lib.Die()."""
46 # Should be a call to cros_lib.Die. We'll have it fake a _DeathException...
47 cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)
Doug Andersonf0c73952011-01-18 13:46:07 -080048
49 # Run the command and verify proper mocks were called...
50 self.mox.ReplayAll()
Doug Andersone91900d2011-01-26 11:37:17 -080051 self.assertRaises(_DeathException, main._FindCommand, 'implode')
Doug Andersonf0c73952011-01-18 13:46:07 -080052 self.mox.VerifyAll()
53
54 def testBlankCommandWithQuit(self):
55 """Test that _FindCommand('') shows menu, mocking quit.
56
57 This tests the case that the user quit out of the menu without choosing
58 anything.
59 """
60 # Should be one call to TextMenu, which will return None for quit.
61 text_menu.TextMenu(mox.IsA(list),
62 mox.IsA(basestring),
63 menu_width=0).AndReturn(None)
64
65 # Should die in response to the quit.
Doug Andersona9b10902011-02-01 17:54:31 -080066 cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)
Doug Andersonf0c73952011-01-18 13:46:07 -080067
68 # Run the command and verify proper mocks were called...
69 self.mox.ReplayAll()
Doug Andersone91900d2011-01-26 11:37:17 -080070 self.assertRaises(_DeathException, main._FindCommand, '')
Doug Andersonf0c73952011-01-18 13:46:07 -080071 self.mox.VerifyAll()
72
73 def testBlankCommandWithChoice0(self):
74 """Test that _FindCommand('') shows menu, mocking choice 0.
75
76 This tests the case that the user chose choice 0 for the menu.
77 """
78 # Should be one call to TextMenu, which will return item 0.
79 text_menu.TextMenu(mox.IsA(list),
80 mox.IsA(basestring),
81 menu_width=0).AndReturn(0)
82
83 # Run the command and verify proper mocks were called...
84 self.mox.ReplayAll()
Doug Andersone91900d2011-01-26 11:37:17 -080085 cmd_str = main._FindCommand('')
Doug Andersonf0c73952011-01-18 13:46:07 -080086 self.mox.VerifyAll()
87
88 self.assertTrue(isinstance(cmd_str, basestring),
89 '_FindCommand should return a string')
90 self.assertTrue(bool(cmd_str),
91 '_FindCommand should not return a blank string')
92
93 def _TestExactCommand(self, cmd_to_find):
94 """Helper for tests that try to find an exact match.
95
96 Args:
97 cmd_to_find: The name of the command to find, like 'Build', ...
98 """
99 # Expect no mocks to be called...
100
101 # Run the command and verify proper mocks were called...
102 self.mox.ReplayAll()
Doug Andersone91900d2011-01-26 11:37:17 -0800103 cmd_str = main._FindCommand(cmd_to_find)
Doug Andersonf0c73952011-01-18 13:46:07 -0800104 self.mox.VerifyAll()
105
106 self.assertEqual(cmd_str, cmd_to_find.lower(),
107 '_FindCommand("%s") should return "%s" back.' %
108 (cmd_to_find, cmd_to_find.lower()))
109
110 def testCaseSensitiveBuild(self):
111 """Test that _FindCommand('build') returns 'build'.
112
113 The command matching should be case sensitive.
114 """
115 self._TestExactCommand('build')
116
117 def testCaseInsensitiveBuild(self):
118 """Test that _FindCommand('BUiLD') returns 'build'.
119
120 The command matching should be case insensitive.
121 """
122 self._TestExactCommand('BUiLD')
123
124 def testShCommand(self):
125 """Test that _FindCommand('sh') returns 'shell'.
126
127 This serves two purposes:
128 1. Test the 'prefix' feature of _FindCommand
129 2. Validate that nobody has introduced another command that starts with
130 'sh', since it's expected that many people will use this to invoke the
131 shell.
132 """
133 # _FindCommand should give us a message that it has interpreted sh as shell.
Doug Andersona9b10902011-02-01 17:54:31 -0800134 cros_lib.Info(mox.IsA(basestring))
Doug Andersonf0c73952011-01-18 13:46:07 -0800135
136 # Run the command and verify proper mocks were called...
137 self.mox.ReplayAll()
Doug Andersone91900d2011-01-26 11:37:17 -0800138 cmd_str = main._FindCommand('sh')
Doug Andersonf0c73952011-01-18 13:46:07 -0800139 self.mox.VerifyAll()
140
141 self.assertEqual(cmd_str, 'shell',
142 '_FindCommand("sh") should return "shell" back.')
143
144
145class TestFindSpec(unittest.TestCase):
Doug Andersona9b10902011-02-01 17:54:31 -0800146 """Test utils.FindSpec."""
Doug Andersonf0c73952011-01-18 13:46:07 -0800147
148 def setUp(self):
149 """Test initialization."""
150 # Create our mox and stub out function calls used by _FindSpec()...
151 self.mox = mox.Mox()
152 self.mox.StubOutWithMock(os, 'listdir')
153 self.mox.StubOutWithMock(os.path, 'isfile')
Doug Andersona9b10902011-02-01 17:54:31 -0800154 self.mox.StubOutWithMock(cros_lib, 'Die')
155 self.mox.StubOutWithMock(cros_lib, 'Info')
Doug Andersonf0c73952011-01-18 13:46:07 -0800156 self.mox.StubOutWithMock(text_menu, 'TextMenu')
157
158 def tearDown(self):
159 """Test cleanup."""
160 # Unset stubs...
161 self.mox.UnsetStubs()
162
163 def testInvalidSpec(self):
Doug Andersona9b10902011-02-01 17:54:31 -0800164 """Test that _FindSpec('bogusSpec') causes cros_lib.Die()."""
Doug Andersonf0c73952011-01-18 13:46:07 -0800165 # Pass this spec name...
166 spec_name = 'bogusSpec'
167
168 # We'll tell mox to say that these specs exist...
169 dir_list = ['x87-toadstool.spec', 'x87-luigi.SPeC', 'x88-princess.spec',
170 '_default']
171
172 # This spec doesn't represent any full path.
173 os.path.isfile(spec_name).AndReturn(False)
174
175 # This spec isn't found in our search path.
176 os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).MultipleTimes(
177 ).AndReturn(False)
178
179 # Give the fake directory listing...
180 os.listdir(mox.IsA(basestring)).MultipleTimes().AndReturn(dir_list)
181
Doug Andersona9b10902011-02-01 17:54:31 -0800182 # Should be a call to cros_lib.Die. We'll have it fake a _DeathException...
183 cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)
Doug Andersonf0c73952011-01-18 13:46:07 -0800184
185 # Run the command and verify proper mocks were called...
186 self.mox.ReplayAll()
Doug Andersona9b10902011-02-01 17:54:31 -0800187 self.assertRaises(_DeathException, utils.FindSpec, 'bogusSpec')
Doug Andersonf0c73952011-01-18 13:46:07 -0800188 self.mox.VerifyAll()
189
190 def testFullPath(self):
191 """Test that _FindSpec(full_path) returns full_path.
192
193 _FindSpec is defined so that if you pass a full file path to it, it
194 should just return that. It doesn't need to have any special suffix or
195 live in a spec folder.
196 """
197 # Pass this spec name...
198 spec_name = __file__
199
200 # Just say that this is a full path...
201 os.path.isfile(spec_name).AndReturn(True)
202
203 # Run the command and verify proper mocks were called...
204 self.mox.ReplayAll()
Doug Andersona9b10902011-02-01 17:54:31 -0800205 path = utils.FindSpec(spec_name)
Doug Andersonf0c73952011-01-18 13:46:07 -0800206 self.mox.VerifyAll()
207
208 self.assertEqual(path, spec_name,
209 '_FindSpec() should just return param if full path.')
210
211 def testExactSpecName(self):
212 """Test that _FindSpec(exact_spec_name) returns the path for the spec."""
213 # We'll search for this bogus spec; we'll use mox to pretend it exists in
214 # the search path.
215 spec_name = 'y87-luigi'
216
217 # This spec doesn't represent any full path
218 os.path.isfile(spec_name).AndReturn(False)
219
220 # When we look through the search path for this spec (with .spec at
221 # the end), we will consider the spec to be found.
222 os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).AndReturn(True)
223
224 # Run the command and verify proper mocks were called...
225 self.mox.ReplayAll()
Doug Andersona9b10902011-02-01 17:54:31 -0800226 spec_path = utils.FindSpec(spec_name)
Doug Andersonf0c73952011-01-18 13:46:07 -0800227 self.mox.VerifyAll()
228
229 self.assertTrue(re.search('^/.*%s.spec$' % spec_name, spec_path),
230 '_FindSpec() should have returned absolute path for spec.')
231
232 def testUniqueSpecName(self):
233 """Test that _FindSpec(unique_part_name) returns the path for the spec."""
234 # We'll search for this spec. Weird capitalization on purpose to test
235 # case sensitiveness.
236 spec_name = 'ToaDSTooL'
237
238 # We'll tell mox to say that these specs exist in the first directory...
239 dir_list = ['_default',
240 'x87-luigi.spec', 'x87-toadstool.SPeC', 'x88-princess.spec']
241
242 # We expect it to find this spec.
243 expected_result = 'x87-toadstool.SPeC'
244
245 # Self-checks for test code...
246 assert dir_list == sorted(dir_list)
247
248 # This spec doesn't represent any full path.
249 os.path.isfile(spec_name).AndReturn(False)
250
251 # This spec isn't found in our search path.
252 os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).MultipleTimes(
253 ).AndReturn(False)
254
255 # Return our directory listing.
256 # TODO(dianders): How to make first mocked call return dir_list and
257 # subsequent return []
258 os.listdir(mox.IsA(basestring)).AndReturn(dir_list)
259
260 os.path.isfile(mox.Regex('^/.*%s$' % expected_result)).AndReturn(True)
261
262 # Run the command and verify proper mocks were called...
263 self.mox.ReplayAll()
Doug Andersona9b10902011-02-01 17:54:31 -0800264 spec_path = utils.FindSpec(spec_name)
Doug Andersonf0c73952011-01-18 13:46:07 -0800265 self.mox.VerifyAll()
266
267 self.assertTrue(re.search('^/.*%s$' % expected_result, spec_path),
268 '_FindSpec("%s") incorrectly returned "%s".' %
269 (spec_name, spec_path))
270
271 def _TestBlankSpecName(self, menu_return):
272 """Helper for tests passing a blank spec name.
273
274 Args:
275 menu_return: This value is returned by TextMenu. Could be none or an
276 integer index into the dir_list of this function.
277 """
278 # We'll search for this spec.
279 spec_name = ''
280
281 # We'll tell mox to say that these specs exist in the first directory...
282 # ...only valid specs to make it easier to compare things.
283 dir_list = ['x87-luigi.spec', 'x87-toadstool.SPeC', 'x88-princess.spec']
284 num_specs = len(dir_list)
285
286 # Self-checks for test code...
287 assert menu_return < len(dir_list)
288 assert dir_list == sorted(dir_list)
289
290 # This spec doesn't represent any full path.
291 os.path.isfile(spec_name).AndReturn(False)
292
293 # Return our directory listing.
294 # TODO(dianders): How to make first mocked call return dir_list and
295 # subsequent return []
296 os.listdir(mox.IsA(basestring)).AndReturn(dir_list)
297
298 for i in xrange(num_specs):
299 os.path.isfile(mox.Regex('^/.*%s$' % dir_list[i])).AndReturn(True)
300
301 # We expect there to be 1 more item than we passed in, since we account
302 # for 'HOST'.
303 check_num_items_fn = lambda items: len(items) == (num_specs + 1)
304
305 # Add 1 to menu_return, since 'HOST' is first...
306 if menu_return is None:
307 adjusted_menu_return = menu_return
308 else:
309 adjusted_menu_return = menu_return + 1
310
311 # Should be one call to TextMenu, which will return menu_return.
312 text_menu.TextMenu(mox.And(mox.IsA(list), mox.Func(check_num_items_fn)),
313 mox.IsA(basestring)).AndReturn(adjusted_menu_return)
314
315 # Should die in response to the quit if directed to quit.
316 if menu_return is None:
Doug Andersona9b10902011-02-01 17:54:31 -0800317 cros_lib.Die(mox.IsA(basestring)).AndRaise(_DeathException)
Doug Andersonf0c73952011-01-18 13:46:07 -0800318
319 # Run the command and verify proper mocks were called...
320 self.mox.ReplayAll()
321 if menu_return is None:
Doug Andersona9b10902011-02-01 17:54:31 -0800322 self.assertRaises(_DeathException, utils.FindSpec, spec_name)
Doug Andersonf0c73952011-01-18 13:46:07 -0800323 else:
Doug Andersona9b10902011-02-01 17:54:31 -0800324 spec_path = utils.FindSpec(spec_name)
Doug Andersonf0c73952011-01-18 13:46:07 -0800325 self.mox.VerifyAll()
326
327 if menu_return is not None:
328 expected_result = dir_list[menu_return]
329 self.assertTrue(re.search('^/.*%s$' % expected_result, spec_path),
330 '_FindSpec("%s") incorrectly returned "%s".' %
331 (spec_name, spec_path))
332
333 def testBlankSpecNameWithQuit(self):
334 """Test that _FindSpec('') shows menu, mocking quit."""
335 self._TestBlankSpecName(None)
336
337 def testBlankSpecNameWithChoice0(self):
338 """Test that _FindSpec('') shows menu, mocking choice 0."""
339 self._TestBlankSpecName(0)
340
341 def testPartialSpecNameWithChoice0(self):
342 """Test that _FindSpec(non_unique_str) shows menu, mocking choice 0."""
343 # We'll search for this spec.
344 spec_name = 'x87'
345
346 # We'll tell mox to say that these specs exist in the first directory...
347 dir_list = ['_default',
348 'x87-luigi.spec', 'x87-toadstool.SPeC', 'x88-princess.spec']
349
350 # We expect 2 matches and should get back luigi as choice 0.
351 matches = ['x87-luigi.spec', 'x87-toadstool.SPeC']
352 num_match = len(matches)
353 expected_result = 'x87-luigi.spec'
354
355 # Self-checks for test code...
356 assert dir_list == sorted(dir_list)
357
358 # This spec doesn't represent any full path.
359 os.path.isfile(spec_name).AndReturn(False)
360
361 # This spec isn't found in our search path.
362 os.path.isfile(mox.Regex('^/.*%s.spec$' % spec_name)).MultipleTimes(
363 ).AndReturn(False)
364
365 # Return our directory listing.
366 # TODO(dianders): How to make first mocked call return dir_list and
367 # subsequent return []
368 os.listdir(mox.IsA(basestring)).AndReturn(dir_list)
369
370 for i in xrange(num_match):
371 os.path.isfile(mox.Regex('^/.*%s$' % matches[i])).AndReturn(True)
372
373 # Should be one call to TextMenu, which will return 0.
374 text_menu.TextMenu(mox.And(mox.IsA(list),
375 mox.Func(lambda items: len(items) == num_match)),
376 mox.IsA(basestring)).AndReturn(0)
377
378 # Run the command and verify proper mocks were called...
379 self.mox.ReplayAll()
Doug Andersona9b10902011-02-01 17:54:31 -0800380 spec_path = utils.FindSpec(spec_name)
Doug Andersonf0c73952011-01-18 13:46:07 -0800381 self.mox.VerifyAll()
382
383 self.assertTrue(re.search('^/.*%s$' % expected_result, spec_path),
384 '_FindSpec("%s") incorrectly returned "%s".' %
385 (spec_name, spec_path))
386
387
388if __name__ == '__main__':
Doug Andersone91900d2011-01-26 11:37:17 -0800389 doctest.testmod(main)
Doug Andersonf0c73952011-01-18 13:46:07 -0800390 unittest.main()