def test_wrong_class_statement(): with pytest.raises(TokenParseError): compileScenic('constructor Foo(object):\n' ' pass') with pytest.raises(TokenParseError): compileScenic('import collections\n' 'constructor Foo(collections.defaultdict):\n' ' pass')
def test_dump_python(): scenic.syntax.translator.dumpTranslatedPython = True compileScenic('ego = Object') scenic.syntax.translator.dumpTranslatedPython = False scenic.syntax.translator.dumpFinalAST = True compileScenic('ego = Object') scenic.syntax.translator.dumpFinalAST = False
def test_veneer_activation(): checkVeneerIsInactive() compileScenic('ego = Object') checkVeneerIsInactive() with pytest.raises(Exception): compileScenic('raise Exception') checkVeneerIsInactive()
def test_illegal_binary_operators(op): # Basic usage with pytest.raises(TokenParseError): compileScenic(f'x = 3 {op} 2') # Augmented assignments with pytest.raises(TokenParseError): compileScenic(f'x {op}= 4')
def test_bug_template_sanity(template, tmpdir): """Check that the program templates above have the correct form.""" line, program = template program = program.format(bug='') # Check that they compile when not injecting a bug print(f'TRYING PROGRAM:\n{program}') compileScenic(program)
def test_noninterference(): scenario = compileScenic('ego = Object') assert len(scenario.objects) == 1 ego1 = scenario.egoObject for i in range(5): scene, iterations = scenario.generate(maxIterations=1) scenario = compileScenic('ego = Object') assert len(scenario.objects) == 1 ego2 = scenario.egoObject assert ego1 is not ego2
def test_noninterference(runLocally): code = ("import scenic.simulators.webots.road.world as world\n" "world.worldPath = 'richmond.wbt'\n" "from scenic.simulators.webots.road.road_model import *\n" "ego = Pedestrian") with runLocally(): scenario = compileScenic(code) assert len(scenario.objects) == 1 roads1 = scenario.workspace.roads scenario = compileScenic(code) assert len(scenario.objects) == 1 roads2 = scenario.workspace.roads assert len(roads1) == len(roads2)
def test_wrong_class_statement(): with pytest.raises(ASTParseError): compileScenic( 'class Foo(Point):\n' ' pass' ) with pytest.raises(ASTParseError): compileScenic( 'constructor Foo:\n' ' pass\n' 'class Bar(Foo):\n' ' pass' )
def test_polygonal_empty_intersection(): scenario = compileScenic( 'r1 = PolygonalRegion([0@0, 10@0, 10@10, 0@10])\n' 'ego = Object at -10@0, facing (-90, 0) deg, with viewAngle 60 deg\n' 'Object in visible r1, with requireVisible False') for i in range(30): scenario.generate(maxIterations=1000)
def test_unmatched_parentheses(): with pytest.raises(TokenParseError): compileScenic('(') with pytest.raises(TokenParseError): compileScenic('x = (3 + 4') with pytest.raises(TokenParseError): compileScenic(')') with pytest.raises(TokenParseError): compileScenic('x = (4 - 2))')
def test_python_class(): scenario = compileScenic('class Foo(object):\n' ' def __init__(self, x):\n' ' self.x = x\n' 'ego = Object with width Foo(4).x') scene, iterations = scenario.generate(maxIterations=1) ego = scene.egoObject assert ego.width == 4
def test_inherit_requirements(runLocally): with runLocally(): scenario = compileScenic('import helper3\n' 'ego = Object') assert len(scenario.requirements) == 1 for i in range(50): scene, iterations = scenario.generate(maxIterations=100) assert len(scene.objects) == 2 constrainedObj = scene.objects[1] assert constrainedObj.position.x > 0
def test_ego_second(): scenario = compileScenic('Object\n' 'ego = Object at 0 @ -5') assert len(scenario.objects) == 2 obj = scenario.objects[0] assert obj is scenario.egoObject scene, iterations = scenario.generate(maxIterations=1) assert len(scene.objects) == 2 obj = scene.objects[0] assert obj is scene.egoObject
def test_property_simple(): scenario = compileScenic('class Foo:\n' ' position: 3 @ 9\n' ' flubber: -12\n' 'ego = Foo') scene, iterations = scenario.generate(maxIterations=1) ego = scene.egoObject assert type(ego).__name__ == 'Foo' assert tuple(ego.position) == (3, 9) assert ego.flubber == -12
def test_property_inheritance(): scenario = compileScenic('class Foo:\n' ' flubber: -12\n' 'class Bar(Foo):\n' ' flubber: 7\n' 'ego = Bar') scene, iterations = scenario.generate(maxIterations=1) ego = scene.egoObject assert type(ego).__name__ == 'Bar' assert ego.flubber == 7
def test_malformed_soft_requirement(): with pytest.raises(TokenParseError): compileScenic('require[x] 3 == 3') with pytest.raises(TokenParseError): compileScenic('require[1+x] 3 == 3') with pytest.raises(TokenParseError): compileScenic('require[] 3 == 3')
def test_minimal(): scenario = compileScenic('ego = Object') assert len(scenario.objects) == 1 obj = scenario.objects[0] assert type(obj) is Object assert obj is scenario.egoObject assert len(scenario.params) == 0 assert len(scenario.requirements) == 0 scene, iterations = scenario.generate(maxIterations=1) assert len(scene.objects) == 1 obj = scene.objects[0] assert type(obj) is Object assert obj is scene.egoObject assert len(scene.params) == 0
def test_illegal_operators(): # Unary operators with pytest.raises(TokenParseError): compileScenic('x = ~2') # Binary operators binops = ('<<', '>>', '|', '&', '^', '//') for op in binops: try: compileScenic(f'x = 3 {op} 2') pytest.fail(f'Illegal operator {op} did not raise ParseError') except TokenParseError: pass # Augmented assignments for op in binops: try: compileScenic(f'x {op}= 4') pytest.fail( f'Illegal augmented assigment {op}= did not raise ParseError') except TokenParseError: pass
def test_malformed_range(): with pytest.raises(ASTParseError): compileScenic('x = (4,)') with pytest.raises(ASTParseError): compileScenic('x = (4, 5, 6)')
def test_malformed_constructor(): with pytest.raises(TokenParseError): compileScenic('constructor Foo\n' ' pass') with pytest.raises(TokenParseError): compileScenic('constructor Foo(Bar:\n' ' pass')
def test_constructor_undefined_superclass(): with pytest.raises(TokenParseError): compileScenic('constructor Foo(Bar):\n' ' pass')
def test_constructor_python_superclass(): with pytest.raises(TokenParseError): compileScenic('constructor Foo(object):\n' ' pass')
def test_illegal_constructor_superclass(): for name in badNames: with pytest.raises(TokenParseError): compileScenic(f'constructor Foo({name}):\n' ' pass')
def test_illegal_constructor_name(): for name in badNames: with pytest.raises(TokenParseError): compileScenic(f'constructor {name}:\n' ' pass')
def test_bug_template_sanity(tmpdir): """Check that the program templates above have the correct form.""" # Check that they compile when not injecting a bug for program, line in programsWithBug(''): print(f'TRYING PROGRAM:\n{program}') compileScenic(program)
def test_multiple_requirements(): with pytest.raises(ASTParseError): compileScenic('require True, True') with pytest.raises(ASTParseError): compileScenic('require True, True, True')
def test_extra_infix_package(): """Packaged (3+-ary) infix operator with too many arguments.""" with pytest.raises(ASTParseError): compileScenic('x = 4 at 12 by 17') with pytest.raises(ASTParseError): compileScenic('x = 4 offset along 12 by 17 by 19')
def test_incomplete_infix_package(): """Packaged (3+-ary) infix operator with too few arguments.""" with pytest.raises(ASTParseError): compileScenic('x = 4 offset along 12')
def test_incomplete_infix_operator(): """Binary infix operator with too few arguments.""" with pytest.raises(PythonParseError): compileScenic('x = 3 @') with pytest.raises(PythonParseError): compileScenic('x = 3 at')
def test_incomplete_multiline_string(): with pytest.raises(TokenParseError): compileScenic('"""foobar') with pytest.raises(TokenParseError): compileScenic('x = """foobar\n' 'wog\n')