Пример #1
0
    def test_basic_no_prune(self):
        inp1 = MockConnectToControllers(fingerprint="a")
        inp2 = MockInputEvent(fingerprint="b")
        int1 = MockInternalEvent(fingerprint="c")
        inp3 = MockInputEvent(fingerprint="d")
        events = [inp1, inp2, int1, inp3]

        def fake_find_internal_events(replay_dag, inject_input, wait_time):
            if inject_input == inp1:
                return []
            elif inject_input == inp2:
                return [int1]
            elif inject_input == inp3:
                return []
            else:
                raise AssertionError("Unexpected event sequence queried: %s" %
                                     replay_dag.events)

        # first, prefix peeker
        self.prefix_peeker.find_internal_events = fake_find_internal_events
        new_dag = self.prefix_peeker.peek(EventDag(events))
        self.assertEquals(events, new_dag.events)

        # next, snapshot peeker
        # Hack alert! throw away first two args
        def snapshotter_fake_find_internal_events(s, c, dag_interval,
                                                  inject_input, wait_time):
            return (fake_find_internal_events(dag_interval, inject_input,
                                              wait_time),
                    self.mock_snapshotter)

        self.snapshot_peeker.find_internal_events = snapshotter_fake_find_internal_events
        new_dag = self.snapshot_peeker.peek(EventDag(events))
        self.assertEquals(events, new_dag.events)
Пример #2
0
 def test_basic_noop(self):
     """ test_basic_noop: running on a dag with no internal events returns the same dag """
     events = [MockConnectToControllers(fingerprint=("class", 0))] + [
         MockInputEvent(fingerprint=("class", f)) for f in range(1, 7)
     ]
     new_dag = self.prefix_peeker.peek(EventDag(events))
     self.assertEquals(events, new_dag.events)
     new_dag = self.snapshot_peeker.peek(EventDag(events))
     self.assertEquals(events, new_dag.events)
Пример #3
0
  def __init__(self, simulation_cfg, superlog_path_or_dag,
               invariant_check=InvariantChecker.check_correspondence,
               transform_dag=None, end_wait_seconds=0.5,
               mcs_trace_path=None, extra_log=None, dump_runtime_stats=True,
               **kwargs):
    super(MCSFinder, self).__init__(simulation_cfg)
    self.sync_callback = None
    self._log = logging.getLogger("mcs_finder")

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(superlog_parser.parse_path(superlog_path))
    else:
      self.dag = superlog_path_or_dag

    self.invariant_check = invariant_check
    self.transform_dag = transform_dag
    self.mcs_trace_path = mcs_trace_path
    self._extra_log = extra_log
    self._runtime_stats = None
    self.kwargs = kwargs
    self.end_wait_seconds = end_wait_seconds
    if dump_runtime_stats:
      self._runtime_stats = {}
Пример #4
0
 def test_all(self):
     trace = [MockInputEvent(fingerprint=("class", f)) for f in range(1, 7)]
     dag = EventDag(trace)
     mcs = trace
     mcs_finder = MockMCSFinder(dag, mcs)
     result = mcs_finder.simulate()
     self.assertEqual(mcs, result)
Пример #5
0
  def _track_new_internal_events(self, simulation, replayer):
    ''' Pre: simulation must have been run through a replay'''
    # We always check against internal events that were buffered at the end of
    # the original run (don't want to overcount)
    prev_buffered_receives = []
    try:
      path = self.superlog_path + ".unacked"
      if not os.path.exists(path):
        log.warn("unacked internal events file from original run does not exist")
        return
      prev_buffered_receives = set([ e.pending_receive for e in
                                     [ f for f in EventDag(log_parser.parse_path(path)).events
                                       if type(f) == ControlMessageReceive ] ])
    except ValueError as e:
      log.warn("unacked internal events is corrupt? %r" % e)
      return
    buffered_message_receipts = []
    for p in simulation.openflow_buffer.pending_receives:
      if p not in prev_buffered_receives:
        buffered_message_receipts.append(repr(p))
      else:
        prev_buffered_receives.remove(p)

    self._runtime_stats.record_buffered_message_receipts(buffered_message_receipts)
    new_internal_events = replayer.unexpected_state_changes + replayer.passed_unexpected_messages
    self._runtime_stats.record_new_internal_events(new_internal_events)
    self._runtime_stats.record_early_internal_events(replayer.early_state_changes)
    self._runtime_stats.record_timed_out_events(replayer.event_scheduler_stats.get_timeouts_dict())
    self._runtime_stats.record_matched_events(replayer.event_scheduler_stats.get_matches_dict())
