Home | History | Annotate | Download | only in rh
      1 #!/usr/bin/python
      2 # -*- coding:utf-8 -*-
      3 # Copyright 2016 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 """Unittests for the shell module."""
     18 
     19 from __future__ import print_function
     20 
     21 import difflib
     22 import os
     23 import sys
     24 import unittest
     25 
     26 _path = os.path.realpath(__file__ + '/../..')
     27 if sys.path[0] != _path:
     28     sys.path.insert(0, _path)
     29 del _path
     30 
     31 import rh.shell
     32 
     33 
     34 class DiffTestCase(unittest.TestCase):
     35     """Helper that includes diff output when failing."""
     36 
     37     def setUp(self):
     38         self.differ = difflib.Differ()
     39 
     40     def _assertEqual(self, func, test_input, test_output, result):
     41         """Like assertEqual but with built in diff support."""
     42         diff = '\n'.join(list(self.differ.compare([test_output], [result])))
     43         msg = ('Expected %s to translate %r to %r, but got %r\n%s' %
     44                (func, test_input, test_output, result, diff))
     45         self.assertEqual(test_output, result, msg)
     46 
     47     def _testData(self, functor, tests, check_type=True):
     48         """Process a dict of test data."""
     49         for test_output, test_input in tests.iteritems():
     50             result = functor(test_input)
     51             self._assertEqual(functor.__name__, test_input, test_output, result)
     52 
     53             if check_type:
     54                 # Also make sure the result is a string, otherwise the %r
     55                 # output will include a "u" prefix and that is not good for
     56                 # logging.
     57                 self.assertEqual(type(test_output), str)
     58 
     59 
     60 class ShellQuoteTest(DiffTestCase):
     61     """Test the shell_quote & shell_unquote functions."""
     62 
     63     def testShellQuote(self):
     64         """Basic ShellQuote tests."""
     65         # Dict of expected output strings to input lists.
     66         tests_quote = {
     67             "''": '',
     68             'a': unicode('a'),
     69             "'a b c'": unicode('a b c'),
     70             "'a\tb'": 'a\tb',
     71             "'/a$file'": '/a$file',
     72             "'/a#file'": '/a#file',
     73             """'b"c'""": 'b"c',
     74             "'a@()b'": 'a@()b',
     75             'j%k': 'j%k',
     76             r'''"s'a\$va\\rs"''': r"s'a$va\rs",
     77             r'''"\\'\\\""''': r'''\'\"''',
     78             r'''"'\\\$"''': r"""'\$""",
     79         }
     80 
     81         # Expected input output specific to ShellUnquote.  This string cannot
     82         # be produced by ShellQuote but is still a valid bash escaped string.
     83         tests_unquote = {
     84             r'''\$''': r'''"\\$"''',
     85         }
     86 
     87         def aux(s):
     88             return rh.shell.shell_unquote(rh.shell.shell_quote(s))
     89 
     90         self._testData(rh.shell.shell_quote, tests_quote)
     91         self._testData(rh.shell.shell_unquote, tests_unquote)
     92 
     93         # Test that the operations are reversible.
     94         self._testData(aux, {k: k for k in tests_quote.values()}, False)
     95         self._testData(aux, {k: k for k in tests_quote.keys()}, False)
     96 
     97 
     98 class CmdToStrTest(DiffTestCase):
     99     """Test the cmd_to_str function."""
    100 
    101     def testCmdToStr(self):
    102         # Dict of expected output strings to input lists.
    103         tests = {
    104             r"a b": ['a', 'b'],
    105             r"'a b' c": ['a b', 'c'],
    106             r'''a "b'c"''': ['a', "b'c"],
    107             r'''a "/'\$b" 'a b c' "xy'z"''':
    108                 [unicode('a'), "/'$b", 'a b c', "xy'z"],
    109             '': [],
    110         }
    111         self._testData(rh.shell.cmd_to_str, tests)
    112 
    113 
    114 class BooleanShellTest(unittest.TestCase):
    115     """Test the boolean_shell_value function."""
    116 
    117     def testFull(self):
    118         """Verify nputs work as expected"""
    119         for v in (None,):
    120             self.assertTrue(rh.shell.boolean_shell_value(v, True))
    121             self.assertFalse(rh.shell.boolean_shell_value(v, False))
    122 
    123         for v in (1234, '', 'akldjsf', '"'):
    124             self.assertRaises(ValueError, rh.shell.boolean_shell_value, v, True)
    125 
    126         for v in ('yes', 'YES', 'YeS', 'y', 'Y', '1', 'true', 'True', 'TRUE',):
    127             self.assertTrue(rh.shell.boolean_shell_value(v, True))
    128             self.assertTrue(rh.shell.boolean_shell_value(v, False))
    129 
    130         for v in ('no', 'NO', 'nO', 'n', 'N', '0', 'false', 'False', 'FALSE',):
    131             self.assertFalse(rh.shell.boolean_shell_value(v, True))
    132             self.assertFalse(rh.shell.boolean_shell_value(v, False))
    133 
    134 
    135 if __name__ == '__main__':
    136     unittest.main()
    137