def get_contained_objects(obj): if isinstance(obj, list): return flatten(map(get_contained_objects, obj)) if obj in events_so_far: return [] else: events_so_far.add(obj) if isinstance(obj, SequenceObject): return get_those_and_contained_objects(obj.contained_objects) elif isinstance(obj, MapObject): return get_those_and_contained_objects(flatten(obj.mapping)) elif isinstance(obj, LibraryObject): return get_those_and_contained_objects(obj.arguments) elif isinstance(obj, BuiltinException): return get_those_and_contained_objects(obj.args) elif isinstance(obj, UserObject): return get_contained_objects(obj.get_init_call() or []) elif isinstance(obj, (FunctionCall, MethodCall, GeneratorObjectInvocation)): return get_those_and_contained_objects(obj.input.values()) elif isinstance(obj, GeneratorObject): if obj.is_activated(): return get_those_and_contained_objects(obj.args.values() + obj.calls) return [] elif isinstance(obj, SideEffect): return get_those_and_contained_objects(list(obj.affected_objects)) elif isinstance(obj, MethodCallContext): return get_those_and_contained_objects([obj.call, obj.user_object]) elif isinstance(obj, EqualAssertionLine): # Actual may be just a variable name, so just skip that. if isinstance(obj.actual, str): return get_those_and_contained_objects([obj.expected]) return get_those_and_contained_objects([obj.expected, obj.actual]) elif isinstance(obj, GeneratorAssertionLine): return get_contained_objects(obj.generator_call) elif isinstance(obj, RaisesAssertionLine): return get_those_and_contained_objects( [obj.call, obj.expected_exception]) elif isinstance(obj, Assign): if isinstance(obj.obj, SerializedObject): return get_those_and_contained_objects([obj.obj]) return [] elif isinstance(obj, ObjectAttributeReference): return get_those_and_contained_objects([obj.obj]) elif isinstance(obj, BindingChange): return get_those_and_contained_objects([obj.obj, obj.name]) elif isinstance( obj, (ImmutableObject, UnknownObject, CallToC, CommentLine, SkipTestLine, EqualAssertionStubLine, ModuleVariableReference)): return [] else: raise TypeError("Wrong argument to get_contained_objects: %s." % repr(obj))
def get_contained_objects(obj): if isinstance(obj, list): return flatten(map(get_contained_objects, obj)) if obj in events_so_far: return [] else: events_so_far.add(obj) if isinstance(obj, SequenceObject): return get_those_and_contained_objects(obj.contained_objects) elif isinstance(obj, MapObject): return get_those_and_contained_objects(flatten(obj.mapping)) elif isinstance(obj, LibraryObject): return get_those_and_contained_objects(obj.arguments) elif isinstance(obj, BuiltinException): return get_those_and_contained_objects(obj.args) elif isinstance(obj, UserObject): return get_contained_objects(obj.get_init_call() or []) elif isinstance(obj, (FunctionCall, MethodCall, GeneratorObjectInvocation)): return get_those_and_contained_objects(obj.input.values()) elif isinstance(obj, GeneratorObject): if obj.is_activated(): return get_those_and_contained_objects(obj.args.values() + obj.calls) return [] elif isinstance(obj, SideEffect): return get_those_and_contained_objects(list(obj.affected_objects)) elif isinstance(obj, MethodCallContext): return get_those_and_contained_objects([obj.call, obj.user_object]) elif isinstance(obj, EqualAssertionLine): # Actual may be just a variable name, so just skip that. if isinstance(obj.actual, str): return get_those_and_contained_objects([obj.expected]) return get_those_and_contained_objects([obj.expected, obj.actual]) elif isinstance(obj, GeneratorAssertionLine): return get_contained_objects(obj.generator_call) elif isinstance(obj, RaisesAssertionLine): return get_those_and_contained_objects([obj.call, obj.expected_exception]) elif isinstance(obj, Assign): if isinstance(obj.obj, SerializedObject): return get_those_and_contained_objects([obj.obj]) return [] elif isinstance(obj, ObjectAttributeReference): return get_those_and_contained_objects([obj.obj]) elif isinstance(obj, BindingChange): return get_those_and_contained_objects([obj.obj, obj.name]) elif isinstance(obj, (ImmutableObject, UnknownObject, CallToC, CommentLine, SkipTestLine, EqualAssertionStubLine, ModuleVariableReference)): return [] else: raise TypeError("Wrong argument to get_contained_objects: %s." % repr(obj))
def get_contained_events(obj): """Return a list of Events this object requires during testing. This function will descend recursively if objects contained within given object are composite themselves. """ if isinstance(obj, list): return flatten(list(map(get_contained_events, obj))) # Lists are unhashable anyway, so we don't remember them. if obj in events_so_far: return [] else: events_so_far.add(obj) if isinstance(obj, ImmutableObject): # ImmutableObjects are self-sufficient. return [] elif isinstance(obj, UnknownObject): return [] elif isinstance(obj, SequenceObject): return get_those_and_contained_events(obj.contained_objects) elif isinstance(obj, MapObject): return get_those_and_contained_events(flatten(obj.mapping)) elif isinstance(obj, LibraryObject): return get_those_and_contained_events(obj.arguments) elif isinstance(obj, BuiltinException): return get_those_and_contained_events(obj.args) elif isinstance(obj, UserObject): return get_contained_events(obj.get_init_and_external_calls()) elif isinstance(obj, (FunctionCall, MethodCall, GeneratorObjectInvocation)): ret = get_those_and_contained_events( list(obj.input.values()) + list(obj.side_effects)) if obj.caller: ret += side_effects_before_and_affected_objects(obj) return ret elif isinstance(obj, GeneratorObject): if obj.is_activated(): return get_those_and_contained_events(list(obj.args.values())) +\ get_contained_events(obj.calls) else: return [] elif isinstance(obj, SideEffect): return [obj] + get_those_and_contained_events( list(obj.affected_objects)) elif isinstance(obj, CallToC): return side_effects_before_and_affected_objects(obj) else: raise TypeError("Wrong argument to get_contained_events: %s." % repr(obj))
def test_timeline_for_user_object(execution_events, user_object): """Construct a new timeline for a test case based on real execution timeline and a user object that needs to be tested. The new timeline in most cases will contain assertions. """ init_call = user_object.get_init_call() external_calls = testable_calls(user_object.get_external_calls()) # If the constructor raised an exception, object creation should be an assertion. if init_call and init_call.raised_exception(): call_return_timestamp = last_call_action_timestamp(init_call) return [ RaisesAssertionLine( init_call.exception, MethodCallContext(init_call, user_object), call_return_timestamp + 0.25 ) ] timeline = give_context_to_method_calls( compact([init_call]) + flatten(map(lambda call: test_timeline_for_call(execution_events, call), external_calls)), user_object, ) if init_call and len(external_calls) == 0: timeline.append(CommentLine("# Make sure it doesn't raise any exceptions.", timeline[-1].timestamp)) return timeline
def test_timeline_for_user_object(execution_events, user_object): """Construct a new timeline for a test case based on real execution timeline and a user object that needs to be tested. The new timeline in most cases will contain assertions. """ init_call = user_object.get_init_call() external_calls = testable_calls(user_object.get_external_calls()) # If the constructor raised an exception, object creation should be an assertion. if init_call and init_call.raised_exception(): call_return_timestamp = last_call_action_timestamp(init_call) return [ RaisesAssertionLine(init_call.exception, MethodCallContext(init_call, user_object), call_return_timestamp + 0.25) ] timeline = give_context_to_method_calls( compact([init_call]) + flatten([ test_timeline_for_call(execution_events, call) for call in external_calls ]), user_object) if init_call and len(external_calls) == 0: timeline.append( CommentLine("# Make sure it doesn't raise any exceptions.", timeline[-1].timestamp)) return timeline
def get_contained_events(obj): """Return a list of Events this object requires during testing. This function will descend recursively if objects contained within given object are composite themselves. """ if isinstance(obj, list): return flatten(map(get_contained_events, obj)) # Lists are unhashable anyway, so we don't remember them. if obj in events_so_far: return [] else: events_so_far.add(obj) if isinstance(obj, ImmutableObject): # ImmutableObjects are self-sufficient. return [] elif isinstance(obj, UnknownObject): return [] elif isinstance(obj, SequenceObject): return get_those_and_contained_events(obj.contained_objects) elif isinstance(obj, MapObject): return get_those_and_contained_events(flatten(obj.mapping)) elif isinstance(obj, LibraryObject): return get_those_and_contained_events(obj.arguments) elif isinstance(obj, BuiltinException): return get_those_and_contained_events(obj.args) elif isinstance(obj, UserObject): return get_contained_events(obj.get_init_and_external_calls()) elif isinstance(obj, (FunctionCall, MethodCall, GeneratorObjectInvocation)): ret = get_those_and_contained_events(obj.input.values() + list(obj.side_effects)) if obj.caller: ret += side_effects_before_and_affected_objects(obj) return ret elif isinstance(obj, GeneratorObject): if obj.is_activated(): return get_those_and_contained_events(obj.args.values()) +\ get_contained_events(obj.calls) else: return [] elif isinstance(obj, SideEffect): return [obj] + get_those_and_contained_events(list(obj.affected_objects)) elif isinstance(obj, CallToC): return side_effects_before_and_affected_objects(obj) else: raise TypeError("Wrong argument to get_contained_events: %s." % repr(obj))
def ec(event): if isinstance(event, list): return flatten(map(ec, event)) # Avoid infinite recursion. if event in events_so_far: return [] else: events_so_far.add(event) if isinstance(event, Call): return [event] + ec(event.subcalls) + ec(event.input.values()) elif isinstance(event, Callable): return ec(event.calls) elif isinstance(event, EqualAssertionLine) and isinstance(event.actual, (Call, MethodCallContext)): return ec(event.actual) elif isinstance(event, GeneratorAssertionLine): return ec(event.generator_call) elif isinstance(event, RaisesAssertionLine): return ec(event.call) elif isinstance(event, MethodCallContext): return ec(event.call) return []
def ClassWithMethods(classname, methods, call_type='output'): """call_type has to be one of 'output', 'exception' or 'generator'. """ execution = EmptyProjectExecution() method_objects = [] method_calls = [] klass = Class(classname, methods=method_objects) user_object = UserObject(None, klass) for name, calls in methods: method = Method(name, ['self'] + flatten([a.keys() for a,_ in calls]), is_generator=(call_type=='generator')) method_objects.append(method) for args, output in calls: method_calls.append(create_method_call(method, args, output, call_type, execution, user_object)) klass.add_methods(method_objects) user_object.calls = method_calls klass.add_user_object(user_object) return klass
def ec(event): if isinstance(event, list): return flatten(map(ec, event)) # Avoid infinite recursion. if event in events_so_far: return [] else: events_so_far.add(event) if isinstance(event, Call): return [event] + ec(event.subcalls) + ec(event.input.values()) elif isinstance(event, Callable): return ec(event.calls) elif isinstance(event, EqualAssertionLine) and isinstance( event.actual, (Call, MethodCallContext)): return ec(event.actual) elif isinstance(event, GeneratorAssertionLine): return ec(event.generator_call) elif isinstance(event, RaisesAssertionLine): return ec(event.call) elif isinstance(event, MethodCallContext): return ec(event.call) return []
def side_effects_of(calls): return flatten([c.side_effects for c in calls])
def side_effects_of(calls): return flatten(map(lambda c: c.side_effects, calls))
def side_effects_of_call(call): if isinstance(call, GeneratorObject): return flatten([c.side_effects for c in call.calls]) return call.side_effects
def objects_affected_by_side_effects(side_effects): return flatten(map(lambda se: se.affected_objects, side_effects))
def objects_affected_by_side_effects(side_effects): return flatten([se.affected_objects for se in side_effects])