Пример #6
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 mock_controllers=True,
                 input_logger=None,
                 show_flow_tables_each_step=True):
        # TODO(cs): allow user to specify a round number where they want to stop,
        # otherwise play forward events without asking for interactive ack.
        Interactive.__init__(self, simulation_cfg, input_logger=input_logger)

        if mock_controllers is False:
            raise NotImplementedError("Live controllers not yet supported")
        self.mock_controllers = mock_controllers

        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents.
            self.event_list = EventDag(
                log_parser.parse_path(superlog_path)).events
        else:
            self.event_list = superlog_path_or_dag.events

        # TODO(cs): support compute_interpolated_time whenever we support
        # non-mocked controllers.

        if self.mock_controllers:
            self.event_list = [
                e for e in self.event_list
                if type(e) in InteractiveReplayer.supported_input_events
                or type(e) in InteractiveReplayer.supported_internal_events
            ]
        self.show_flow_tables_each_step = show_flow_tables_each_step
Пример #7
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 create_event_scheduler=None,
                 **kwargs):
        ControlFlow.__init__(self, simulation_cfg)
        self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents
            self.dag = EventDag(superlog_parser.parse_path(superlog_path))
        else:
            self.dag = superlog_path_or_dag

        # compute interpolate to time to be just before first event
        self.compute_interpolated_time(self.dag.events[0])

        if create_event_scheduler:
            self.create_event_scheduler = create_event_scheduler
        else:
            self.create_event_scheduler = \
              lambda simulation: EventScheduler(simulation,
                  **{ k: v for k,v in kwargs.items()
                      if k in EventScheduler.kwargs })
Пример #8
0
 def test_basic_noop(self):
     """ test_basic_noop: running on a dag with no input events returns the same dag """
     events = [
         MockInputEvent(fingerprint=("class", f)) for f in range(1, 7)
     ]
     new_dag = self.peeker.peek(EventDag(events))
     self.assertEquals(events, new_dag.events)
Пример #9
0
 def _ignore_interposition(self):
     '''
 Configure all interposition points to immediately pass through all
 internal events
 (possibly useful for replays affected by non-determinism)
 '''
     filtered_events = [
         e for e in self.dag.events if type(e) not in all_internal_events
     ]
     self.dag = EventDag(filtered_events)
     self.default_dp_permit = True
     self.dp_checker = AlwaysAllowDataplane(self.dag)
Пример #10
0
 def all(self, mcs_finder_type):
     trace = [MockInputEvent(fingerprint=("class", f)) for f in range(1, 7)]
     trace.append(InvariantViolation(["violation"], persistent=True))
     dag = EventDag(trace)
     mcs = trace[0:6]
     mcs_finder = mcs_finder_type(dag, mcs)
     try:
         os.makedirs(mcs_results_path)
         mcs_finder.init_results(mcs_results_path)
         mcs_finder.simulate()
     finally:
         shutil.rmtree(mcs_results_path)
     self.assertEqual(mcs, mcs_finder.dag.input_events)
Пример #11
0
 def setUp(self):
     self.input_trace = [
         MockInputEvent(fingerprint=("class", f)) for f in range(1, 7)
     ]
     self.dag = EventDag(self.input_trace)
     self.prefix_peeker = PrefixPeeker(None)
     IPAddressSpace._claimed_addresses.clear()
     ControllerConfig._controller_labels.clear()
     controller_cfg = ControllerConfig(start_cmd="sleep")
     simulation_cfg = SimulationConfig(controller_configs=[controller_cfg])
     self.snapshot_peeker = SnapshotPeeker(simulation_cfg,
                                           default_dp_permit=True)
     self.snapshot_peeker.setup_simulation = lambda: (None, None)
     # N.B. this assumes that no internal events occur before the first input
     # event.
     self.snapshot_peeker.snapshot_and_play_forward = lambda *args: ([],
                                                                     None)
     self.snapshot_peeker.replay_interval = lambda *args: []
     self.mock_snapshotter = MockSnapshotter()
