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}, options) 475 self.assertEqual(leftover, []) 476 flist.clean() 477 478 479 def test_parse_no_add_on(self): 480 flist = cli_mock.create_file('host1\nhost2\nleft2') 481 sys.argv = ['atest', '--web', 'fooweb', '--parse', '-g', 482 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 483 self.atest.parser.add_option('-M', '--mlist', type='string') 484 item_info = topic_common.item_parse_info(attribute_name='hosts', 485 filename_option='mlist') 486 (options, leftover) = self.atest.parse([item_info]) 487 self.assertEqualNoOrder(self.atest.hosts, 488 ['left2', 'host1', 'host2']) 489 490 self.assertEqual({'mlist': flist.name, 491 'web_server': 'fooweb', 492 'parse': True, 493 'parse_delim': '|', 494 'kill_on_failure': True, 495 'verbose': False, 496 'no_confirmation': False, 497 'debug': True}, options) 498 self.assertEqual(leftover, ['left1', 'left2']) 499 flist.clean() 500 501 502 def test_parse_add_on_first(self): 503 flist = cli_mock.create_file('host1\nhost2\nleft2') 504 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 505 sys.argv = ['atest', '-g', '--parse', '--ulist', ulist.name, 506 '-u', 'myuser,youruser', 507 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 508 self.atest.parser.add_option('-M', '--mlist', type='string') 509 self.atest.parser.add_option('-U', '--ulist', type='string') 510 self.atest.parser.add_option('-u', '--user', type='string') 511 host_info = topic_common.item_parse_info(attribute_name='hosts', 512 filename_option='mlist', 513 use_leftover=True) 514 user_info = topic_common.item_parse_info(attribute_name='users', 515 inline_option='user', 516 filename_option='ulist') 517 518 (options, leftover) = self.atest.parse([host_info, user_info]) 519 self.assertEqualNoOrder(self.atest.hosts, 520 ['left1', 'left2', 'host1', 'host2']) 521 self.assertEqualNoOrder(self.atest.users, 522 ['user1', 'user2', 'user3', 523 'myuser', 'youruser']) 524 525 self.assertEqual({'mlist': flist.name, 526 'ulist': ulist.name, 527 'user': 'myuser,youruser', 528 'web_server': None, 529 'parse': True, 530 'parse_delim': '|', 531 'kill_on_failure': True, 532 'verbose': False, 533 'no_confirmation': False, 534 'debug': True}, options) 535 self.assertEqual(leftover, []) 536 flist.clean() 537 ulist.clean() 538 539 540 def test_parse_add_on_second(self): 541 flist = cli_mock.create_file('host1\nhost2\nleft2') 542 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 543 sys.argv = ['atest', '-g', '--parse', '-U', ulist.name, 544 '-u', 'myuser,youruser', 545 '--kill-on-failure', 'left1', 'left2', '-M', flist.name] 546 self.atest.parser.add_option('-M', '--mlist', type='string') 547 self.atest.parser.add_option('-U', '--ulist', type='string') 548 self.atest.parser.add_option('-u', '--user', type='string') 549 host_info = topic_common.item_parse_info(attribute_name='hosts', 550 filename_option='mlist', 551 use_leftover=True) 552 user_info = topic_common.item_parse_info(attribute_name='users', 553 inline_option='user', 554 filename_option='ulist') 555 (options, leftover) = self.atest.parse([host_info, user_info]) 556 557 self.assertEqualNoOrder(self.atest.hosts, 558 ['left1', 'left2', 'host1', 'host2']) 559 self.assertEqualNoOrder(self.atest.users, 560 ['user1', 'user2', 'user3', 561 'myuser', 'youruser']) 562 563 self.assertEqual({'mlist': flist.name, 564 'ulist': ulist.name, 565 'user': 'myuser,youruser', 566 'web_server': None, 567 'parse': True, 568 'parse_delim': '|', 569 'kill_on_failure': True, 570 'verbose': False, 571 'no_confirmation': False, 572 'debug': True}, options) 573 self.assertEqual(leftover, []) 574 flist.clean() 575 ulist.clean() 576 577 578 def test_parse_all_opts(self): 579 flist = cli_mock.create_file('host1\nhost2\nleft2') 580 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 581 sys.argv = ['atest', '-g', '--parse', '--ulist', ulist.name, 582 '-u', 'myuser,youruser', 583 '--kill-on-failure', '-M', flist.name, 'left1', 'left2'] 584 self.atest.parser.add_option('-M', '--mlist', type='string') 585 self.atest.parser.add_option('-U', '--ulist', type='string') 586 self.atest.parser.add_option('-u', '--user', type='string') 587 host_info = topic_common.item_parse_info(attribute_name='hosts', 588 filename_option='mlist', 589 use_leftover=True) 590 user_info = topic_common.item_parse_info(attribute_name='users', 591 inline_option='user', 592 filename_option='ulist') 593 (options, leftover) = self.atest.parse([host_info, user_info]) 594 self.assertEqualNoOrder(self.atest.hosts, 595 ['left1', 'left2', 'host1', 'host2']) 596 self.assertEqualNoOrder(self.atest.users, 597 ['user1', 'user2', 'user3', 598 'myuser', 'youruser']) 599 600 self.assertEqual({'mlist': flist.name, 601 'ulist': ulist.name, 602 'user': 'myuser,youruser', 603 'web_server': None, 604 'parse': True, 605 'parse_delim': '|', 606 'kill_on_failure': True, 607 'verbose': False, 608 'no_confirmation': False, 609 'debug': True}, options) 610 self.assertEqual(leftover, []) 611 flist.clean() 612 ulist.clean() 613 614 615 def test_parse_no_add_on_2(self): 616 flist = cli_mock.create_file('host1\nhost2\nleft2') 617 ulist = cli_mock.create_file('user1\nuser2\nuser3\n') 618 sys.argv = ['atest', '-U', ulist.name, 619 '--kill-on-failure', '-M', flist.name] 620 self.atest.parser.add_option('-M', '--mlist', type='string') 621 self.atest.parser.add_option('-U', '--ulist', type='string') 622 self.atest.parser.add_option('-u', '--user', type='string') 623 host_info = topic_common.item_parse_info(attribute_name='hosts', 624 filename_option='mlist', 625 use_leftover=True) 626 user_info = topic_common.item_parse_info(attribute_name='users', 627 inline_option='user', 628 filename_option='ulist') 629 (options, leftover) = self.atest.parse([host_info, user_info]) 630 self.assertEqualNoOrder(self.atest.hosts, 631 ['left2', 'host1', 'host2']) 632 self.assertEqualNoOrder(self.atest.users, 633 ['user1', 'user2', 'user3']) 634 635 self.assertEqual({'mlist': flist.name, 636 'ulist': ulist.name, 637 'user': None, 638 'web_server': None, 639 'parse': False, 640 'parse_delim': '|', 641 'kill_on_failure': True, 642 'verbose': False, 643 'no_confirmation': False, 644 'debug': False}, options) 645 self.assertEqual(leftover, []) 646 flist.clean() 647 ulist.clean() 648 649 650 def test_parse_no_flist_add_on(self): 651 sys.argv = ['atest', '-g', '--parse', '-u', 'myuser,youruser', 652 '--kill-on-failure', 'left1', 'left2'] 653 self.atest.parser.add_option('-M', '--mlist', type='string') 654 self.atest.parser.add_option('-U', '--ulist', type='string') 655 self.atest.parser.add_option('-u', '--user', type='string') 656 host_info = topic_common.item_parse_info(attribute_name='hosts', 657 use_leftover=True) 658 user_info = topic_common.item_parse_info(attribute_name='users', 659 inline_option='user') 660 (options, leftover) = self.atest.parse([host_info, user_info]) 661 self.assertEqualNoOrder(self.atest.hosts, 662 ['left1', 'left2']) 663 self.assertEqualNoOrder(self.atest.users, 664 ['myuser', 'youruser']) 665 666 self.assertEqual({'mlist': None, 667 'ulist': None, 668 'user': 'myuser,youruser', 669 'web_server': None, 670 'parse': True, 671 'parse_delim': '|', 672 'kill_on_failure': True, 673 'verbose': False, 674 'no_confirmation': False, 675 'debug': True}, options) 676 self.assertEqual(leftover, []) 677 678 679 def test_parse_no_flist_no_add_on(self): 680 sys.argv = ['atest', '-u', 'myuser,youruser', '--kill-on-failure', 681 '-a', 'acl1,acl2'] 682 self.atest.parser.add_option('-u', '--user', type='string') 683 self.atest.parser.add_option('-a', '--acl', type='string') 684 acl_info = topic_common.item_parse_info(attribute_name='acls', 685 inline_option='acl') 686 user_info = topic_common.item_parse_info(attribute_name='users', 687 inline_option='user') 688 (options, leftover) = self.atest.parse([user_info, acl_info]) 689 self.assertEqualNoOrder(self.atest.acls, 690 ['acl1', 'acl2']) 691 self.assertEqualNoOrder(self.atest.users, 692 ['myuser', 'youruser']) 693 694 self.assertEqual({'user': 'myuser,youruser', 695 'acl': 'acl1,acl2', 696 'web_server': None, 697 'parse': False, 698 'parse_delim': '|', 699 'kill_on_failure': True, 700 'verbose': False, 701 'no_confirmation': False, 702 'debug': False}, options) 703 self.assertEqual(leftover, []) 704 705 706 def test_parse_req_items_ok(self): 707 sys.argv = ['atest', '-u', 'myuser,youruser'] 708 self.atest.parser.add_option('-u', '--user', type='string') 709 user_info = topic_common.item_parse_info(attribute_name='users', 710 inline_option='user') 711 (options, leftover) = self.atest.parse([user_info], 712 req_items='users') 713 self.assertEqualNoOrder(self.atest.users, 714 ['myuser', 'youruser']) 715 716 self.assertEqual({'user': 'myuser,youruser', 717 'web_server': None, 718 'parse': False, 719 'parse_delim': '|', 720 'kill_on_failure': False, 721 'verbose': False, 722 'no_confirmation': False, 723 'debug': False}, options) 724 self.assertEqual(leftover, []) 725 726 727 def test_parse_req_items_missing(self): 728 sys.argv = ['atest', '-u', 'myuser,youruser', '--kill-on-failure'] 729 self.atest.parser.add_option('-u', '--user', type='string') 730 acl_info = topic_common.item_parse_info(attribute_name='acls', 731 inline_option='acl') 732 user_info = topic_common.item_parse_info(attribute_name='users', 733 inline_option='user') 734 self.god.mock_io() 735 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 736 self.assertRaises(cli_mock.ExitException, 737 self.atest.parse, 738 [user_info, acl_info], 739 'acls') 740 self.assertEqualNoOrder(self.atest.users, 741 ['myuser', 'youruser']) 742 743 self.assertEqualNoOrder(self.atest.acls, []) 744 self.god.check_playback() 745 self.god.unmock_io() 746 747 748 def test_parse_bad_option(self): 749 sys.argv = ['atest', '--unknown'] 750 self.god.stub_function(self.atest.parser, 'error') 751 self.atest.parser.error.expect_call('no such option: --unknown').and_return(None) 752 self.atest.parse() 753 self.god.check_playback() 754 755 756 def test_parse_all_set(self): 757 sys.argv = ['atest', '--web', 'fooweb', '--parse', '--debug', 758 '--kill-on-failure', '--verbose', 'left1', 'left2', 759 '--parse-delim', '?'] 760 (options, leftover) = self.atest.parse() 761 self.assertEqual({'web_server': 'fooweb', 762 'parse': True, 763 'parse_delim': '?', 764 'kill_on_failure': True, 765 'verbose': True, 766 'no_confirmation': False, 767 'debug': True}, options) 768 self.assertEqual(leftover, ['left1', 'left2']) 769 770 771 def test_execute_rpc_bad_server(self): 772 self.atest.afe = rpc.afe_comm('http://does_not_exist') 773 self.god.mock_io() 774 rpc.afe_comm.run.expect_call('myop').and_raises(urllib2.URLError("<urlopen error (-2, 'Name or service not known')>")) 775 sys.exit.expect_call(1).and_raises(cli_mock.ExitException) 776 self.assertRaises(cli_mock.ExitException, 777 self.atest.execute_rpc, 'myop') 778 (output, err) = self.god.unmock_io() 779 self.god.check_playback() 780 self.assert_(err.find('http://does_not_exist') >= 0) 781 782 783 # 784 # Print Unit tests 785 # 786 def __test_print_fields(self, func, expected, **dargs): 787 if not dargs.has_key('items'): 788 dargs['items']=[{'hostname': 'h0', 789 'platform': 'p0', 790 'labels': [u'l0', u'l1'], 791 'locked': 1, 792 'id': 'id0', 793 'name': 'name0'}, 794 {'hostname': 'h1', 795 'platform': 'p1', 796 'labels': [u'l2', u'l3'], 797 'locked': 0, 798 'id': 'id1', 799 'name': 'name1'}] 800 self.god.mock_io() 801 func(**dargs) 802 (output, err) = self.god.unmock_io() 803 self.assertEqual(expected, output) 804 805 806 # 807 # Print fields Standard 808 # 809 def __test_print_fields_std(self, keys, expected): 810 self.__test_print_fields(self.atest.print_fields_std, 811 expected, keys=keys) 812 813 814 def test_print_fields_std_one_str(self): 815 self.__test_print_fields_std(['hostname'], 816 'Host: h0\n' 817 'Host: h1\n') 818 819 820 def test_print_fields_std_conv_bool(self): 821 """Make sure the conversion functions are called""" 822 self.__test_print_fields_std(['locked'], 823 'Locked: True\n' 824 'Locked: False\n') 825 826 827 def test_print_fields_std_conv_label(self): 828 """Make sure the conversion functions are called""" 829 self.__test_print_fields_std(['labels'], 830 'Labels: l0, l1\n' 831 'Labels: l2, l3\n') 832 833 834 def test_print_fields_std_all_fields(self): 835 """Make sure the conversion functions are called""" 836 self.__test_print_fields_std(['hostname', 'platform','locked'], 837 'Host: h0\n' 838 'Platform: p0\n' 839 'Locked: True\n' 840 'Host: h1\n' 841 'Platform: p1\n' 842 'Locked: False\n') 843 844 845 # 846 # Print fields parse 847 # 848 def __test_print_fields_parse(self, keys, expected): 849 self.__test_print_fields(self.atest.print_fields_parse, 850 expected, keys=keys) 851 852 853 def test_print_fields_parse_one_str(self): 854 self.__test_print_fields_parse(['hostname'], 855 'Host=h0\n' 856 'Host=h1\n') 857 858 859 def test_print_fields_parse_conv_bool(self): 860 self.__test_print_fields_parse(['locked'], 861 'Locked=True\n' 862 'Locked=False\n') 863 864 865 def test_print_fields_parse_conv_label(self): 866 self.__test_print_fields_parse(['labels'], 867 'Labels=l0, l1\n' 868 'Labels=l2, l3\n') 869 870 871 def test_print_fields_parse_all_fields(self): 872 self.__test_print_fields_parse(['hostname', 'platform', 'locked'], 873 'Host=h0|Platform=p0|' 874 'Locked=True\n' 875 'Host=h1|Platform=p1|' 876 'Locked=False\n') 877 878 879 # 880 # Print table standard 881 # 882 def __test_print_table_std(self, keys, expected): 883 self.__test_print_fields(self.atest.print_table_std, 884 expected, keys_header=keys) 885 886 887 def test_print_table_std_all_fields(self): 888 self.__test_print_table_std(['hostname', 'platform','locked'], 889 'Host Platform Locked\n' 890 'h0 p0 True\n' 891 'h1 p1 False\n') 892 893 # TODO JME - add long fields tests 894 895 896 # 897 # Print table parse 898 # 899 def __test_print_table_parse(self, keys, expected): 900 self.__test_print_fields(self.atest.print_table_parse, 901 expected, keys_header=keys) 902 903 904 def test_print_table_parse_all_fields(self): 905 self.__test_print_table_parse(['hostname', 'platform', 906 'locked'], 907 'Host=h0|Platform=p0|Locked=True\n' 908 'Host=h1|Platform=p1|Locked=False\n') 909 910 911 def test_print_table_parse_all_fields_2(self): 912 self.atest.parse_delim = '?' 913 self.__test_print_table_parse(['hostname', 'platform', 914 'locked'], 915 'Host=h0?Platform=p0?Locked=True\n' 916 'Host=h1?Platform=p1?Locked=False\n') 917 918 919 def test_print_table_parse_empty_fields(self): 920 self.__test_print_fields(self.atest.print_table_parse, 921 'Host=h0|Platform=p0\n' 922 'Host=h1|Platform=p1|Labels=l2, l3\n', 923 items=[{'hostname': 'h0', 924 'platform': 'p0', 925 'labels': [], 926 'locked': 1, 927 'id': 'id0', 928 'name': 'name0'}, 929 {'hostname': 'h1', 930 'platform': 'p1', 931 'labels': [u'l2', u'l3'], 932 'locked': 0, 933 'id': 'id1', 934 'name': 'name1'}], 935 keys_header=['hostname', 'platform', 936 'labels']) 937 938 939 # 940 # Print mix table standard 941 # 942 def __test_print_mix_table_std(self, keys_header, sublist_keys, 943 expected): 944 self.__test_print_fields(self.atest.print_table_std, 945 expected, 946 keys_header=keys_header, 947 sublist_keys=sublist_keys) 948 949 950 def test_print_mix_table(self): 951 self.__test_print_mix_table_std(['name', 'hostname'], [], 952 'Name Host\n' 953 'name0 h0\n' 954 'name1 h1\n') 955 956 957 def test_print_mix_table_sublist(self): 958 self.__test_print_mix_table_std(['name', 'hostname'], ['labels'], 959 'Name Host\n' 960 'name0 h0\n' 961 'Labels: \n' 962 '\tl0, l1\n\n\n' 963 'name1 h1\n' 964 'Labels: \n' 965 '\tl2, l3\n\n\n') 966 967 968 # 969 # Print by ID standard 970 # 971 def __test_print_by_ids_std(self, expected): 972 self.__test_print_fields(self.atest.print_by_ids_std, 973 expected) 974 975 976 def test_print_by_ids_std_all_fields(self): 977 self.__test_print_by_ids_std('Id Name\n' 978 'id0 name0\n' 979 'id1 name1\n') 980 981 982 # 983 # Print by ID parse 984 # 985 def __test_print_by_ids_parse(self, expected): 986 self.__test_print_fields(self.atest.print_by_ids_parse, 987 expected) 988 989 990 def test_print_by_ids_parse_all_fields(self): 991 self.__test_print_by_ids_parse('Id=id0|Name=name0|' 992 'Id=id1|Name=name1\n') 993 994 995 if __name__ == '__main__': 996 unittest.main() 997