1 # pylint: disable-msg=C0111 2 #!/usr/bin/python 3 # 4 # Copyright 2008 Google Inc. All Rights Reserved. 5 6 """Test for atest.""" 7 8 import unittest, os, sys, urllib2 9 10 import common 11 from autotest_lib.cli import cli_mock, topic_common, rpc 12 13 14 class topic_common_misc_tests(unittest.TestCase): 15 def test_get_item_key(self): 16 get_item_key = topic_common._get_item_key 17 self.assertRaises(ValueError, get_item_key, {}, '') 18 self.assertRaises(ValueError, get_item_key, {}, '.') 19 self.assertRaises(KeyError, get_item_key, {}, 'a') 20 self.assertRaises(KeyError, get_item_key, {}, 'a.') 21 self.assertRaises(ValueError, get_item_key, {'a': {}}, 'a.') 22 self.assertRaises(KeyError, get_item_key, {'a': {}}, 'a.b') 23 self.assertEquals(2, get_item_key({'a.b': 2, 'a': {}}, 'a.b')) 24 self.assertEquals(9, get_item_key({'a': {'b': 9}}, 'a.b')) 25 self.assertEquals(3, get_item_key({'a': {'b': {'c': 3}}}, 'a.b.c')) 26 self.assertEquals(5, get_item_key({'a': 5}, 'a')) 27 self.assertEquals({'b': 9}, get_item_key({'a': {'b': 9}}, 'a')) 28 29 30 class item_parse_info_unittest(cli_mock.cli_unittest): 31 def __test_parsing_flist_bad(self, options): 32 parse_info = topic_common.item_parse_info 33 test_parse_info = parse_info(attribute_name='testing', 34 filename_option='flist') 35 self.assertRaises(topic_common.CliError, 36 test_parse_info.get_values, options, []) 37 38 39 def __test_parsing_flist_good(self, options, expected): 40 parse_info = topic_common.item_parse_info 41 test_parse_info = parse_info(attribute_name='testing', 42 filename_option='flist') 43 result, leftover = test_parse_info.get_values(options, []) 44 45 self.assertEqualNoOrder(expected, result) 46 os.unlink(options.flist) 47 48 49 def __test_parsing_inline_good(self, options, expected): 50 parse_info = topic_common.item_parse_info 51 test_parse_info = parse_info(attribute_name='testing', 52 inline_option='inline') 53 result, leftover = test_parse_info.get_values(options, []) 54 55 self.assertEqualNoOrder(expected, result) 56 57 58 def __test_parsing_leftover_good(self, leftover, expected): 59 class opt(object): 60 pass 61 parse_info = topic_common.item_parse_info 62 test_parse_info = parse_info(attribute_name='testing', 63 inline_option='inline', 64 use_leftover=True) 65 result, leftover = test_parse_info.get_values(opt(), leftover) 66 67 self.assertEqualNoOrder(expected, result) 68 69 70 def __test_parsing_all_good(self, options, leftover, expected): 71 parse_info = topic_common.item_parse_info 72 test_parse_info = parse_info(attribute_name='testing', 73 inline_option='inline', 74 filename_option='flist', 75 use_leftover=True) 76 result, leftover = test_parse_info.get_values(options, leftover) 77 78 self.assertEqualNoOrder(expected, result) 79 os.unlink(options.flist) 80 81 82 def __test_parsing_all_bad(self, options, leftover): 83 parse_info = topic_common.item_parse_info 84 test_parse_info = parse_info(attribute_name='testing', 85 inline_option='inline', 86 filename_option='flist', 87 use_leftover=True) 88 self.assertRaises(topic_common.CliError, 89 test_parse_info.get_values, options, leftover) 90 91 92 def test_file_list_wrong_file(self): 93 class opt(object): 94 flist = './does_not_exist' 95 self.__test_parsing_flist_bad(opt()) 96 97 98 def test_file_list_empty_file(self): 99 class opt(object): 100 flist_obj = cli_mock.create_file('') 101 flist = flist_obj.name 102 self.__test_parsing_flist_bad(opt()) 103 104 105 def test_file_list_ok(self): 106 class opt(object): 107 flist_obj = cli_mock.create_file('a\nb\nc\n') 108 flist = flist_obj.name 109 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c']) 110 111 112 def test_file_list_one_line_space(self): 113 class opt(object): 114 flist_obj = cli_mock.create_file('a b c\nd e\nf\n') 115 flist = flist_obj.name 116 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 'f']) 117 118 119 def test_file_list_one_line_comma(self): 120 class opt(object): 121 flist_obj = cli_mock.create_file('a,b,c\nd,e\nf\n') 122 flist = flist_obj.name 123 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 'f']) 124 125 126 def test_file_list_one_line_mix(self): 127 class opt(object): 128 flist_obj = cli_mock.create_file('a,b c\nd,e\nf\ng h,i') 129 flist = flist_obj.name 130 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 131 'f', 'g', 'h', 'i']) 132 133 134 def test_file_list_one_line_comma_space(self): 135 class opt(object): 136 flist_obj = cli_mock.create_file('a, b c\nd,e\nf\ng h,i') 137 flist = flist_obj.name 138 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 139 'f', 'g', 'h', 'i']) 140 141 142 def test_file_list_line_end_comma_space(self): 143 class opt(object): 144 flist_obj = cli_mock.create_file('a, b c\nd,e, \nf,\ng h,i ,') 145 flist = flist_obj.name 146 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c', 'd', 'e', 147 'f', 'g', 'h', 'i']) 148 149 150 def test_file_list_no_eof(self): 151 class opt(object): 152 flist_obj = cli_mock.create_file('a\nb\nc') 153 flist = flist_obj.name 154 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c']) 155 156 157 def test_file_list_blank_line(self): 158 class opt(object): 159 flist_obj = cli_mock.create_file('\na\nb\n\nc\n') 160 flist = flist_obj.name 161 self.__test_parsing_flist_good(opt(), ['a', 'b', 'c']) 162 163 164 def test_file_list_escaped_commas(self): 165 class opt(object): 166 flist_obj = cli_mock.create_file('a\nb\\,c\\,d\nef\\,g') 167 flist = flist_obj.name 168 self.__test_parsing_flist_good(opt(), ['a', 'b,c,d', 'ef,g']) 169 170 171 def test_file_list_escaped_commas_slashes(self): 172 class opt(object): 173 flist_obj = cli_mock.create_file('a\nb\\\\\\,c\\,d\nef\\\\,g') 174 flist = flist_obj.name 175 self.__test_parsing_flist_good(opt(), ['a', 'b\\,c,d', 'ef\\', 'g']) 176 177 178 def test_file_list_opt_list_one(self): 179 class opt(object): 180 inline = 'a' 181 self.__test_parsing_inline_good(opt(), ['a']) 182 183 184 def test_file_list_opt_list_space(self): 185 class opt(object): 186 inline = 'a b c' 187 self.__test_parsing_inline_good(opt(), ['a', 'b', 'c']) 188 189 190 def test_file_list_opt_list_mix_space_comma(self): 191 class opt(object): 192 inline = 'a b,c,d e' 193 self.__test_parsing_inline_good(opt(), ['a', 'b', 'c', 'd', 'e']) 194 195 196 def test_file_list_opt_list_mix_comma_space(self): 197 class opt(object): 198 inline = 'a b,c, d e' 199 self.__test_parsing_inline_good(opt(), ['a', 'b', 'c', 'd', 'e']) 200 201 202 def test_file_list_opt_list_end_comma_space(self): 203 class opt(object): 204 inline = 'a b, ,c,, d e, ' 205 self.__test_parsing_inline_good(opt(), ['a', 'b', 'c', 'd', 'e']) 206 207 208 def test_file_list_opt_list_escaped_commas(self): 209 class opt(object): 210 inline = 'a\\,b,c, d' 211 self.__test_parsing_inline_good(opt(), ['a,b', 'c', 'd']) 212 213 214 def test_file_list_opt_list_escaped_commas_slashes(self): 215 class opt(object): 216 inline = 'a\\,b\\\\\\,c,d,e' 217 self.__test_parsing_inline_good(opt(), ['a,b\\,c', 'd', 'e']) 218 219 220 def test_file_list_add_on_space(self): 221 self.__test_parsing_leftover_good(['a','c','b'], 222 ['a', 'b', 'c']) 223 224 225 def test_file_list_add_on_mix_space_comma(self): 226 self.__test_parsing_leftover_good(['a', 'c','b,d'], 227 ['a', 'b', 'c', 'd']) 228 229 230 def test_file_list_add_on_mix_comma_space(self): 231 self.__test_parsing_leftover_good(['a', 'c', 'b,', 'd'], 232 ['a', 'b', 'c', 'd']) 233 234 235 def test_file_list_add_on_end_comma_space(self): 236 self.__test_parsing_leftover_good(['a', 'c', 'b,', 'd,', ','], 237 ['a', 'b', 'c', 'd']) 238 239 240 def test_file_list_add_on_escaped_commas(self): 241 self.__test_parsing_leftover_good(['a', 'c', 'b,', 'd\\,e\\,f'], 242 ['a', 'b', 'c', 'd,e,f']) 243 244 245 def test_file_list_add_on_escaped_commas_slashes(self): 246 self.__test_parsing_leftover_good(['a', 'c', 'b,', 'd\\\\\\,e,f'], 247 ['a', 'b', 'c', 'd\\,e', 'f']) 248 249 250 def test_file_list_all_opt(self): 251 class opt(object): 252 flist_obj = cli_mock.create_file('f\ng\nh\n') 253 flist = flist_obj.name 254 inline = 'a b,c,d e' 255 self.__test_parsing_all_good(opt(), ['i', 'j'], 256 ['a', 'b', 'c', 'd', 'e', 257 'f', 'g', 'h', 'i', 'j']) 258 259 260 def test_file_list_all_opt_empty_file(self): 261 class opt(object): 262 flist_obj = cli_mock.create_file('') 263 flist = flist_obj.name 264 inline = 'a b,c,d e' 265 self.__test_parsing_all_bad(opt(), ['i', 'j']) 266 267 268 def test_file_list_all_opt_in_common(self): 269 class opt(object): 270 flist_obj = cli_mock.create_file('f\nc\na\n') 271 flist = flist_obj.name 272 inline = 'a b,c,d e' 273 self.__test_parsing_all_good(opt(), ['i','j,d'], 274 ['a', 'b', 'c', 'd', 'e', 'f', 'i', 'j']) 275 276 277 def test_file_list_all_opt_in_common_space(self): 278 class opt(object): 279 flist_obj = cli_mock.create_file('a b c\nd,e\nf\ng') 280 flist = flist_obj.name 281 inline = 'a b,c,d h' 282 self.__test_parsing_all_good(opt(), ['i','j,d'], 283 ['a', 'b', 'c', 'd', 'e', 284 'f', 'g', 'h', 'i', 'j']) 285 286 287 def test_file_list_all_opt_in_common_weird(self): 288 class opt(object): 289 flist_obj = cli_mock.create_file('a b c\nd,e\nf\ng, \n, ,,') 290 flist = flist_obj.name 291 inline = 'a b,c,d h, , ,, ' 292 self.__test_parsing_all_good(opt(), ['i','j,d'], 293 ['a', 'b', 'c', 'd', 'e', 294 'f', 'g', 'h', 'i', 'j']) 295 296 297 def test_file_list_all_opt_in_common_escaped_commas(self): 298 class opt(object): 299 flist_obj = cli_mock.create_file('a\\,b\\,c\nd,e\nf\ng') 300 flist = flist_obj.name 301 inline = 'a\\,b\\,c,d h' 302 self.__test_parsing_all_good(opt(), ['i','j,d'], 303 ['a,b,c', 'd', 'e', 'f', 'g', 'h', 304 'i', 'j']) 305 306 307 def test_file_list_all_opt_in_common_escaped_commas_slashes(self): 308 class opt(object): 309 flist_obj = cli_mock.create_file('a\\,b\\\\\\,c\nd,e\nf,ghi, ,, j,') 310 flist = flist_obj.name 311 inline = 'a\\,b\\\\\\,c,d h,ijk' 312 self.__test_parsing_all_good(opt(), ['i','j,d'], 313 ['a,b\\,c', 'd', 'e', 'f', 'ghi', 'h', 314 'i', 'j', 'ijk']) 315 316 317 class atest_unittest(cli_mock.cli_unittest): 318 def setUp(self): 319 super(atest_unittest, self).setUp() 320 self.atest = topic_common.atest() 321 self.atest.afe = rpc.afe_comm() 322 if 'AUTOTEST_WEB' in os.environ: 323 del os.environ['AUTOTEST_WEB'] 324 325 326 def tearDown(self): 327 self.atest = None 328 super(atest_unittest, self).tearDown() 329 330 331 def test_invalid_arg_kill(self): 332 self.atest.kill_on_failure = True 333 self.god.mock_io() 334 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 335 self.assertRaises(cli_mock.ExitException, 336 self.atest.invalid_arg, 'This is bad') 337 (output, err) = self.god.unmock_io() 338 self.god.check_playback() 339 self.assert_(err.find('This is bad') >= 0) 340 341 342 def test_invalid_arg_continue(self): 343 self.god.mock_io() 344 self.atest.invalid_arg('This is sort of ok') 345 (output, err) = self.god.unmock_io() 346 self.assert_(err.find('This is sort of ok') >= 0) 347 348 349 def test_failure_continue(self): 350 self.atest.failure('This is partly bad', item='item0', 351 what_failed='something important') 352 err = self.atest.failed['something important'] 353 self.assert_('This is partly bad' in err.keys()) 354 355 356 def test_failure_continue_multiple_different_errors(self): 357 self.atest.failure('This is partly bad', item='item0', 358 what_failed='something important') 359 self.atest.failure('This is really bad', item='item0', 360 what_failed='something really important') 361 err = self.atest.failed['something important'] 362 self.assert_('This is partly bad' in err) 363 self.assert_('This is really bad' not in err) 364 err = self.atest.failed['something really important'] 365 self.assert_('This is partly bad' not in err) 366 self.assert_('This is really bad' in err) 367 368 369 def test_failure_continue_multiple_same_errors(self): 370 self.atest.failure('This is partly bad', item='item0', 371 what_failed='something important') 372 self.atest.failure('This is really bad', item='item1', 373 what_failed='something important') 374 errs = self.atest.failed['something important'] 375 self.assert_('This is partly bad' in errs) 376 self.assert_('This is really bad' in errs) 377 self.assert_(set(['item0']) in errs.values()) 378 self.assert_(set(['item1']) in errs.values()) 379 380 381 def test_failure_continue_multiple_errors_mixed(self): 382 self.atest.failure('This is partly bad', item='item0', 383 what_failed='something important') 384 self.atest.failure('This is really bad', item='item0', 385 what_failed='something really important') 386 self.atest.failure('This is really bad', item='item1', 387 what_failed='something important') 388 errs = self.atest.failed['something important'] 389 self.assert_('This is partly bad' in errs) 390 self.assert_('This is really bad' in errs) 391 self.assert_(set(['item0']) in errs.values()) 392 self.assert_(set(['item1']) in errs.values()) 393 394 errs = self.atest.failed['something really important'] 395 self.assert_('This is really bad' in errs) 396 self.assert_('This is partly bad' not in errs) 397 self.assert_(set(['item0']) in errs.values()) 398 self.assert_(set(['item1']) not in errs.values()) 399 400 401 def test_failure_continue_multiple_errors_mixed_same_error(self): 402 self.atest.failure('This is partly bad', item='item0', 403 what_failed='something important') 404 self.atest.failure('This is really bad', item='item0', 405 what_failed='something really important') 406 self.atest.failure('This is partly bad', item='item1', 407 what_failed='something important') 408 errs = self.atest.failed['something important'] 409 self.assert_('This is partly bad' in errs) 410 self.assert_('This is really bad' not in errs) 411 self.assert_(set(['item0', 'item1']) in errs.values()) 412 413 errs = self.atest.failed['something really important'] 414 self.assert_('This is really bad' in errs) 415 self.assert_('This is partly bad' not in errs) 416 self.assert_(set(['item0']) in errs.values()) 417 self.assert_(set(['item1']) not in errs.values()) 418 419 420 def test_failure_exit(self): 421 self.atest.kill_on_failure = True 422 self.god.mock_io() 423 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 424 self.assertRaises(cli_mock.ExitException, 425 self.atest.failure, 'This is partly bad') 426 (output, err) = self.god.unmock_io() 427 self.god.check_playback() 428 self.assert_(err.find('This is partly bad') >= 0) 429 430 431 def test_failure_exit_item(self): 432 self.atest.kill_on_failure = True 433 self.god.mock_io() 434 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 435 self.assertRaises(cli_mock.ExitException, 436 self.atest.failure, 'This is partly bad', 437 item='item0') 438 (output, err) = self.god.unmock_io() 439 self.god.check_playback() 440 self.assertWords(err, ['This is partly bad'], ['item0']) 441 442 443 def test_show_all_failures_common(self): 444 self.atest.failure('This is partly bad', item='item0', 445 what_failed='something important') 446 self.atest.failure('This is partly bad', item='item1', 447 what_failed='something important') 448 self.god.mock_io() 449 self.atest.show_all_failures() 450 (output, err) = self.god.unmock_io() 451 self.assertWords(err, ['something important', 452 'This is partly bad', 'item0', 'item1']) 453 454 455 def test_parse_add_on(self): 456 flist = cli_mock.create_file('host1\nhost2\nleft2') 457 sys.argv = ['atest', '--web', 'fooweb', '--parse', 458 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 459 self.atest.parser.add_option('-M', '--mlist', type='string') 460 item_info = topic_common.item_parse_info(attribute_name='hosts', 461 filename_option='mlist', 462 use_leftover=True) 463 (options, leftover) = self.atest.parse([item_info]) 464 self.assertEqualNoOrder(self.atest.hosts, 465 ['left1', 'left2', 'host1', 'host2']) 466 467 self.assertEqual({'mlist': flist.name, 468 'web_server': 'fooweb', 469 'parse': True, 470 'parse_delim': '|', 471 'kill_on_failure': True, 472 'verbose': False, 473 'no_confirmation': False, 474 'debug': False, 475 'log_level':'ERROR'}, options) 476 self.assertEqual(leftover, []) 477 flist.clean() 478 479 480 def test_parse_no_add_on(self): 481 flist = cli_mock.create_file('host1\nhost2\nleft2') 482 sys.argv = ['atest', '--web', 'fooweb', '--parse', '-g', 483 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 484 self.atest.parser.add_option('-M', '--mlist', type='string') 485 item_info = topic_common.item_parse_info(attribute_name='hosts', 486 filename_option='mlist') 487 (options, leftover) = self.atest.parse([item_info]) 488 self.assertEqualNoOrder(self.atest.hosts, 489 ['left2', 'host1', 'host2']) 490 491 self.assertEqual({'mlist': flist.name, 492 'web_server': 'fooweb', 493 'parse': True, 494 'parse_delim': '|', 495 'kill_on_failure': True, 496 'verbose': False, 497 'no_confirmation': False, 498 'debug': True, 499 'log_level':'ERROR'}, options) 500 self.assertEqual(leftover, ['left1', 'left2']) 501 flist.clean() 502 503 504 def test_parse_add_on_first(self): 505 flist = cli_mock.create_file('host1\nhost2\nleft2') 506 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 507 sys.argv = ['atest', '-g', '--parse', '--ulist', ulist.name, 508 '-u', 'myuser,youruser', 509 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 510 self.atest.parser.add_option('-M', '--mlist', type='string') 511 self.atest.parser.add_option('-U', '--ulist', type='string') 512 self.atest.parser.add_option('-u', '--user', type='string') 513 host_info = topic_common.item_parse_info(attribute_name='hosts', 514 filename_option='mlist', 515 use_leftover=True) 516 user_info = topic_common.item_parse_info(attribute_name='users', 517 inline_option='user', 518 filename_option='ulist') 519 520 (options, leftover) = self.atest.parse([host_info, user_info]) 521 self.assertEqualNoOrder(self.atest.hosts, 522 ['left1', 'left2', 'host1', 'host2']) 523 self.assertEqualNoOrder(self.atest.users, 524 ['user1', 'user2', 'user3', 525 'myuser', 'youruser']) 526 527 self.assertEqual({'mlist': flist.name, 528 'ulist': ulist.name, 529 'user': 'myuser,youruser', 530 'web_server': None, 531 'parse': True, 532 'parse_delim': '|', 533 'kill_on_failure': True, 534 'verbose': False, 535 'no_confirmation': False, 536 'debug': True, 537 'log_level':'ERROR'}, options) 538 self.assertEqual(leftover, []) 539 flist.clean() 540 ulist.clean() 541 542 543 def test_parse_add_on_second(self): 544 flist = cli_mock.create_file('host1\nhost2\nleft2') 545 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 546 sys.argv = ['atest', '-g', '--parse', '-U', ulist.name, 547 '-u', 'myuser,youruser', 548 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 549 self.atest.parser.add_option('-M', '--mlist', type='string') 550 self.atest.parser.add_option('-U', '--ulist', type='string') 551 self.atest.parser.add_option('-u', '--user', type='string') 552 host_info = topic_common.item_parse_info(attribute_name='hosts', 553 filename_option='mlist', 554 use_leftover=True) 555 user_info = topic_common.item_parse_info(attribute_name='users', 556 inline_option='user', 557 filename_option='ulist') 558 (options, leftover) = self.atest.parse([host_info, user_info]) 559 560 self.assertEqualNoOrder(self.atest.hosts, 561 ['left1', 'left2', 'host1', 'host2']) 562 self.assertEqualNoOrder(self.atest.users, 563 ['user1', 'user2', 'user3', 564 'myuser', 'youruser']) 565 566 self.assertEqual({'mlist': flist.name, 567 'ulist': ulist.name, 568 'user': 'myuser,youruser', 569 'web_server': None, 570 'parse': True, 571 'parse_delim': '|', 572 'kill_on_failure': True, 573 'verbose': False, 574 'no_confirmation': False, 575 'debug': True, 576 'log_level':'ERROR'}, options) 577 self.assertEqual(leftover, []) 578 flist.clean() 579 ulist.clean() 580 581 582 def test_parse_all_opts(self): 583 flist = cli_mock.create_file('host1\nhost2\nleft2') 584 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 585 sys.argv = ['atest', '-g', '--parse', '--ulist', ulist.name, 586 '-u', 'myuser,youruser', 587 '--kill-on-failure', '-M', flist.name, 'left1', 'left2'] 588 self.atest.parser.add_option('-M', '--mlist', type='string') 589 self.atest.parser.add_option('-U', '--ulist', type='string') 590 self.atest.parser.add_option('-u', '--user', type='string') 591 host_info = topic_common.item_parse_info(attribute_name='hosts', 592 filename_option='mlist', 593 use_leftover=True) 594 user_info = topic_common.item_parse_info(attribute_name='users', 595 inline_option='user', 596 filename_option='ulist') 597 (options, leftover) = self.atest.parse([host_info, user_info]) 598 self.assertEqualNoOrder(self.atest.hosts, 599 ['left1', 'left2', 'host1', 'host2']) 600 self.assertEqualNoOrder(self.atest.users, 601 ['user1', 'user2', 'user3', 602 'myuser', 'youruser']) 603 604 self.assertEqual({'mlist': flist.name, 605 'ulist': ulist.name, 606 'user': 'myuser,youruser', 607 'web_server': None, 608 'parse': True, 609 'parse_delim': '|', 610 'kill_on_failure': True, 611 'verbose': False, 612 'no_confirmation': False, 613 'debug': True, 614 'log_level':'ERROR'}, options) 615 self.assertEqual(leftover, []) 616 flist.clean() 617 ulist.clean() 618 619 620 def test_parse_no_add_on_2(self): 621 flist = cli_mock.create_file('host1\nhost2\nleft2') 622 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 623 sys.argv = ['atest', '-U', ulist.name, 624 '--kill-on-failure', '-M', flist.name] 625 self.atest.parser.add_option('-M', '--mlist', type='string') 626 self.atest.parser.add_option('-U', '--ulist', type='string') 627 self.atest.parser.add_option('-u', '--user', type='string') 628 host_info = topic_common.item_parse_info(attribute_name='hosts', 629 filename_option='mlist', 630 use_leftover=True) 631 user_info = topic_common.item_parse_info(attribute_name='users', 632 inline_option='user', 633 filename_option='ulist') 634 (options, leftover) = self.atest.parse([host_info, user_info]) 635 self.assertEqualNoOrder(self.atest.hosts, 636 ['left2', 'host1', 'host2']) 637 self.assertEqualNoOrder(self.atest.users, 638 ['user1', 'user2', 'user3']) 639 640 self.assertEqual({'mlist': flist.name, 641 'ulist': ulist.name, 642 'user': None, 643 'web_server': None, 644 'parse': False, 645 'parse_delim': '|', 646 'kill_on_failure': True, 647 'verbose': False, 648 'no_confirmation': False, 649 'debug': False, 650 'log_level':'ERROR'}, options) 651 self.assertEqual(leftover, []) 652 flist.clean() 653 ulist.clean() 654 655 656 def test_parse_no_flist_add_on(self): 657 sys.argv = ['atest', '-g', '--parse', '-u', 'myuser,youruser', 658 '--kill-on-failure', 'left1', 'left2'] 659 self.atest.parser.add_option('-M', '--mlist', type='string') 660 self.atest.parser.add_option('-U', '--ulist', type='string') 661 self.atest.parser.add_option('-u', '--user', type='string') 662 host_info = topic_common.item_parse_info(attribute_name='hosts', 663 use_leftover=True) 664 user_info = topic_common.item_parse_info(attribute_name='users', 665 inline_option='user') 666 (options, leftover) = self.atest.parse([host_info, user_info]) 667 self.assertEqualNoOrder(self.atest.hosts, 668 ['left1', 'left2']) 669 self.assertEqualNoOrder(self.atest.users, 670 ['myuser', 'youruser']) 671 672 self.assertEqual({'mlist': None, 673 'ulist': None, 674 'user': 'myuser,youruser', 675 'web_server': None, 676 'parse': True, 677 'parse_delim': '|', 678 'kill_on_failure': True, 679 'verbose': False, 680 'no_confirmation': False, 681 'debug': True, 682 'log_level':'ERROR'}, options) 683 self.assertEqual(leftover, []) 684 685 686 def test_parse_no_flist_no_add_on(self): 687 sys.argv = ['atest', '-u', 'myuser,youruser', '--kill-on-failure', 688 '-a', 'acl1,acl2'] 689 self.atest.parser.add_option('-u', '--user', type='string') 690 self.atest.parser.add_option('-a', '--acl', type='string') 691 acl_info = topic_common.item_parse_info(attribute_name='acls', 692 inline_option='acl') 693 user_info = topic_common.item_parse_info(attribute_name='users', 694 inline_option='user') 695 (options, leftover) = self.atest.parse([user_info, acl_info]) 696 self.assertEqualNoOrder(self.atest.acls, 697 ['acl1', 'acl2']) 698 self.assertEqualNoOrder(self.atest.users, 699 ['myuser', 'youruser']) 700 701 self.assertEqual({'user': 'myuser,youruser', 702 'acl': 'acl1,acl2', 703 'web_server': None, 704 'parse': False, 705 'parse_delim': '|', 706 'kill_on_failure': True, 707 'verbose': False, 708 'no_confirmation': False, 709 'debug': False, 710 'log_level':'ERROR'}, options) 711 self.assertEqual(leftover, []) 712 713 714 def test_parse_req_items_ok(self): 715 sys.argv = ['atest', '-u', 'myuser,youruser'] 716 self.atest.parser.add_option('-u', '--user', type='string') 717 user_info = topic_common.item_parse_info(attribute_name='users', 718 inline_option='user') 719 (options, leftover) = self.atest.parse([user_info], 720 req_items='users') 721 self.assertEqualNoOrder(self.atest.users, 722 ['myuser', 'youruser']) 723 724 self.assertEqual({'user': 'myuser,youruser', 725 'web_server': None, 726 'parse': False, 727 'parse_delim': '|', 728 'kill_on_failure': False, 729 'verbose': False, 730 'no_confirmation': False, 731 'debug': False, 732 'log_level':'ERROR'}, options) 733 self.assertEqual(leftover, []) 734 735 736 def test_parse_req_items_missing(self): 737 sys.argv = ['atest', '-u', 'myuser,youruser', '--kill-on-failure'] 738 self.atest.parser.add_option('-u', '--user', type='string') 739 acl_info = topic_common.item_parse_info(attribute_name='acls', 740 inline_option='acl') 741 user_info = topic_common.item_parse_info(attribute_name='users', 742 inline_option='user') 743 self.god.mock_io() 744 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 745 self.assertRaises(cli_mock.ExitException, 746 self.atest.parse, 747 [user_info, acl_info], 748 'acls') 749 self.assertEqualNoOrder(self.atest.users, 750 ['myuser', 'youruser']) 751 752 self.assertEqualNoOrder(self.atest.acls, []) 753 self.god.check_playback() 754 self.god.unmock_io() 755 756 757 def test_parse_bad_option(self): 758 sys.argv = ['atest', '--unknown'] 759 self.god.stub_function(self.atest.parser, 'error') 760 self.atest.parser.error.expect_call('no such option: --unknown').and_return(None) 761 self.atest.parse() 762 self.god.check_playback() 763 764 765 def test_parse_all_set(self): 766 sys.argv = ['atest', '--web', 'fooweb', '--parse', '--debug', 767 '--kill-on-failure', '--verbose', 'left1', 'left2', 768 '--parse-delim', '?'] 769 (options, leftover) = self.atest.parse() 770 self.assertEqual({'web_server': 'fooweb', 771 'parse': True, 772 'parse_delim': '?', 773 'kill_on_failure': True, 774 'verbose': True, 775 'no_confirmation': False, 776 'debug': True, 777 'log_level':'ERROR'}, options) 778 self.assertEqual(leftover, ['left1', 'left2']) 779 780 781 def test_execute_rpc_bad_server(self): 782 self.atest.afe = rpc.afe_comm('http://does_not_exist') 783 self.god.mock_io() 784 rpc.afe_comm.run.expect_call('myop').and_raises(urllib2.URLError("<urlopen error (-2, 'Name or service not known')>")) 785 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 786 self.assertRaises(cli_mock.ExitException, 787 self.atest.execute_rpc, 'myop') 788 (output, err) = self.god.unmock_io() 789 self.god.check_playback() 790 self.assert_(err.find('http://does_not_exist') >= 0) 791 792 793 # 794 # Print Unit tests 795 # 796 def __test_print_fields(self, func, expected, **dargs): 797 if not dargs.has_key('items'): 798 dargs['items']=[{'hostname': 'h0', 799 'platform': 'p0', 800 'labels': [u'l0', u'l1'], 801 'locked': 1, 802 'id': 'id0', 803 'name': 'name0'}, 804 {'hostname': 'h1', 805 'platform': 'p1', 806 'labels': [u'l2', u'l3'], 807 'locked': 0, 808 'id': 'id1', 809 'name': 'name1'}] 810 self.god.mock_io() 811 func(**dargs) 812 (output, err) = self.god.unmock_io() 813 self.assertEqual(expected, output) 814 815 816 # 817 # Print fields Standard 818 # 819 def __test_print_fields_std(self, keys, expected): 820 self.__test_print_fields(self.atest.print_fields_std, 821 expected, keys=keys) 822 823 824 def test_print_fields_std_one_str(self): 825 self.__test_print_fields_std(['hostname'], 826 'Host: h0\n' 827 'Host: h1\n') 828 829 830 def test_print_fields_std_conv_bool(self): 831 """Make sure the conversion functions are called""" 832 self.__test_print_fields_std(['locked'], 833 'Locked: True\n' 834 'Locked: False\n') 835 836 837 def test_print_fields_std_conv_label(self): 838 """Make sure the conversion functions are called""" 839 self.__test_print_fields_std(['labels'], 840 'Labels: l0, l1\n' 841 'Labels: l2, l3\n') 842 843 844 def test_print_fields_std_all_fields(self): 845 """Make sure the conversion functions are called""" 846 self.__test_print_fields_std(['hostname', 'platform','locked'], 847 'Host: h0\n' 848 'Platform: p0\n' 849 'Locked: True\n' 850 'Host: h1\n' 851 'Platform: p1\n' 852 'Locked: False\n') 853 854 855 # 856 # Print fields parse 857 # 858 def __test_print_fields_parse(self, keys, expected): 859 self.__test_print_fields(self.atest.print_fields_parse, 860 expected, keys=keys) 861 862 863 def test_print_fields_parse_one_str(self): 864 self.__test_print_fields_parse(['hostname'], 865 'Host=h0\n' 866 'Host=h1\n') 867 868 869 def test_print_fields_parse_conv_bool(self): 870 self.__test_print_fields_parse(['locked'], 871 'Locked=True\n' 872 'Locked=False\n') 873 874 875 def test_print_fields_parse_conv_label(self): 876 self.__test_print_fields_parse(['labels'], 877 'Labels=l0, l1\n' 878 'Labels=l2, l3\n') 879 880 881 def test_print_fields_parse_all_fields(self): 882 self.__test_print_fields_parse(['hostname', 'platform', 'locked'], 883 'Host=h0|Platform=p0|' 884 'Locked=True\n' 885 'Host=h1|Platform=p1|' 886 'Locked=False\n') 887 888 889 # 890 # Print table standard 891 # 892 def __test_print_table_std(self, keys, expected): 893 self.__test_print_fields(self.atest.print_table_std, 894 expected, keys_header=keys) 895 896 897 def test_print_table_std_all_fields(self): 898 self.__test_print_table_std(['hostname', 'platform','locked'], 899 'Host Platform Locked\n' 900 'h0 p0 True\n' 901 'h1 p1 False\n') 902 903 # TODO JME - add long fields tests 904 905 906 # 907 # Print table parse 908 # 909 def __test_print_table_parse(self, keys, expected): 910 self.__test_print_fields(self.atest.print_table_parse, 911 expected, keys_header=keys) 912 913 914 def test_print_table_parse_all_fields(self): 915 self.__test_print_table_parse(['hostname', 'platform', 916 'locked'], 917 'Host=h0|Platform=p0|Locked=True\n' 918 'Host=h1|Platform=p1|Locked=False\n') 919 920 921 def test_print_table_parse_all_fields_2(self): 922 self.atest.parse_delim = '?' 923 self.__test_print_table_parse(['hostname', 'platform', 924 'locked'], 925 'Host=h0?Platform=p0?Locked=True\n' 926 'Host=h1?Platform=p1?Locked=False\n') 927 928 929 def test_print_table_parse_empty_fields(self): 930 self.__test_print_fields(self.atest.print_table_parse, 931 'Host=h0|Platform=p0\n' 932 'Host=h1|Platform=p1|Labels=l2, l3\n', 933 items=[{'hostname': 'h0', 934 'platform': 'p0', 935 'labels': [], 936 'locked': 1, 937 'id': 'id0', 938 'name': 'name0'}, 939 {'hostname': 'h1', 940 'platform': 'p1', 941 'labels': [u'l2', u'l3'], 942 'locked': 0, 943 'id': 'id1', 944 'name': 'name1'}], 945 keys_header=['hostname', 'platform', 946 'labels']) 947 948 949 # 950 # Print mix table standard 951 # 952 def __test_print_mix_table_std(self, keys_header, sublist_keys, 953 expected): 954 self.__test_print_fields(self.atest.print_table_std, 955 expected, 956 keys_header=keys_header, 957 sublist_keys=sublist_keys) 958 959 960 def test_print_mix_table(self): 961 self.__test_print_mix_table_std(['name', 'hostname'], [], 962 'Name Host\n' 963 'name0 h0\n' 964 'name1 h1\n') 965 966 967 def test_print_mix_table_sublist(self): 968 self.__test_print_mix_table_std(['name', 'hostname'], ['labels'], 969 'Name Host\n' 970 'name0 h0\n' 971 'Labels: \n' 972 '\tl0, l1\n\n\n' 973 'name1 h1\n' 974 'Labels: \n' 975 '\tl2, l3\n\n\n') 976 977 978 # 979 # Print by ID standard 980 # 981 def __test_print_by_ids_std(self, expected): 982 self.__test_print_fields(self.atest.print_by_ids_std, 983 expected) 984 985 986 def test_print_by_ids_std_all_fields(self): 987 self.__test_print_by_ids_std('Id Name\n' 988 'id0 name0\n' 989 'id1 name1\n') 990 991 992 # 993 # Print by ID parse 994 # 995 def __test_print_by_ids_parse(self, expected): 996 self.__test_print_fields(self.atest.print_by_ids_parse, 997 expected) 998 999 1000 def test_print_by_ids_parse_all_fields(self): 1001 self.__test_print_by_ids_parse('Id=id0|Name=name0|' 1002 'Id=id1|Name=name1\n') 1003 1004 1005 if __name__ == '__main__': 1006 unittest.main() 1007