Пример #12
0
    def test_basic_prune(self):
        inp1 = MockInputEvent(fingerprint="a")
        inp2 = MockInputEvent(fingerprint="b")
        int1 = MockInternalEvent(fingerprint="c")
        inp3 = MockInputEvent(fingerprint="d")
        int2 = MockInternalEvent(fingerprint="e")
        all_events = [inp1, inp2, int1, inp3, int2]
        sub_events = [inp2, int1, inp3, int2]

        def fake_find_internal_events(replay_dag, wait_time):
            if replay_dag.events == [inp2]:
                return []
            elif replay_dag.events == [inp2, inp3]:
                return [int2]
            else:
                raise AssertionError("Unexpected event sequence queried: %s" %
                                     replay_dag.events)

        self.peeker.find_internal_events = fake_find_internal_events
        new_dag = self.peeker.peek(EventDag(sub_events))
        self.assertEquals([inp2, inp3, int2], new_dag.events)
Пример #13
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 ignore_trailing_flow_mod_deletes=True):
        # TODO(cs): allow the user to specify a stop point in the event dag, in
        # case the point they are interested in occurs before the end of the trace.
        self.simulation_cfg = simulation_cfg
        self.sync_callback = ReplaySyncCallback()
        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents.
            self.event_list = EventDag(
                log_parser.parse_path(superlog_path)).events
        else:
            self.event_list = superlog_path_or_dag.events

        self.event_list = [
            e for e in self.event_list if type(e) == ControlMessageReceive
            and type(e.get_packet()) != ofp_packet_out
        ]
        self.ignore_trailing_flow_mod_deletes = ignore_trailing_flow_mod_deletes
