def run_iteration(
    fn1: Callable, fn2: Callable, sig: inspect.Signature, space: StateSpace
) -> Tuple[Optional[VerificationStatus], Optional[BehaviorDiff]]:
    original_args = gen_args(sig)
    args1 = copy.deepcopy(original_args)
    args2 = copy.deepcopy(original_args)

    coverage_manager = measure_fn_coverage(fn1, fn2)
    with ExceptionFilter() as efilter, coverage_manager as coverage:
        result1 = describe_behavior(fn1, args1)
        result2 = describe_behavior(fn2, args2)
        space.check_deferred_assumptions()
        if result1 == result2 and args1 == args2:
            debug("Functions equivalent")
            return (VerificationStatus.CONFIRMED, None)
        debug("Functions differ")
        realized_args = {
            k: repr(v)
            for (k, v) in original_args.arguments.items()
        }
        post_execution_args1 = {k: repr(v) for k, v in args1.arguments.items()}
        post_execution_args2 = {k: repr(v) for k, v in args2.arguments.items()}
        diff = BehaviorDiff(
            realized_args,
            Result(repr(result1[0]), result1[1], post_execution_args1),
            Result(repr(result2[0]), result2[1], post_execution_args2),
            coverage(fn1),
            coverage(fn2),
        )
        return (VerificationStatus.REFUTED, diff)
    if efilter.user_exc:
        debug("User-level exception found", repr(efilter.user_exc[0]),
              efilter.user_exc[1])
    return (None, None)
 def symbolic_run(
     self,
     fn: Callable[[StateSpace, Dict[str, object]], object],
     typed_args: Dict[str, type],
 ) -> Tuple[object,  # return value
            Optional[Dict[str, object]],  # arguments after execution
            Optional[BaseException],  # exception thrown, if any
            StateSpace, ]:
     search_root = SinglePathNode(True)
     with COMPOSITE_TRACER, Patched():
         for itr in range(1, 200):
             debug("iteration", itr)
             space = StateSpace(time.monotonic() + 10.0,
                                1.0,
                                search_root=search_root)
             symbolic_args = {}
             try:
                 with StateSpaceContext(space):
                     symbolic_args = {
                         name: proxy_for_type(typ, name)
                         for name, typ in typed_args.items()
                     }
                     ret = fn(space, symbolic_args)
                     ret = (deep_realize(ret), symbolic_args, None, space)
                     space.check_deferred_assumptions()
                     return ret
             except IgnoreAttempt as e:
                 debug("ignore iteration attempt: ", str(e))
                 pass
             except BaseException as e:
                 debug(traceback.format_exc())
                 return (None, symbolic_args, e, space)
             top_analysis, space_exhausted = space.bubble_status(
                 CallAnalysis())
             if space_exhausted:
                 return (
                     None,
                     symbolic_args,
                     CrosshairInternal(f"exhausted after {itr} iterations"),
                     space,
                 )
     return (
         None,
         None,
         CrosshairInternal(
             "Unable to find a successful symbolic execution"),
         space,
     )