#!python # vim: encoding=latin1 ts=8 sts=4 et si sw=4 ft=python """ Test ranges module on pool of integer values """ __author__ = 'Tobias Herp ' VERSION = '.'.join(map(str, (0, 1, ))) import unittest from ranges import * class Testcase_data_sanity(unittest.TestCase): def test_enum_value(self): "ENUM has expected value" self.assertEqual(ENUM, 1) def test_range_value(self): "RANGE has expected value" self.assertEqual(RANGE, 2) def test_normality(self): """\ NORMAL_TOKEN values for each expression type and NON_NUMBERS """ for a in (1, 2): # ENUMeration or RANGE expressions for tok in NON_NUMBERS: # to, or... NORMAL_TOKEN[a][tok] def test_keywords(self): "uses the expected keywords" self.assertEqual(KEYWORDS, ('or', 'to')) POOL = tuple(range(1, 11)) # 1 .. 10 class Tokenizer(unittest.TestCase): known_tokens = ( ('1 to 5', ('1', ' ', 'to', ' ', '5')), ('1; 2; 3', # input expression ('1', ';', ' ', '2', ';', ' ', '3',)), ) def test_tokenizer(self): for expr, predicted in self.known_tokens: tokens = tuple(tokenize(expr)) self.assertEqual(tokens, predicted) class Testcase_working_semicolon(unittest.TestCase): """ Testcase for correct expressions without commas """ known_values = ( ('1; 2; 3', # input expression (1, 2, 3,), # result set (based on POOL) 'x in (1,2,3,)'), # used Python expression ('1 or 2; 3', (1, 2, 3,), 'x in (1,2,3,)'), ('1 or 2 or 3', (1, 2, 3,), 'x in (1,2,3,)'), ('1;2;5;3', (1, 2, 3, 5,), 'x in (1,2,5,3,)'), # no sorting ('1 to 5', (1, 2, 3, 4, 5,), '1 <= x <= 5'), ('1; 5', (1, 5,), 'x in (1,5,)'), # depending on the input expression, # the generated Python expression has parentheses: ('[1; 5]', (1, 2, 3, 4, 5,), '(1 <= x <= 5)'), # because of par. in input ('[1; 5)', (1, 2, 3, 4,), '(1 <= x < 5)'), ('(1; 5)', (2, 3, 4,), '(1 < x < 5)'), ('[1; 3] or (6; 9)', (1, 2, 3, 7, 8,), '(1 <= x <= 3) or (6 < x < 9)'), ('[3;]', (3, 4, 5, 6, 7, 8, 9, 10,), '(3 <= x)'), ('(3;)', (4, 5, 6, 7, 8, 9, 10,), '(3 < x)'), # "(3;)" is a sub-expression to the root; # simple values are collected and pushed up: ('(3;) or 1', (1, 4, 5, 6, 7, 8, 9, 10,), 'x in (1,) or (3 < x)'), # single value pushed up ('(3;);1', (1, 4, 5, 6, 7, 8, 9, 10,), 'x in (1,) or (3 < x)'), # single value pushed up ('(3;);1;5', (1, 4, 5, 6, 7, 8, 9, 10,), 'x in (1,5,) or (3 < x)'), # single value pushed up # "(1 or 5)" is a sub-expression and as such processed in order: ('(3;) or (1 or 5)', (1, 4, 5, 6, 7, 8, 9, 10,), '(3 < x) or (x in (1,5,))'), ('(3;); (1 or 5)', (1, 4, 5, 6, 7, 8, 9, 10,), '(3 < x) or (x in (1,5,))'), ) """ ) dummy = ( """ # not expected to work already, and not yet tested: tricky_values = ( ('1 to 3; 6', (1, 2, 3, 6,), '1 <= x <= 3 or x in (6,)'), ) def test_knownvalues(self): "filter functions yield predicted subsets" for expr, predicted, pyex in self.known_values: eo = make_expression(expr) res = filter(eo.filter_func(), POOL) self.assertEqual(res, predicted) def test_python_expressions(self): "Expression objects yield predicted Python expressions" for expr, predicted, pyex in self.known_values: eo = make_expression(expr) self.assertEqual(pyex, eo.python_expression()) empty_values = ( ('', # input expression POOL, # result set (based on POOL) '1'), # used Python expression ('()', POOL, '(1)'), ) def test_emptyvalues(self): "filter functions yield complete pool for empty expressions" for expr, predicted, pyex in self.empty_values: eo = make_expression(expr) res = filter(eo.filter_func(), POOL) self.assertEqual(res, predicted) def test_empty_python_expressions(self): "Empty expressions yield dummy Python expression" for expr, predicted, pyex in self.empty_values: eo = make_expression(expr) self.assertEqual(pyex, eo.python_expression()) # coughing during creation invalid_expressions_1 = ( ('(', None, # no normalized versions yet ParenthesesError), (')', None, # currently ProgrammingError; # should probably be ParenthesesError: ExpressionError), ) def test_invalid_input_raises_errors(self): "invalid expressions raise errors during creation" for expr, norm, error in self.invalid_expressions_1: self.assertRaises(error, make_expression, expr) invalid_expressions_2 = ( ('{1;2)', None, ParenthesesMismatch), ('{1 to 5}', # '{' implies ENUM, 'to' implies RANGE None, AmbiguityError), ) def test_invalid_input_raises_errors2(self): "invalid expressions raise errors during execution" for expr, norm, error in self.invalid_expressions_2: eo = make_expression(expr) self.assertRaises(error, eo.python_expression) if __name__ == '__main__': unittest.main()