Пример #14
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 create_event_scheduler=None,
                 print_buffers=True,
                 wait_on_deterministic_values=False,
                 default_dp_permit=False,
                 fail_to_interactive=False,
                 fail_to_interactive_on_persistent_violations=False,
                 end_in_interactive=False,
                 input_logger=None,
                 allow_unexpected_messages=False,
                 expected_message_round_window=3,
                 pass_through_whitelisted_messages=False,
                 delay_flow_mods=False,
                 invariant_check_name="",
                 bug_signature="",
                 end_wait_seconds=0.5,
                 transform_dag=None,
                 pass_through_sends=False,
                 fail_fast=False,
                 check_interval=5,
                 **kwargs):
        '''
     - If invariant_check_name is not None, check it at the end for the
       execution
     - If bug_signature is not None, check whether this particular signature
       appears in the output of the invariant check at the end of the
       execution
    '''
        ControlFlow.__init__(self, simulation_cfg)
        # Label uniquely identifying this replay, set in init_results()
        self.replay_id = "N/A"
        self.logical_time = 0
        if wait_on_deterministic_values:
            self.sync_callback = ReplaySyncCallback()
        else:
            self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents
            self.dag = EventDag(log_parser.parse_path(superlog_path))
        else:
            self.dag = superlog_path_or_dag

        if len(self.dag.events) == 0:
            raise ValueError("No events to replay!")

        self.default_dp_permit = default_dp_permit
        self.dp_checker = self._setup_dp_checker(default_dp_permit)
        if self.default_dp_permit:
            # Set DataplanePermit and DataplaneDrop to passive if permit is set
            # to default
            # TODO(cs): rather than setting these to passive (which still causes them to
            # be scheduled as regular events) should these just be removed from the
            # event dag altogether?
            for event in [e for e in self.dag.events if type(e) in dp_events]:
                event.passive = default_dp_permit

        self.print_buffers_flag = print_buffers
        self.fail_fast = fail_fast
        self.check_interval = check_interval

        # compute interpolate to time to be just before first event
        self.compute_interpolated_time(self.dag.events[0])
        # String repesentations of unexpected state changes we've passed through, for
        # statistics purposes.
        self.unexpected_state_changes = []
        self.early_state_changes = []
        self.event_scheduler_stats = None
        self.end_in_interactive = end_in_interactive
        self.fail_to_interactive = fail_to_interactive
        self.fail_to_interactive_on_persistent_violations =\
          fail_to_interactive_on_persistent_violations
        self._input_logger = input_logger
        self.allow_unexpected_messages = allow_unexpected_messages
        self.expected_message_round_window = expected_message_round_window
        self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
        self.pass_through_sends = pass_through_sends
        # How many logical rounds to peek ahead when deciding if a message is
        # expected or not.
        # String repesentations of unexpected messages we've passed through, for
        # statistics purposes.
        self.passed_unexpected_messages = []
        self.delay_flow_mods = delay_flow_mods
        self.end_wait_seconds = end_wait_seconds
        self.transform_dag = transform_dag
        self.bug_signature = bug_signature
        self.invariant_check_name = invariant_check_name
        self.invariant_check = None
        if self.invariant_check_name:
            if self.invariant_check_name not in name_to_invariant_check:
                raise ValueError(
                    '''Unknown invariant check %s.\n'''
                    '''Invariant check name must be defined in config.invariant_checks''',
                    self.invariant_check_name)
            self.invariant_check = name_to_invariant_check[
                self.invariant_check_name]

        if self.pass_through_whitelisted_messages:
            for event in self.dag.events:
                if hasattr(event, "ignore_whitelisted_packets"):
                    event.ignore_whitelisted_packets = True

        if self.simulation_cfg.ignore_interposition:
            self._ignore_interposition()

        if create_event_scheduler:
            self.create_event_scheduler = create_event_scheduler
        else:
            if self.default_dp_permit:
                # Tell EventScheduler to use call into us whenever it wants to sleep or
                # select, so that we can keep forwarding dataplane packets.
                kwargs[
                    'sleep_continuation'] = self._sleep_with_dataplane_passthrough
                kwargs[
                    'select_continuation'] = self._select_with_dataplane_passthrough

            self.create_event_scheduler = \
              lambda simulation: EventScheduler(simulation,
                  **{ k: v for k,v in kwargs.items()
                      if k in EventScheduler.kwargs })

        unknown_kwargs = [
            k for k in kwargs.keys() if k not in EventScheduler.kwargs
        ]
        if unknown_kwargs != []:
            raise ValueError("Unknown kwargs %s" % str(unknown_kwargs))
Пример #15
0
 def setUp(self):
     self.input_trace = [
         MockInputEvent(fingerprint=("class", f)) for f in range(1, 7)
     ]
     self.dag = EventDag(self.input_trace)
     self.peeker = Peeker(None)
