Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / chromite / lib / commandline_unittest.py
1 #!/usr/bin/python
2 # Copyright (c) 2012 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 """Test the commandline module."""
7
8 import cPickle
9 import signal
10 import os
11 import sys
12 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(
13     os.path.abspath(__file__)))))
14
15 from chromite.lib import commandline
16 from chromite.lib import cros_build_lib_unittest
17 from chromite.lib import cros_test_lib
18 from chromite.lib import gs
19 from chromite.lib import partial_mock
20
21 from chromite.cbuildbot import constants
22
23 # pylint: disable=W0212
24 class TestShutDownException(cros_test_lib.TestCase):
25   """Test that ShutDownException can be pickled."""
26
27   def testShutDownException(self):
28     """Test that ShutDownException can be pickled."""
29     ex = commandline._ShutDownException(signal.SIGTERM, 'Received SIGTERM')
30     ex2 = cPickle.loads(cPickle.dumps(ex))
31     self.assertEqual(ex.signal, ex2.signal)
32     self.assertEqual(ex.message, ex2.message)
33
34
35 class GSPathTest(cros_test_lib.TestCase):
36   """Test type=gs_path normalization functionality."""
37
38   GS_REL_PATH = 'bucket/path/to/artifacts'
39
40   @staticmethod
41   def _ParseCommandLine(argv):
42     parser = commandline.OptionParser()
43     parser.add_option('-g', '--gs-path', type='gs_path',
44                       help=('GS path that contains the chrome to deploy.'))
45     return parser.parse_args(argv)
46
47   def _RunGSPathTestCase(self, raw, parsed):
48     options, _ =  self._ParseCommandLine(['--gs-path', raw])
49     self.assertEquals(options.gs_path, parsed)
50
51   def testNoGSPathCorrectionNeeded(self):
52     """Test case where GS path correction is not needed."""
53     gs_path = '%s/%s' % (gs.BASE_GS_URL, self.GS_REL_PATH)
54     self._RunGSPathTestCase(gs_path, gs_path)
55
56   def testTrailingSlashRemoval(self):
57     """Test case where GS path ends with /."""
58     gs_path = '%s/%s/' % (gs.BASE_GS_URL, self.GS_REL_PATH)
59     self._RunGSPathTestCase(gs_path, gs_path.rstrip('/'))
60
61   def testDuplicateSlashesRemoved(self):
62     """Test case where GS path contains many / in a row."""
63     self._RunGSPathTestCase(
64         '%s/a/dir/with//////////slashes' % gs.BASE_GS_URL,
65         '%s/a/dir/with/slashes' % gs.BASE_GS_URL)
66
67   def testRelativePathsRemoved(self):
68     """Test case where GS path contain /../ logic."""
69     self._RunGSPathTestCase(
70         '%s/a/dir/up/here/.././../now/down/there' % gs.BASE_GS_URL,
71         '%s/a/dir/now/down/there' % gs.BASE_GS_URL)
72
73   def testCorrectionNeeded(self):
74     """Test case where GS path correction is needed."""
75     self._RunGSPathTestCase(
76         '%s/%s/' % (gs.PRIVATE_BASE_HTTPS_URL, self.GS_REL_PATH),
77         '%s/%s' % (gs.BASE_GS_URL, self.GS_REL_PATH))
78
79   def testInvalidPath(self):
80     """Path cannot be normalized."""
81     with cros_test_lib.OutputCapturer():
82       self.assertRaises2(
83           SystemExit, self._RunGSPathTestCase, 'http://badhost.com/path', '',
84           check_attrs={'code': 2})
85
86
87 class DetermineCheckoutTest(cros_test_lib.MockTempDirTestCase):
88   """Verify functionality for figuring out what checkout we're in."""
89
90   def setUp(self):
91     self.rc_mock = cros_build_lib_unittest.RunCommandMock()
92     self.StartPatcher(self.rc_mock)
93     self.rc_mock.SetDefaultCmdResult()
94
95   def RunTest(self, dir_struct, cwd, expected_root, expected_type,
96               expected_src):
97     """Run a test with specific parameters and expected results."""
98     cros_test_lib.CreateOnDiskHierarchy(self.tempdir, dir_struct)
99     cwd = os.path.join(self.tempdir, cwd)
100     checkout_info = commandline.DetermineCheckout(cwd)
101     full_root = expected_root
102     if expected_root is not None:
103       full_root = os.path.join(self.tempdir, expected_root)
104     full_src = expected_src
105     if expected_src is not None:
106       full_src = os.path.join(self.tempdir, expected_src)
107
108     self.assertEquals(checkout_info.root, full_root)
109     self.assertEquals(checkout_info.type, expected_type)
110     self.assertEquals(checkout_info.chrome_src_dir, full_src)
111
112   def testGclientRepo(self):
113     dir_struct = [
114         'a/.gclient',
115         'a/b/.repo/',
116         'a/b/c/.gclient',
117         'a/b/c/d/somefile',
118     ]
119     self.RunTest(dir_struct, 'a/b/c', 'a/b/c',
120                  commandline.CHECKOUT_TYPE_GCLIENT,
121                  'a/b/c/src')
122     self.RunTest(dir_struct, 'a/b/c/d', 'a/b/c',
123                  commandline.CHECKOUT_TYPE_GCLIENT,
124                  'a/b/c/src')
125     self.RunTest(dir_struct, 'a/b', 'a/b',
126                  commandline.CHECKOUT_TYPE_REPO,
127                  None)
128     self.RunTest(dir_struct, 'a', 'a',
129                  commandline.CHECKOUT_TYPE_GCLIENT,
130                  'a/src')
131
132   def testGitSubmodule(self):
133     """Recognizes a chrome git submodule checkout."""
134     self.rc_mock.AddCmdResult(
135         partial_mock.In('config'), output=constants.CHROMIUM_GOB_URL)
136     dir_struct = [
137         'a/.gclient',
138         'a/.repo',
139         'a/b/.git/',
140     ]
141     self.RunTest(dir_struct, 'a/b', 'a/b',
142                  commandline.CHECKOUT_TYPE_SUBMODULE,
143                  'a/b')
144
145   def testBadGit1(self):
146     """.git is not a directory."""
147     self.RunTest(['a/.git'], 'a', None,
148                  commandline.CHECKOUT_TYPE_UNKNOWN, None)
149
150   def testBadGit2(self):
151     """'git config' returns nothing."""
152     self.RunTest(['a/.repo/', 'a/b/.git/'], 'a/b', 'a',
153                  commandline.CHECKOUT_TYPE_REPO, None)
154
155   def testBadGit3(self):
156     """'git config' returns error."""
157     self.rc_mock.AddCmdResult(partial_mock.In('config'), returncode=5)
158     self.RunTest(['a/.git/'], 'a', None,
159                  commandline.CHECKOUT_TYPE_UNKNOWN, None)
160
161
162 class CacheTest(cros_test_lib.MockTempDirTestCase):
163   """Test cache dir specification and finding functionality."""
164
165   REPO_ROOT = '/fake/repo/root'
166   GCLIENT_ROOT = '/fake/gclient/root'
167   SUBMODULE_ROOT = '/fake/submodule/root'
168   CACHE_DIR = '/fake/cache/dir'
169
170   def setUp(self):
171     self.PatchObject(commandline.ArgumentParser, 'ConfigureCacheDir')
172     dir_struct = [
173       'repo/.repo/',
174       'gclient/.gclient',
175       'submodule/.git/',
176     ]
177     cros_test_lib.CreateOnDiskHierarchy(self.tempdir, dir_struct)
178     self.repo_root = os.path.join(self.tempdir, 'repo')
179     self.gclient_root = os.path.join(self.tempdir, 'gclient')
180     self.submodule_root = os.path.join(self.tempdir, 'submodule')
181     self.nocheckout_root = os.path.join(self.tempdir, 'nothing')
182
183     self.rc_mock = self.StartPatcher(cros_build_lib_unittest.RunCommandMock())
184     self.rc_mock.AddCmdResult(
185         partial_mock.In('config'), output=constants.CHROMIUM_GOB_URL)
186     self.cwd_mock = self.PatchObject(os, 'getcwd')
187     self.parser = commandline.ArgumentParser(caching=True)
188
189   def _CheckCall(self, expected):
190     # pylint: disable=E1101
191     f = self.parser.ConfigureCacheDir
192     self.assertEquals(1, f.call_count)
193     self.assertTrue(f.call_args[0][0].startswith(expected))
194
195   def testRepoRoot(self):
196     """Test when we are inside a repo checkout."""
197     self.cwd_mock.return_value = self.repo_root
198     self.parser.parse_args([])
199     self._CheckCall(self.repo_root)
200
201   def testGclientRoot(self):
202     """Test when we are inside a gclient checkout."""
203     self.cwd_mock.return_value = self.gclient_root
204     self.parser.parse_args([])
205     self._CheckCall(self.gclient_root)
206
207   def testSubmoduleRoot(self):
208     """Test when we are inside a git submodule Chrome checkout."""
209     self.cwd_mock.return_value = self.submodule_root
210     self.parser.parse_args([])
211     self._CheckCall(self.submodule_root)
212
213   def testTempdir(self):
214     """Test when we are not in any checkout."""
215     self.cwd_mock.return_value = self.nocheckout_root
216     self.parser.parse_args([])
217     self._CheckCall('/tmp')
218
219   def testSpecifiedDir(self):
220     """Test when user specifies a cache dir."""
221     self.cwd_mock.return_value = self.repo_root
222     self.parser.parse_args(['--cache-dir', self.CACHE_DIR])
223     self._CheckCall(self.CACHE_DIR)
224
225
226 class ParseArgsTest(cros_test_lib.TestCase):
227   """Test parse_args behavior of our custom argument parsing classes."""
228
229   def _CreateOptionParser(self, cls):
230     """Create a class of optparse.OptionParser with prepared config.
231
232     Args:
233       cls: Some subclass of optparse.OptionParser.
234
235     Returns:
236       The created OptionParser object.
237     """
238     usage = 'usage: some usage'
239     parser = cls(usage=usage)
240
241     # Add some options.
242     parser.add_option('-x', '--xxx', action='store_true', default=False,
243                       help='Gimme an X')
244     parser.add_option('-y', '--yyy', action='store_true', default=False,
245                       help='Gimme a Y')
246     parser.add_option('-a', '--aaa', type='string', default='Allan',
247                       help='Gimme an A')
248     parser.add_option('-b', '--bbb', type='string', default='Barry',
249                       help='Gimme a B')
250     parser.add_option('-c', '--ccc', type='string', default='Connor',
251                       help='Gimme a C')
252
253     return parser
254
255   def _CreateArgumentParser(self, cls):
256     """Create a class of argparse.ArgumentParser with prepared config.
257
258     Args:
259       cls: Some subclass of argparse.ArgumentParser.
260
261     Returns:
262       The created ArgumentParser object.
263     """
264     usage = 'usage: some usage'
265     parser = cls(usage=usage)
266
267     # Add some options.
268     parser.add_argument('-x', '--xxx', action='store_true', default=False,
269                         help='Gimme an X')
270     parser.add_argument('-y', '--yyy', action='store_true', default=False,
271                         help='Gimme a Y')
272     parser.add_argument('-a', '--aaa', type=str, default='Allan',
273                         help='Gimme an A')
274     parser.add_argument('-b', '--bbb', type=str, default='Barry',
275                         help='Gimme a B')
276     parser.add_argument('-c', '--ccc', type=str, default='Connor',
277                         help='Gimme a C')
278     parser.add_argument('args', type=str, nargs='*', help='args')
279
280     return parser
281
282   def _TestParser(self, parser):
283     """Test the given parser with a prepared argv."""
284     argv = ['-x', '--bbb', 'Bobby', '-c', 'Connor', 'foobar']
285
286     parsed = parser.parse_args(argv)
287
288     if isinstance(parser, commandline.OptionParser):
289       # optparse returns options and args separately.
290       options, args = parsed
291       self.assertEquals(['foobar'], args)
292     else:
293       # argparse returns just options.  Options configured above to have the
294       # args stored at option "args".
295       options = parsed
296       self.assertEquals(['foobar'], parsed.args)
297
298     self.assertTrue(options.xxx)
299     self.assertFalse(options.yyy)
300
301     self.assertEquals('Allan', options.aaa)
302     self.assertEquals('Bobby', options.bbb)
303     self.assertEquals('Connor', options.ccc)
304
305     self.assertRaises(AttributeError, getattr, options, 'xyz')
306
307     # Now try altering option values.
308     options.aaa = 'Arick'
309     self.assertEquals('Arick', options.aaa)
310
311     # Now freeze the options and try altering again.
312     options.Freeze()
313     self.assertRaises(commandline.cros_build_lib.AttributeFrozenError,
314                       setattr, options, 'aaa', 'Arnold')
315     self.assertEquals('Arick', options.aaa)
316
317   def testOptionParser(self):
318     self._TestParser(self._CreateOptionParser(commandline.OptionParser))
319
320   def testFilterParser(self):
321     self._TestParser(self._CreateOptionParser(commandline.FilteringParser))
322
323   def testArgumentParser(self):
324     self._TestParser(self._CreateArgumentParser(commandline.ArgumentParser))
325
326
327 class ScriptWrapperMainTest(cros_test_lib.MockTestCase):
328   """Test the behavior of the ScriptWrapperMain function."""
329
330   def setUp(self):
331     self.PatchObject(sys, 'exit')
332
333   # pylint: disable=W0613
334   @staticmethod
335   def _DummyChrootTarget(args):
336     raise commandline.ChrootRequiredError()
337
338   DUMMY_CHROOT_TARGET_ARGS = ['cmd', 'arg1', 'arg2']
339
340   @staticmethod
341   def _DummyChrootTargetArgs(args):
342     args = ScriptWrapperMainTest.DUMMY_CHROOT_TARGET_ARGS
343     raise commandline.ChrootRequiredError(args)
344
345   def testRestartInChroot(self):
346     rc = self.StartPatcher(cros_build_lib_unittest.RunCommandMock())
347     rc.SetDefaultCmdResult()
348
349     ret = lambda x: ScriptWrapperMainTest._DummyChrootTarget
350     commandline.ScriptWrapperMain(ret)
351     rc.assertCommandContains(enter_chroot=True)
352     rc.assertCommandContains(self.DUMMY_CHROOT_TARGET_ARGS, expected=False)
353
354   def testRestartInChrootArgs(self):
355     rc = self.StartPatcher(cros_build_lib_unittest.RunCommandMock())
356     rc.SetDefaultCmdResult()
357
358     ret = lambda x: ScriptWrapperMainTest._DummyChrootTargetArgs
359     commandline.ScriptWrapperMain(ret)
360     rc.assertCommandContains(self.DUMMY_CHROOT_TARGET_ARGS, enter_chroot=True)
361
362
363 if __name__ == '__main__':
364   cros_test_lib.main()