1#!/usr/bin/python3 2# pylint: disable-msg=C0111 3 4from __future__ import absolute_import 5from __future__ import division 6from __future__ import print_function 7 8import json 9import os 10import six 11from six.moves import range 12import unittest 13 14import common 15 16from autotest_lib.client.common_lib import control_data, autotemp 17 18 19ControlData = control_data.ControlData 20 21CONTROL = """ 22AUTHOR = 'Author' 23DEPENDENCIES = "console, power" 24DOC = \"\"\"\ 25doc stuff\"\"\" 26# EXPERIMENTAL should implicitly be False 27NAME = 'nA' "mE" 28RUN_VERIFY = False 29SYNC_COUNT = 2 30TIME='short' 31TEST_CLASS=u'Kernel' 32TEST_CATEGORY='Stress' 33TEST_TYPE='client' 34REQUIRE_SSP = False 35ATTRIBUTES = "suite:smoke, suite:bvt" 36SUITE = "suite-listed-only-in-suite-line" 37""" 38 39# Control data being wrapped into step* functions. 40WRAPPED_CONTROL = """ 41def step_init(): 42 step0() 43 44def step0(): 45 AUTHOR = 'Author' 46 DEPENDENCIES = "console, power" 47 DOC = \"\"\"\ 48 doc stuff\"\"\" 49 # EXPERIMENTAL should implicitly be False 50 NAME = 'nA' "mE" 51 RUN_VERIFY = False 52 SYNC_COUNT = 2 53 TIME='short' 54 TEST_CLASS=u'Kernel' 55 TEST_CATEGORY='Stress' 56 TEST_TYPE='client' 57 REQUIRE_SSP = False 58 ATTRIBUTES = "suite:smoke, suite:bvt" 59 SUITE = "suite-listed-only-in-suite-line" 60 MAX_RESULT_SIZE_KB = 20000 61 62step_init() 63""" 64 65 66class ControlDataTestCase(unittest.TestCase): 67 def setUp(self): 68 self._required_vars = control_data.REQUIRED_VARS 69 control_data.REQUIRED_VARS = set() 70 71 72 def tearDown(self): 73 control_data.REQUIRED_VARS = self._required_vars 74 75 76 def test_suite_tag_parts(self): 77 cd = ControlData({'suite': 'foo,bar'}, 'filename') 78 self.assertEqual(set(cd.suite_tag_parts), {'foo', 'bar'}) 79 80 81 def test_suite_tag_parts_empty_for_non_suite(self): 82 cd = ControlData({}, 'filename') 83 self.assertEqual(cd.suite_tag_parts, []) 84 85 86 87class ParseControlTest(unittest.TestCase): 88 def setUp(self): 89 self.control_tmp = autotemp.tempfile(unique_id='control_unit', 90 text=True) 91 os.write(self.control_tmp.fd, str.encode(CONTROL)) 92 93 94 def tearDown(self): 95 self.control_tmp.clean() 96 97 98 def test_parse_control(self): 99 cd = control_data.parse_control(self.control_tmp.name, True) 100 self.assertEqual(cd.author, "Author") 101 self.assertEqual(cd.dependencies, set(['console', 'power'])) 102 self.assertEqual(cd.doc, "doc stuff") 103 self.assertEqual(cd.experimental, False) 104 self.assertEqual(cd.name, "nAmE") 105 self.assertEqual(cd.run_verify, False) 106 self.assertEqual(cd.sync_count, 2) 107 self.assertEqual(cd.time, "short") 108 self.assertEqual(cd.test_class, "kernel") 109 self.assertEqual(cd.test_category, "stress") 110 self.assertEqual(cd.test_type, "client") 111 self.assertEqual(cd.require_ssp, False) 112 self.assertEqual(cd.attributes, set(["suite:smoke", "suite:bvt"])) 113 self.assertEqual(cd.suite, "bvt,smoke,suite-listed-only-in-suite-line") 114 115 116class ParseWrappedControlTest(unittest.TestCase): 117 """Test control data can be retrieved from wrapped step functions.""" 118 def setUp(self): 119 self.control_tmp = autotemp.tempfile(unique_id='wrapped_control_unit', 120 text=True) 121 os.write(self.control_tmp.fd, str.encode(WRAPPED_CONTROL)) 122 123 124 def tearDown(self): 125 self.control_tmp.clean() 126 127 128 def test_parse_control(self): 129 cd = control_data.parse_control(self.control_tmp.name, True) 130 self.assertEqual(cd.author, "Author") 131 self.assertEqual(cd.dependencies, set(['console', 'power'])) 132 self.assertEqual(cd.doc, "doc stuff") 133 self.assertEqual(cd.experimental, False) 134 self.assertEqual(cd.name, "nAmE") 135 self.assertEqual(cd.run_verify, False) 136 self.assertEqual(cd.sync_count, 2) 137 self.assertEqual(cd.time, "short") 138 self.assertEqual(cd.test_class, "kernel") 139 self.assertEqual(cd.test_category, "stress") 140 self.assertEqual(cd.test_type, "client") 141 self.assertEqual(cd.require_ssp, False) 142 self.assertEqual(cd.attributes, set(["suite:smoke", "suite:bvt"])) 143 self.assertEqual(cd.suite, "bvt,smoke,suite-listed-only-in-suite-line") 144 self.assertEqual(cd.max_result_size_KB, 20000) 145 146 147class ParseControlFileBugTemplate(unittest.TestCase): 148 def setUp(self): 149 self.control_tmp = autotemp.tempfile(unique_id='control_unit', 150 text=True) 151 self.bug_template = { 152 'owner': '[email protected]', 153 'labels': ['a', 'b'], 154 'status': None, 155 'summary': None, 156 'title': None, 157 'cc': ['a@something, b@something'], 158 } 159 160 161 def tearDown(self): 162 self.control_tmp.clean() 163 164 165 def insert_bug_template(self, control_file_string): 166 """Insert a bug template into the control file string. 167 168 @param control_file_string: A string of the control file contents 169 this test will run on. 170 171 @return: The control file string with the BUG_TEMPLATE line. 172 """ 173 bug_template_line = 'BUG_TEMPLATE = %s' % json.dumps(self.bug_template) 174 return control_file_string + bug_template_line 175 176 177 def verify_bug_template(self, new_bug_template): 178 """Verify that the bug template given matches the original. 179 180 @param new_bug_template: A bug template pulled off parsing the 181 control file. 182 183 @raises AssetionError: If a value under a give key in the bug template 184 doesn't match the value in self.bug_template. 185 @raises KeyError: If a key in either bug template is missing. 186 """ 187 for key, value in six.iteritems(new_bug_template): 188 self.assertEqual(value, self.bug_template[key]) 189 190 191 def test_bug_template_parsing(self): 192 """Basic parsing test for a bug templates in a test control file.""" 193 os.write(self.control_tmp.fd, 194 str.encode(self.insert_bug_template(CONTROL))) 195 cd = control_data.parse_control(self.control_tmp.name, True) 196 self.verify_bug_template(cd.bug_template) 197 198 199 def test_bug_template_list(self): 200 """Test that lists in the bug template can handle other datatypes.""" 201 self.bug_template['labels'].append({'foo': 'bar'}) 202 os.write(self.control_tmp.fd, 203 str.encode(self.insert_bug_template(CONTROL))) 204 cd = control_data.parse_control(self.control_tmp.name, True) 205 self.verify_bug_template(cd.bug_template) 206 207 208 def test_bad_template(self): 209 """Test that a bad bug template doesn't result in a bad control data.""" 210 self.bug_template = 'foobarbug_template' 211 os.write(self.control_tmp.fd, 212 str.encode(self.insert_bug_template(CONTROL))) 213 cd = control_data.parse_control(self.control_tmp.name, True) 214 self.assertFalse(hasattr(cd, 'bug_template')) 215 216 217class SetMethodTests(unittest.TestCase): 218 def setUp(self): 219 self.required_vars = control_data.REQUIRED_VARS 220 control_data.REQUIRED_VARS = set() 221 222 223 def tearDown(self): 224 control_data.REQUIRED_VARS = self.required_vars 225 226 227 def test_bool(self): 228 cd = ControlData({}, 'filename') 229 cd._set_bool('foo', 'False') 230 self.assertEqual(cd.foo, False) 231 cd._set_bool('foo', True) 232 self.assertEqual(cd.foo, True) 233 cd._set_bool('foo', 'FALSE') 234 self.assertEqual(cd.foo, False) 235 cd._set_bool('foo', 'true') 236 self.assertEqual(cd.foo, True) 237 self.assertRaises(ValueError, cd._set_bool, 'foo', '') 238 self.assertRaises(ValueError, cd._set_bool, 'foo', 1) 239 self.assertRaises(ValueError, cd._set_bool, 'foo', []) 240 self.assertRaises(ValueError, cd._set_bool, 'foo', None) 241 242 243 def test_int(self): 244 cd = ControlData({}, 'filename') 245 cd._set_int('foo', 0) 246 self.assertEqual(cd.foo, 0) 247 cd._set_int('foo', '0') 248 self.assertEqual(cd.foo, 0) 249 cd._set_int('foo', '-1', min=-2, max=10) 250 self.assertEqual(cd.foo, -1) 251 self.assertRaises(ValueError, cd._set_int, 'foo', 0, min=1) 252 self.assertRaises(ValueError, cd._set_int, 'foo', 1, max=0) 253 self.assertRaises(ValueError, cd._set_int, 'foo', 'x') 254 self.assertRaises(ValueError, cd._set_int, 'foo', '') 255 self.assertRaises(TypeError, cd._set_int, 'foo', None) 256 257 258 def test_set(self): 259 cd = ControlData({}, 'filename') 260 cd._set_set('foo', 'a') 261 self.assertEqual(cd.foo, set(['a'])) 262 cd._set_set('foo', 'a,b,c') 263 self.assertEqual(cd.foo, set(['a', 'b', 'c'])) 264 cd._set_set('foo', ' a , b , c ') 265 self.assertEqual(cd.foo, set(['a', 'b', 'c'])) 266 cd._set_set('foo', None) 267 self.assertEqual(cd.foo, set(['None'])) 268 269 270 def test_string(self): 271 cd = ControlData({}, 'filename') 272 cd._set_string('foo', 'a') 273 self.assertEqual(cd.foo, 'a') 274 cd._set_string('foo', 'b') 275 self.assertEqual(cd.foo, 'b') 276 cd._set_string('foo', 'B') 277 self.assertEqual(cd.foo, 'B') 278 cd._set_string('foo', 1) 279 self.assertEqual(cd.foo, '1') 280 cd._set_string('foo', None) 281 self.assertEqual(cd.foo, 'None') 282 cd._set_string('foo', []) 283 self.assertEqual(cd.foo, '[]') 284 285 286 def test_option(self): 287 options = ['a', 'b'] 288 cd = ControlData({}, 'filename') 289 cd._set_option('foo', 'a', options) 290 self.assertEqual(cd.foo, 'a') 291 cd._set_option('foo', 'b', options) 292 self.assertEqual(cd.foo, 'b') 293 cd._set_option('foo', 'B', options) 294 self.assertEqual(cd.foo, 'B') 295 self.assertRaises(ValueError, cd._set_option, 296 'foo', 'x', options) 297 self.assertRaises(ValueError, cd._set_option, 298 'foo', 1, options) 299 self.assertRaises(ValueError, cd._set_option, 300 'foo', [], options) 301 self.assertRaises(ValueError, cd._set_option, 302 'foo', None, options) 303 304 305 def test_set_attributes(self): 306 cd = ControlData({}, 'filename') 307 cd.set_attributes('suite:bvt') 308 self.assertEqual(cd.attributes, set(['suite:bvt'])) 309 310 311 def test_get_test_time_index(self): 312 inputs = [time.upper() for time in 313 ControlData.TEST_TIME_LIST] 314 time_min_index = [ControlData.get_test_time_index(time) 315 for time in inputs] 316 expected_time_index = list(range(len(ControlData.TEST_TIME_LIST))) 317 self.assertEqual(time_min_index, expected_time_index) 318 319 320 def test_get_test_time_index_failure(self): 321 def fail(): 322 """Test function to raise ControlVariableException exception 323 for invalid TIME setting.""" 324 index = ControlData.get_test_time_index('some invalid TIME') 325 326 self.assertRaises(control_data.ControlVariableException, fail) 327 328 329# this is so the test can be run in standalone mode 330if __name__ == '__main__': 331 unittest.main() 332