Пример #16
0
  def peek(self, dag):
    '''
    If dag.events == [], returns immediately.

    If dag.events != [], assumes that isinstance(dag.events[0], ConnectToControllers)
    '''
    if dag.input_events == []:
      return dag
    # post: len(dag.input_events) > 0

    unsupported_types = [ProcessFlowMod, DataplaneDrop]
    if find(lambda e: type(e) in unsupported_types, dag.events) is not None:
      raise ValueError('''Delayed flow_mods not yet supported. Please '''
                       '''implement the TODO near the sleep() call in play_forward()''')

    if not isinstance(dag.events[0], ConnectToControllers):
      raise ValueError("First event must be ConnectToControllers")

    simulation = None
    try:
      # Inferred events includes input events and internal events
      inferred_events = []

      (simulation, controller) = self.setup_simulation()

      # dag.input_events returns only prunable input events. We also need
      # include ConnectToControllers, which is a non-prunable input event.
      assert(dag.input_events[0] != dag.events[0])
      snapshot_inputs = [dag.events[0]] + dag.input_events

      # The input event from the previous iteration, followed by the internal
      # events that were inferred from the previous peek().
      # Since we assume that the first event is always ConnectToControllers,
      # there are never internal events (nor input events) preceding the
      # initial ConnectToControllers.
      # TODO(cs): might not want to contrain the caller's dag in this way.
      events_inferred_last_iteration = []

      for inject_input_idx in xrange(0, len(snapshot_inputs)):
        inject_input = get_inject_input(inject_input_idx, snapshot_inputs)
        following_input = get_following_input(inject_input_idx, snapshot_inputs)
        expected_internal_events = \
           get_expected_internal_events(inject_input, following_input, dag.events)

        log.debug("peek()'ing after input %d (%s)" %
                  (inject_input_idx, str(inject_input)))

        inferred_events += events_inferred_last_iteration

        # We replay events_inferred_last_iteration (internal events preceding
        # inject_input), as well as a NOPInput with the same timestamp as inject_input
        # to ensure that the timing is the same before peek()ing.
        fencepost = NOPInput(time=inject_input.time, round=inject_input.round)
        dag_interval = EventDag(events_inferred_last_iteration + [fencepost])

        if expected_internal_events == []:
          # Optimization: if no internal events occured between this input and the
          # next, no need to peek(), just bring the simulation's state forward up to
          # inject_input
          log.debug("Optimization: no expected internal events")
          Peeker.ambiguous_counts[0.0] += 1
          self.replay_interval(simulation, dag_interval, 0)
          events_inferred_last_iteration = [inject_input]
          continue

        wait_time_seconds = self.get_wait_time_seconds(inject_input, following_input)
        (found_events, snapshotter) = self.find_internal_events(simulation, controller,
                                                                dag_interval, inject_input,
                                                                wait_time_seconds)
        events_inferred_last_iteration = [inject_input]
        events_inferred_last_iteration += match_and_filter(found_events, expected_internal_events)
        snapshotter.snapshot_proceed()

      # Don't forget the final iteration's output
      inferred_events += events_inferred_last_iteration
    finally:
      if simulation is not None:
        simulation.clean_up()

    return EventDag(inferred_events)
Пример #17
0
  def peek(self, dag):
    ''' Infer which internal events are/aren't going to occur (for the entire
    sequence of input events in dag)'''
    # TODO(cs): optimization: write the prefix trie to a file, in case we want to run
    # FindMCS again?
    if len(dag.input_events) == 0:
      # Postcondition: input_events[-1] is not None
      #                and self._events_list[-1] is not None
      return dag

    # dag.input_events returns only prunable input events. We also need
    # include ConnectToControllers, which is a non-prunable input event.
    if not isinstance(dag.events[0], ConnectToControllers):
      raise ValueError("First event must be ConnectToControllers")
    assert(dag.input_events[0] != dag.events[0])
    input_events = [dag.events[0]] + dag.input_events

    # Initilize current_input_prefix to the longest_match prefix we've
    # inferred previously (or [] if this is an entirely new prefix)
    current_input_prefix = list(self._prefix_trie\
                                .longest_prefix(input_events, default=[]))
    log.debug("Current input prefix: %s" % str(current_input_prefix))

    # The value is both internal events and input events (values of the trie)
    # leading up, but not including the next input following the tail of the
    # prefix.
    # Note that we assume that there are no internal events before the first
    # input event (i.e. we assume quiescence)
    inferred_events = list(self._prefix_trie\
                           .longest_prefix_value(input_events, default=[]))
    log.debug("Current inferred_events: %s" % str(inferred_events))
    inject_input_idx = len(current_input_prefix)

    # While we still have inputs to inject
    while inject_input_idx < len(input_events):
      # The input we're about to inject
      inject_input = input_events[inject_input_idx]
      following_input = get_following_input(inject_input_idx, dag.input_events)

      # The input following the one we're going to inject
      log.debug("peek()'ing after input %d" % (inject_input_idx))

      expected_internal_events = \
        get_expected_internal_events(inject_input, following_input, dag.events)

      # Optimization: if no internal events occured between this input and the
      # next, no need to peek()
      if expected_internal_events == []:
        log.debug("Optimization: no expected internal events")
        newly_inferred_events = []
        Peeker.ambiguous_counts[0.0] += 1
      else:
        wait_time_seconds = self.get_wait_time_seconds(inject_input, following_input)
        # We inject a NOPInput with the same timestamp as inject_input
        # to ensure that the timing is the same before peek()ing, then replay
        # inject_input in play_forward()
        fencepost = NOPInput(time=inject_input.time, round=inject_input.round)
        replay_dag = EventDag(inferred_events + [ fencepost ])
        found_events = self.find_internal_events(replay_dag, inject_input, wait_time_seconds)
        newly_inferred_events = match_and_filter(found_events, expected_internal_events)

      (current_input_prefix,
       inferred_events) = self._update_trie(current_input_prefix, inject_input,
                                            inferred_events, newly_inferred_events)
      inject_input_idx += 1

    return EventDag(inferred_events)
