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,
    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