def test_loop_navigation_properties(): # pylint: disable=too-many-statements ''' Tests the start_expr, stop_expr, step_expr and loop_body setter and getter properties. ''' loop = Loop() # Properties return an error if the node is incomplete error_str = ("Loop is incomplete. It should have exactly 4 " "children, but found") with pytest.raises(InternalError) as err: _ = loop.start_expr assert error_str in str(err.value) loop.addchild(Literal("start", INTEGER_SINGLE_TYPE)) loop.addchild(Literal("stop", INTEGER_SINGLE_TYPE)) loop.addchild(Literal("step", INTEGER_SINGLE_TYPE)) # If it's not fully complete, it still returns an error with pytest.raises(InternalError) as err: _ = loop.start_expr assert error_str in str(err.value) with pytest.raises(InternalError) as err: _ = loop.stop_expr assert error_str in str(err.value) with pytest.raises(InternalError) as err: _ = loop.step_expr assert error_str in str(err.value) with pytest.raises(InternalError) as err: _ = loop.loop_body assert error_str in str(err.value) with pytest.raises(InternalError) as err: loop.start_expr = Literal("invalid", INTEGER_SINGLE_TYPE) assert error_str in str(err.value) with pytest.raises(InternalError) as err: loop.stop_expr = Literal("invalid", INTEGER_SINGLE_TYPE) assert error_str in str(err.value) with pytest.raises(InternalError) as err: loop.step_expr = Literal("invalid", INTEGER_SINGLE_TYPE) assert error_str in str(err.value) # Check that Getters properties work loop.addchild(Schedule(parent=loop)) loop.loop_body.addchild(Return(parent=loop.loop_body)) assert loop.start_expr.value == "start" assert loop.stop_expr.value == "stop" assert loop.step_expr.value == "step" assert isinstance(loop.loop_body[0], Return) # Test Setters loop.start_expr = Literal("newstart", INTEGER_SINGLE_TYPE) loop.stop_expr = Literal("newstop", INTEGER_SINGLE_TYPE) loop.step_expr = Literal("newstep", INTEGER_SINGLE_TYPE) assert loop.start_expr.value == "newstart" assert loop.stop_expr.value == "newstop" assert loop.step_expr.value == "newstep"
def test_regiontrans_wrong_children(): ''' Check that the validate method raises the expected error if passed the wrong children of a Node. (e.g. those representing the bounds of a Loop.) ''' # RegionTrans is abstract so use a concrete sub-class rtrans = ACCParallelTrans() # Construct a valid Loop in the PSyIR parent = Loop(parent=None) parent.addchild(Literal("1", INTEGER_TYPE, parent)) parent.addchild(Literal("10", INTEGER_TYPE, parent)) parent.addchild(Literal("1", INTEGER_TYPE, parent)) parent.addchild(Schedule(parent=parent)) with pytest.raises(TransformationError) as err: RegionTrans.validate(rtrans, parent.children) assert ("Cannot apply a transformation to multiple nodes when one or more " "is a Schedule" in str(err.value))
def test_loop_children_validation(): '''Test that children added to Loop are validated. Loop accepts 3 DataNodes and a Schedule. ''' loop = Loop() datanode1 = Literal("1", INTEGER_SINGLE_TYPE) datanode2 = Literal("2", INTEGER_SINGLE_TYPE) datanode3 = Literal("3", INTEGER_SINGLE_TYPE) schedule = Schedule(parent=loop) # First child with pytest.raises(GenerationError) as excinfo: loop.addchild(schedule) assert ("Item 'Schedule' can't be child 0 of 'Loop'. The valid format is: " "'DataNode, DataNode, DataNode, Schedule'." in str(excinfo.value)) loop.addchild(datanode1) # Second child with pytest.raises(GenerationError) as excinfo: loop.addchild(schedule) assert ("Item 'Schedule' can't be child 1 of 'Loop'. The valid format is: " "'DataNode, DataNode, DataNode, Schedule'." in str(excinfo.value)) loop.addchild(datanode2) # Third child with pytest.raises(GenerationError) as excinfo: loop.addchild(schedule) assert ("Item 'Schedule' can't be child 2 of 'Loop'. The valid format is: " "'DataNode, DataNode, DataNode, Schedule'." in str(excinfo.value)) loop.addchild(datanode3) # Fourth child with pytest.raises(GenerationError) as excinfo: loop.addchild(datanode1) assert ("Item 'Literal' can't be child 3 of 'Loop'. The valid format is: " "'DataNode, DataNode, DataNode, Schedule'." in str(excinfo.value)) loop.addchild(schedule) # Additional children with pytest.raises(GenerationError) as excinfo: loop.addchild(schedule) assert ("Item 'Schedule' can't be child 4 of 'Loop'. The valid format is: " "'DataNode, DataNode, DataNode, Schedule'." in str(excinfo.value))
def test_fusetrans_error_incomplete(): ''' Check that we reject attempts to fuse loops which are incomplete. ''' sch = Schedule() loop1 = Loop(variable=DataSymbol("i", INTEGER_TYPE)) loop2 = Loop(variable=DataSymbol("j", INTEGER_TYPE)) sch.addchild(loop1) sch.addchild(loop2) fuse = LoopFuseTrans() # Check first loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert ("Error in LoopFuseTrans transformation. The target loop must have " "four children but found: []" in str(err.value)) loop1.addchild(Literal("start", INTEGER_TYPE)) loop1.addchild(Literal("stop", INTEGER_TYPE)) loop1.addchild(Literal("step", INTEGER_TYPE)) loop1.addchild(Schedule()) loop1.loop_body.addchild(Return()) # Check second loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert ("Error in LoopFuseTrans transformation. The target loop must have " "four children but found: []" in str(err.value)) loop2.addchild(Literal("start", INTEGER_TYPE)) loop2.addchild(Literal("stop", INTEGER_TYPE)) loop2.addchild(Literal("step", INTEGER_TYPE)) loop2.addchild(Schedule()) loop2.loop_body.addchild(Return()) # Validation should now pass fuse.validate(loop1, loop2)
def test_fusetrans_error_not_same_parent(): ''' Check that we reject attempts to fuse loops which don't share the same parent ''' from psyclone.transformations import LoopFuseTrans sch1 = Schedule() sch2 = Schedule() loop1 = Loop(variable=DataSymbol("i", INTEGER_TYPE), parent=sch1) loop2 = Loop(variable=DataSymbol("j", INTEGER_TYPE), parent=sch2) sch1.addchild(loop1) sch2.addchild(loop2) loop1.addchild(Literal("1", INTEGER_TYPE, parent=loop1)) # start loop1.addchild(Literal("10", INTEGER_TYPE, parent=loop1)) # stop loop1.addchild(Literal("1", INTEGER_TYPE, parent=loop1)) # step loop1.addchild(Schedule(parent=loop1)) # loop body loop2.addchild(Literal("1", INTEGER_TYPE, parent=loop2)) # start loop2.addchild(Literal("10", INTEGER_TYPE, parent=loop2)) # stop loop2.addchild(Literal("1", INTEGER_TYPE, parent=loop2)) # step loop2.addchild(Schedule(parent=loop2)) # loop body fuse = LoopFuseTrans() # Try to fuse loops with different parents with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert ("Error in LoopFuseTrans transformation. Loops do not have the " "same parent" in str(err.value))
def test_fusetrans_error_incomplete(): ''' Check that we reject attempts to fuse loops which are incomplete. ''' from psyclone.psyir.nodes import Return from psyclone.transformations import LoopFuseTrans sch = Schedule() loop1 = Loop(variable=DataSymbol("i", INTEGER_TYPE), parent=sch) loop2 = Loop(variable=DataSymbol("j", INTEGER_TYPE), parent=sch) sch.addchild(loop1) sch.addchild(loop2) fuse = LoopFuseTrans() # Check first loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. The first loop does not have " \ "4 children." in str(err.value) loop1.addchild(Literal("start", INTEGER_TYPE, parent=loop1)) loop1.addchild(Literal("stop", INTEGER_TYPE, parent=loop1)) loop1.addchild(Literal("step", INTEGER_TYPE, parent=loop1)) loop1.addchild(Schedule(parent=loop1)) loop1.loop_body.addchild(Return(parent=loop1.loop_body)) # Check second loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. The second loop does not have " \ "4 children." in str(err.value) loop2.addchild(Literal("start", INTEGER_TYPE, parent=loop2)) loop2.addchild(Literal("stop", INTEGER_TYPE, parent=loop2)) loop2.addchild(Literal("step", INTEGER_TYPE, parent=loop2)) loop2.addchild(Schedule(parent=loop2)) loop2.loop_body.addchild(Return(parent=loop2.loop_body)) # Validation should now pass fuse.validate(loop1, loop2)