Пример #18
0
  def peek(self, dag):
    ''' Infer which internal events are/aren't going to occur, '''
    # TODO(cs): optimization: write the prefix trie to a file, in case we want to run
    # FindMCS again?
    input_events = dag.input_events

    if len(input_events) == 0:
      # Postcondition: input_events[-1] is not None
      #                and self._events_list[-1] is not None
      return dag

    # Initilize current_input_prefix to the longest_match prefix we've
    # inferred previously (or [] if this is an entirely new prefix)
    current_input_prefix = list(self._prefix_trie\
                                .longest_prefix(input_events, default=[]))
    log.debug("Current input prefix: %s" % str(current_input_prefix))

    # The value is both internal events and input events (values of the trie)
    # leading up, but not including the next input following the tail of the
    # prefix.
    # Note that we assume that there are no internal events before the first
    # input event (i.e. we assume quiescence)
    inferred_events = list(self._prefix_trie\
                           .longest_prefix_value(input_events, default=[]))
    log.debug("Current inferred_events: %s" % str(inferred_events))
    inject_input_idx = len(current_input_prefix)

    # While we still have inputs to inject
    while inject_input_idx < len(input_events):
      # The input we're about to inject
      inject_input = input_events[inject_input_idx]

      if inject_input_idx < len(input_events) - 1:
        # there is a following input_event
        following_input = input_events[inject_input_idx + 1]
      else:
        following_input = None

      # The input following the one we're going to inject
      log.debug("peek()'ing after input %d" %
                (inject_input_idx))

      expected_internal_events = \
        get_expected_internal_events(inject_input, following_input, dag.events)

      # Optimization: if no internal events occured between this input and the
      # next, no need to peek()
      if expected_internal_events == []:
        log.debug("Optimization: no expected internal events")
        newly_inferred_events = []
      else:
        wait_time_seconds = self.get_wait_time_seconds(inject_input, following_input)
        replay_dag = EventDag(inferred_events + [ inject_input ])
        found_events = self.find_internal_events(replay_dag, wait_time_seconds)
        newly_inferred_events = self.match_and_filter(found_events, expected_internal_events)

      (current_input_prefix,
       inferred_events) = self._update_trie(current_input_prefix, inject_input,
                                            inferred_events, newly_inferred_events)
      inject_input_idx += 1

    return EventDag(inferred_events)
Пример #19
0
def parse_event_trace(trace_path):
    with open(trace_path) as input_file:
        return EventDag(parse(input_file))
