def test_ast_raises_type_mismatch_bitwise(self): parser_ = parser.Parser() statement = parser_.parse('symbol << 1', self.context) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': 1.1}) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': 'string'}) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': True}) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': inf}) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': nan}) self.assertEqual(statement.evaluate({'symbol': 1}), 2) with self.assertRaises(errors.EvaluationError): parser_.parse('symbol << 1.1', self.context) with self.assertRaises(errors.EvaluationError): parser_.parse('symbol << "string"', self.context) with self.assertRaises(errors.EvaluationError): parser_.parse('symbol << true', self.context) with self.assertRaises(errors.EvaluationError): parser_.parse('inf << 1', self.context) with self.assertRaises(errors.EvaluationError): parser_.parse('nan << 1', self.context)
def test_ast_evaluates_logic(self): parser_ = parser.Parser() self.assertTrue(parser_.parse('true and true', self.context).evaluate(None)) self.assertFalse(parser_.parse('true and false', self.context).evaluate(None)) self.assertTrue(parser_.parse('true or false', self.context).evaluate(None)) self.assertFalse(parser_.parse('false or false', self.context).evaluate(None))
def test_ast_raises_type_mismatch_arithmetic_comparisons(self): parser_ = parser.Parser() statement = parser_.parse('symbol < 1', self.context) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': 'string'}) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': True}) self.assertTrue(statement.evaluate({'symbol': 0.0}))
def test_ast_reduces_array_literals(self): parser_ = parser.Parser() statement = parser_.parse('[1, 2, 1 + 2]', self.context) self.assertIsInstance(statement.expression, ast.ArrayExpression) self.assertTrue(statement.expression.is_reduced) self.assertEqual(statement.evaluate(None), (1, 2, 3)) statement = parser_.parse('[foobar]', self.context) self.assertIsInstance(statement.expression, ast.ArrayExpression) self.assertFalse(statement.expression.is_reduced)
def test_ast_evaluates_unary_not(self): parser_ = parser.Parser() statement = parser_.parse('not false', self.context) self.assertTrue(statement.evaluate(None)) statement = parser_.parse('not true', self.context) self.assertFalse(statement.evaluate(None)) statement = parser_.parse('true and not false', self.context) self.assertTrue(statement.evaluate(None)) statement = parser_.parse('false and not true', self.context) self.assertFalse(statement.evaluate(None))
class ParserTestsBase(unittest.TestCase): _parser = parser.Parser() context = engine.Context() def _parse(self, string, context): return self._parser.parse(string, self.context) def assertStatementType(self, string, ast_expression): statement = self._parse(string, self.context) self.assertIsInstance(statement, ast.Statement, msg='the parser did not return a statement') expression = statement.expression self.assertIsInstance(expression, ast_expression, msg='the statement expression is not the correct expression type') return statement
def test_ast_raises_type_mismatch_fuzzy_comparisons(self): parser_ = parser.Parser() statement = parser_.parse('symbol =~ "string"', self.context) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': 1.1}) with self.assertRaises(errors.EvaluationError): statement.evaluate({'symbol': True}) self.assertTrue(statement.evaluate({'symbol': 'string'})) with self.assertRaises(errors.EvaluationError): parser_.parse('"string" =~ 1', self.context) with self.assertRaises(errors.EvaluationError): parser_.parse('"string" =~ true', self.context)
def test_ast_reduces_arithmetic(self): thing = {'one': 1, 'two': 2} parser_ = parser.Parser() statement = parser_.parse('1 + 2', self.context) self.assertIsInstance(statement.expression, ast.FloatExpression) self.assertEqual(statement.evaluate(None), 3) statement = parser_.parse('one + 2', self.context) self.assertIsInstance(statement.expression, ast.ArithmeticExpression) self.assertEqual(statement.evaluate(thing), 3) statement = parser_.parse('1 + two', self.context) self.assertIsInstance(statement.expression, ast.ArithmeticExpression) self.assertEqual(statement.evaluate(thing), 3)
def test_ast_type_hints(self): parser_ = parser.Parser() cases = ( # type, type_is, type_is_not ('symbol << 1', ast.DataType.FLOAT, ast.DataType.STRING), ('symbol + 1', ast.DataType.FLOAT, ast.DataType.STRING), ('symbol > 1', ast.DataType.FLOAT, ast.DataType.STRING), ('symbol =~ "foo"', ast.DataType.STRING, ast.DataType.FLOAT), ) for case, type_is, type_is_not in cases: parser_.parse(case, self.context) context = engine.Context(type_resolver=engine.type_resolver_from_dict({'symbol': type_is})) parser_.parse(case, context) context = engine.Context(type_resolver=engine.type_resolver_from_dict({'symbol': type_is_not})) with self.assertRaises(errors.EvaluationError): parser_.parse(case, context)
def test_ast_evaluates_unary_uminus(self): parser_ = parser.Parser() statement = parser_.parse('-(2 * 5)', self.context) self.assertEqual(statement.evaluate(None), -10)
def test_ast_evaluates_string_comparisons(self): parser_ = parser.Parser() statement = parser_.parse('name == "Alice"', self.context) self.assertTrue(statement.evaluate(self.thing)) statement = parser_.parse('name == "calie"', self.context) self.assertFalse(statement.evaluate(self.thing))
def test_ast_evaluates_fuzzy_comparisons(self): parser_ = parser.Parser() statement = parser_.parse('name =~ ".lic."', self.context) self.assertTrue(statement.evaluate(self.thing)) statement = parser_.parse('name =~~ "lic"', self.context) self.assertTrue(statement.evaluate(self.thing))
def test_ast_evaluates_arithmetic_comparisons(self): parser_ = parser.Parser() statement = parser_.parse('age >= 21', self.context) self.assertTrue(statement.evaluate(self.thing)) statement = parser_.parse('age > 100', self.context) self.assertFalse(statement.evaluate(self.thing))
def test_ast_reduces_ternary(self): parser_ = parser.Parser() statement = parser_.parse('true ? 1 : 0', self.context) self.assertIsInstance(statement.expression, ast.FloatExpression) self.assertEqual(statement.evaluate(None), 1)
def test_ast_reduces_bitwise(self): parser_ = parser.Parser() statement = parser_.parse('1 << 2', self.context) self.assertIsInstance(statement.expression, ast.FloatExpression) self.assertEqual(statement.evaluate(None), 4)
def test_ast_reduces_attributes(self): parser_ = parser.Parser() statement = parser_.parse('"foobar".length', self.context) self.assertIsInstance(statement.expression, ast.FloatExpression) self.assertEqual(statement.evaluate(None), 6)