blob: 4c9e1720c7f3a87e3951dc7116eb00f4f8fc1321 [file] [log] [blame]
mblighbe630eb2008-08-01 16:41:48 +00001#
2# Copyright 2008 Google Inc. All Rights Reserved.
3
4"""Test for cli."""
5
Justin Giorgid76ed502016-06-21 10:27:52 -07006import os
7import sys
8import unittest
mblighbe630eb2008-08-01 16:41:48 +00009
10import common
Justin Giorgid76ed502016-06-21 10:27:52 -070011from autotest_lib.cli import atest, rpc
jamesrenf0a44382010-02-12 00:45:29 +000012from autotest_lib.frontend.afe import rpc_client_lib
mblighbe630eb2008-08-01 16:41:48 +000013from autotest_lib.frontend.afe.json_rpc import proxy
14from autotest_lib.client.common_lib.test_utils import mock
mbligh41515392009-07-11 00:13:11 +000015from autotest_lib.client.common_lib import autotemp
mblighbe630eb2008-08-01 16:41:48 +000016
mblighb9a8b162008-10-29 16:47:29 +000017CLI_USING_PDB = False
mblighbe630eb2008-08-01 16:41:48 +000018CLI_UT_DEBUG = False
19
Justin Giorgid76ed502016-06-21 10:27:52 -070020
21class ExitException(Exception):
22 """Junk that should be removed."""
23 pass
24
mblighbe630eb2008-08-01 16:41:48 +000025def create_file(content):
Justin Giorgid76ed502016-06-21 10:27:52 -070026 """Create a temporary file for testing.
27
28 @param content: string contents for file.
29
30 @return: Instance of autotemp.tempfile with specified contents.
31 """
mbligh41515392009-07-11 00:13:11 +000032 file_temp = autotemp.tempfile(unique_id='cli_mock', text=True)
33 os.write(file_temp.fd, content)
mbligh41515392009-07-11 00:13:11 +000034 return file_temp
mblighbe630eb2008-08-01 16:41:48 +000035
36
mblighbe630eb2008-08-01 16:41:48 +000037class cli_unittest(unittest.TestCase):
Justin Giorgid76ed502016-06-21 10:27:52 -070038 """General mocks and setup / teardown for testing the atest cli.
39 """
mblighbe630eb2008-08-01 16:41:48 +000040 def setUp(self):
Justin Giorgid76ed502016-06-21 10:27:52 -070041 """Setup mocks for rpc calls and system exit.
42 """
mbligh9deeefa2009-05-01 23:11:08 +000043 super(cli_unittest, self).setUp()
mblighcd26d042010-05-03 18:58:24 +000044 self.god = mock.mock_god(debug=CLI_UT_DEBUG, ut=self)
mblighbe630eb2008-08-01 16:41:48 +000045 self.god.stub_class_method(rpc.afe_comm, 'run')
46 self.god.stub_function(sys, 'exit')
47
showardf4a68992010-02-03 20:29:59 +000048 def stub_authorization_headers(*args, **kwargs):
Justin Giorgid76ed502016-06-21 10:27:52 -070049 """No auth headers required for testing."""
showardf4a68992010-02-03 20:29:59 +000050 return {}
jamesrenf0a44382010-02-12 00:45:29 +000051 self.god.stub_with(rpc_client_lib, 'authorization_headers',
showardf4a68992010-02-03 20:29:59 +000052 stub_authorization_headers)
53
mblighbe630eb2008-08-01 16:41:48 +000054
55 def tearDown(self):
Justin Giorgid76ed502016-06-21 10:27:52 -070056 """Remove mocks.
57 """
58 # Unstub first because super may need exit
mblighbe630eb2008-08-01 16:41:48 +000059 self.god.unstub_all()
Justin Giorgid76ed502016-06-21 10:27:52 -070060 super(cli_unittest, self).tearDown()
mblighbe630eb2008-08-01 16:41:48 +000061
62
63 def assertEqualNoOrder(self, x, y, message=None):
Justin Giorgid76ed502016-06-21 10:27:52 -070064 """Assert x and y contain the same elements.
65
66 @param x: list like object for comparison.
67 @param y: second list like object for comparison
68 @param message: Message for AssertionError if x and y contain different
69 elements.
70
71 @raises: AssertionError
72 """
mblighbe630eb2008-08-01 16:41:48 +000073 self.assertEqual(set(x), set(y), message)
74
75
76 def assertWords(self, string, to_find=[], not_in=[]):
Justin Giorgid76ed502016-06-21 10:27:52 -070077 """Assert the string contains all of the set of words to_find and none
78 of the set not_in.
79
80 @param string: String to search.
81 @param to_find: List of strings that must be in string.
82 @param not_in: List of strings that must NOT be in string.
83
84 @raises: AssertionError
85 """
mblighbe630eb2008-08-01 16:41:48 +000086 for word in to_find:
87 self.assert_(string.find(word) >= 0,
88 "Could not find '%s' in: %s" % (word, string))
89 for word in not_in:
90 self.assert_(string.find(word) < 0,
91 "Found (and shouldn't have) '%s' in: %s" % (word,
92 string))
93
94
95 def _check_output(self, out='', out_words_ok=[], out_words_no=[],
96 err='', err_words_ok=[], err_words_no=[]):
97 if out_words_ok or out_words_no:
98 self.assertWords(out, out_words_ok, out_words_no)
99 else:
100 self.assertEqual('', out)
101
102 if err_words_ok or err_words_no:
103 self.assertWords(err, err_words_ok, err_words_no)
104 else:
105 self.assertEqual('', err)
106
107
mbligh7a3ebe32008-12-01 17:10:33 +0000108 def assertOutput(self, obj, results,
mblighbe630eb2008-08-01 16:41:48 +0000109 out_words_ok=[], out_words_no=[],
110 err_words_ok=[], err_words_no=[]):
Justin Giorgid76ed502016-06-21 10:27:52 -0700111 """Assert that obj's output writes the expected strings to std(out/err).
112
113 An empty list for out_words_ok or err_words_ok means that the stdout
114 or stderr (respectively) must be empty.
115
116 @param obj: Command object (such as atest_add_or_remove).
117 @param results: Results of command for obj.output to format.
118 @param out_words_ok: List of strings that must be in stdout.
119 @param out_words_no: List of strings that must NOT be in stdout.
120 @param err_words_ok: List of strings that must be in stderr.
121 @param err_words_no: List of strings that must NOT be in stderr.
122
123 @raises: AssertionError
124 """
mblighbe630eb2008-08-01 16:41:48 +0000125 self.god.mock_io()
mbligh7a3ebe32008-12-01 17:10:33 +0000126 obj.output(results)
mblighbe630eb2008-08-01 16:41:48 +0000127 obj.show_all_failures()
128 (out, err) = self.god.unmock_io()
129 self._check_output(out, out_words_ok, out_words_no,
130 err, err_words_ok, err_words_no)
131
132
133 def mock_rpcs(self, rpcs):
Justin Giorgid76ed502016-06-21 10:27:52 -0700134 """Expect and mock the results of a list of RPCs.
135
136 @param rpcs: A list of tuples, each representing one RPC:
137 (op, args(dict), success, expected)
138 """
mblighbe630eb2008-08-01 16:41:48 +0000139 for (op, dargs, success, expected) in rpcs:
140 comm = rpc.afe_comm.run
141 if success:
142 comm.expect_call(op, **dargs).and_return(expected)
143 else:
Justin Giorgid76ed502016-06-21 10:27:52 -0700144 (comm.expect_call(op, **dargs).
145 and_raises(proxy.JSONRPCException(expected)))
mblighbe630eb2008-08-01 16:41:48 +0000146
147
148 def run_cmd(self, argv, rpcs=[], exit_code=None,
149 out_words_ok=[], out_words_no=[],
150 err_words_ok=[], err_words_no=[]):
Justin Giorgid76ed502016-06-21 10:27:52 -0700151 """Run an atest command with arguments.
152
153 An empty list for out_words_ok or err_words_ok means that the stdout
154 or stderr (respectively) must be empty.
155
156 @param argv: List of command and arguments as strings.
157 @param rpcs: List of rpcs to expect the command to perform.
158 @param exit_code: Expected exit code of the command (if not 0).
159 @param out_words_ok: List of strings to expect in stdout.
160 @param out_words_no: List of strings that must not be in stdout.
161 @param err_words_ok: List of strings to expect in stderr.
162 @param err_words_no: List of strings that must not be in stderr.
163
164 @raises: AssertionError or CheckPlaybackError.
165
166 @returns: stdout, stderr
167 """
mblighbe630eb2008-08-01 16:41:48 +0000168 sys.argv = argv
169
170 self.mock_rpcs(rpcs)
171
mblighb9a8b162008-10-29 16:47:29 +0000172 if not (CLI_USING_PDB and CLI_UT_DEBUG):
mblighbe630eb2008-08-01 16:41:48 +0000173 self.god.mock_io()
mblighd876f452008-12-03 15:09:17 +0000174 if exit_code is not None:
mblighbe630eb2008-08-01 16:41:48 +0000175 sys.exit.expect_call(exit_code).and_raises(ExitException)
176 self.assertRaises(ExitException, atest.main)
177 else:
178 atest.main()
179 (out, err) = self.god.unmock_io()
180 self.god.check_playback()
181 self._check_output(out, out_words_ok, out_words_no,
182 err, err_words_ok, err_words_no)
183 return (out, err)
Justin Giorgid76ed502016-06-21 10:27:52 -0700184