Пример #20
0
  def __init__(self, simulation_cfg, superlog_path_or_dag,
               invariant_check_name="", bug_signature="", transform_dag=None,
               mcs_trace_path=None, extra_log=None, runtime_stats_path=None,
               max_replays_per_subsequence=1,
               optimized_filtering=False, forker=LocalForker(),
               replay_final_trace=True, strict_assertion_checking=False,
               no_violation_verification_runs=None,
               **kwargs):
    ''' Note that you may pass in any keyword argument for Replayer to
    MCSFinder, except 'bug_signature' and 'invariant_check_name' '''
    super(MCSFinder, self).__init__(simulation_cfg)
    # number of subsequences delta debugging has examined so far, for
    # distingushing runtime stats from different intermediate runs.
    self.subsequence_id = 0
    self.mcs_log_tracker = None
    self.replay_log_tracker = None
    self.mcs_trace_path = mcs_trace_path
    self.sync_callback = None
    self._log = logging.getLogger("mcs_finder")

    if invariant_check_name == "":
      raise ValueError("Must specify invariant check")
    if invariant_check_name not in name_to_invariant_check:
      raise ValueError('''Unknown invariant check %s.\n'''
                       '''Invariant check name must be defined in config.invariant_checks''',
                       invariant_check_name)
    self.invariant_check_name = invariant_check_name
    self.invariant_check = name_to_invariant_check[invariant_check_name]

    if type(superlog_path_or_dag) == str:
      self.superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(self.superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if self.simulation_cfg.ignore_interposition:
      filtered_events = [e for e in self.dag.events if type(e) not in all_internal_events]
      self.dag = EventDag(filtered_events)

    last_invariant_violation = self.dag.get_last_invariant_violation()
    if last_invariant_violation is None:
      raise ValueError("No invariant violation found in dag...")
    violations = last_invariant_violation.violations
    self.bug_signature = bug_signature
    if len(violations) > 1:
      while self.bug_signature == "":
        msg.interactive("\n------------------------------------------\n")
        msg.interactive("Multiple violations detected! Choose one for MCS Finding:")
        for i, violation in enumerate(violations):
          msg.interactive("  [%d] %s" % (i+1, violation))
        violation_index = msg.raw_input("> ")
        if re.match("^\d+$", violation_index) is None or\
           int(violation_index) < 1 or\
           int(violation_index) > len(violations):
          msg.fail("Must provide an integer between 1 and %d!" % len(violations))
          continue
        self.bug_signature = violations[int(violation_index)-1]
    if self.bug_signature == "":
      self.bug_signature = violations[0]
    msg.success("\nBug signature to match is %s. Proceeding with MCS finding!\n" % self.bug_signature)

    self.transform_dag = transform_dag
    # A second log with just our MCS progress log messages
    self._extra_log = extra_log
    self.kwargs = kwargs
    unknown_kwargs = [ k for k in kwargs.keys() if k not in Replayer.kwargs ]
    if unknown_kwargs != []:
      raise ValueError("Unknown kwargs %s" % str(unknown_kwargs))
    if no_violation_verification_runs is not None:
      raise ValueError('''no_violation_verification_runs parameter is deprecated. '''
                       '''Use max_replays_per_subsequence.''')
    self.max_replays_per_subsequence = max_replays_per_subsequence
    self._runtime_stats = RuntimeStats(self.subsequence_id, runtime_stats_path=runtime_stats_path)
    # Whether to try alternate trace splitting techiques besides splitting by time.
    self.optimized_filtering = optimized_filtering
    self.forker = forker
    self.replay_final_trace = replay_final_trace
    self.strict_assertion_checking = strict_assertion_checking
Пример #21
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 invariant_check_name=None,
                 transform_dag=None,
                 end_wait_seconds=0.5,
                 mcs_trace_path=None,
                 extra_log=None,
                 runtime_stats_path=None,
                 wait_on_deterministic_values=False,
                 no_violation_verification_runs=1,
                 optimized_filtering=False,
                 forker=LocalForker(),
                 replay_final_trace=True,
                 strict_assertion_checking=False,
                 delay_flow_mods=False,
                 **kwargs):
        super(MCSFinder, self).__init__(simulation_cfg)
        # number of subsequences delta debugging has examined so far, for
        # distingushing runtime stats from different intermediate runs.
        self.subsequence_id = 0
        self.mcs_log_tracker = None
        self.replay_log_tracker = None
        self.mcs_trace_path = mcs_trace_path
        self.sync_callback = None
        self._log = logging.getLogger("mcs_finder")

        if invariant_check_name is None:
            raise ValueError("Must specify invariant check")
        if invariant_check_name not in name_to_invariant_check:
            raise ValueError(
                '''Unknown invariant check %s.\n'''
                '''Invariant check name must be defined in config.invariant_checks''',
                invariant_check_name)
        self.invariant_check = name_to_invariant_check[invariant_check_name]

        if type(superlog_path_or_dag) == str:
            self.superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents
            self.dag = EventDag(log_parser.parse_path(self.superlog_path))
        else:
            self.dag = superlog_path_or_dag

        last_invariant_violation = self.dag.get_last_invariant_violation()
        if last_invariant_violation is None:
            raise ValueError("No invariant violation found in dag...")
        violations = last_invariant_violation.violations
        if len(violations) > 1:
            self.bug_signature = None
            while self.bug_signature is None:
                msg.interactive(
                    "\n------------------------------------------\n")
                msg.interactive(
                    "Multiple violations detected! Choose one for MCS Finding:"
                )
                for i, violation in enumerate(violations):
                    msg.interactive("  [%d] %s" % (i + 1, violation))
                violation_index = msg.raw_input("> ")
                if re.match("^\d+$", violation_index) is None or\
                   int(violation_index) < 1 or\
                   int(violation_index) > len(violations):
                    msg.fail("Must provide an integer between 1 and %d!" %
                             len(violations))
                    continue
                self.bug_signature = violations[int(violation_index) - 1]
        else:
            self.bug_signature = violations[0]
        msg.success(
            "\nBug signature to match is %s. Proceeding with MCS finding!\n" %
            self.bug_signature)

        self.transform_dag = transform_dag
        # A second log with just our MCS progress log messages
        self._extra_log = extra_log
        self.kwargs = kwargs
        self.end_wait_seconds = end_wait_seconds
        self.wait_on_deterministic_values = wait_on_deterministic_values
        # `no' means "number"
        self.no_violation_verification_runs = no_violation_verification_runs
        self._runtime_stats = RuntimeStats(
            self.subsequence_id, runtime_stats_path=runtime_stats_path)
        # Whether to try alternate trace splitting techiques besides splitting by time.
        self.optimized_filtering = optimized_filtering
        self.forker = forker
        self.replay_final_trace = replay_final_trace
        self.strict_assertion_checking = strict_assertion_checking
        self.delay_flow_mods = delay_flow_mods
