Home | History | Annotate | Download | only in cli
      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