Пример #22
0
  def __init__(self, simulation_cfg, superlog_path_or_dag, create_event_scheduler=None,
               print_buffers=True, wait_on_deterministic_values=False, default_dp_permit=False,
               fail_to_interactive=False, fail_to_interactive_on_persistent_violations=False,
               end_in_interactive=False, input_logger=None,
               allow_unexpected_messages=False,
               pass_through_whitelisted_messages=True,
               delay_flow_mods=False,
               **kwargs):
    ControlFlow.__init__(self, simulation_cfg)
    if wait_on_deterministic_values:
      self.sync_callback = ReplaySyncCallback()
    else:
      self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if len(self.dag.events) == 0:
      raise ValueError("No events to replay!")

    self.default_dp_permit = default_dp_permit
    # Set DataplanePermit and DataplaneDrop to passive if permit is set
    # to default
    for event in [ e for e in self.dag.events if type(e) in dp_events ]:
      event.passive = default_dp_permit

    self.dp_checker = None
    if default_dp_permit:
      self.dp_checker = DataplaneChecker(self.dag)

    self.print_buffers_flag = print_buffers

    # compute interpolate to time to be just before first event
    self.compute_interpolated_time(self.dag.events[0])
    # String repesentations of unexpected state changes we've passed through, for
    # statistics purposes.
    self.unexpected_state_changes = []
    self.early_state_changes = []
    self.event_scheduler_stats = None
    self.end_in_interactive = end_in_interactive
    self.fail_to_interactive = fail_to_interactive
    self.fail_to_interactive_on_persistent_violations =\
      fail_to_interactive_on_persistent_violations
    self._input_logger = input_logger
    self.allow_unexpected_messages = allow_unexpected_messages
    self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
    # How many logical rounds to peek ahead when deciding if a message is
    # expected or not.
    self.expected_message_round_window = 3
    # String repesentations of unexpected messages we've passed through, for
    # statistics purposes.
    self.passed_unexpected_messages = []
    self.delay_flow_mods = delay_flow_mods

    if self.pass_through_whitelisted_messages:
      for event in self.dag.events:
        if hasattr(event, "ignore_whitelisted_packets"):
          event.ignore_whitelisted_packets = True

    if create_event_scheduler:
      self.create_event_scheduler = create_event_scheduler
    else:
      self.create_event_scheduler = \
        lambda simulation: EventScheduler(simulation,
            **{ k: v for k,v in kwargs.items()
                if k in EventScheduler.kwargs })