summaryrefslogtreecommitdiffstats
path: root/tools/auto_bisect/bisect_state.py
blob: f5d745115dc56c52e4a9e8423b286dd6e2c3a9e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.


class RevisionState(object):
  """Contains bisect state for a given revision.

  Properties:
    depot: The depot that this revision is from (e.g. WebKit).
    revision: Revision number (Git hash or SVN number).
    index: Position of the state in the list of all revisions.
    value: Value(s) returned from the test.
    perf_time: Time that a test took.
    build_time: Time that a build took.
    passed: Represents whether the performance test was successful at that
        revision. Possible values include: 1 (passed), 0 (failed),
        '?' (skipped), 'F' (build failed).
    external: If the revision is a 'src' revision, 'external' contains the
        revisions of each of the external libraries.
  """

  def __init__(self, depot, revision, index):
    self.depot = depot
    self.revision = revision
    self.index = index
    self.value = None
    self.perf_time = 0
    self.build_time = 0
    self.passed = '?'
    self.external = None

  # TODO(sergiyb): Update() to parse run_results from the RunTest.


class BisectState(object):
  """Represents a state of the bisect as a collection of revision states."""

  def __init__(self, depot, revisions):
    """Initializes a new BisectState object with a set of revision states.

    Args:
      depot: Name of the depot used for initial set of revision states.
      revisions: List of revisions used for initial set of revision states.
    """
    self.revision_states = []
    self.revision_index = {}

    index = 0
    for revision in revisions:
      new_state = self._InitRevisionState(depot, revision, index)
      self.revision_states.append(new_state)
      index += 1

  @staticmethod
  def _RevisionKey(depot, revision):
    return "%s:%s" % (depot, revision)

  def _InitRevisionState(self, depot, revision, index):
    key = self._RevisionKey(depot, revision)
    self.revision_index[key] = index
    return RevisionState(depot, revision, index)

  def GetRevisionState(self, depot, revision):
    """Returns a mutable revision state."""
    key = self._RevisionKey(depot, revision)
    index = self.revision_index.get(key)
    return self.revision_states[index] if index else None

  def CreateRevisionStatesAfter(self, depot, revisions, reference_depot,
                                reference_revision):
    """Creates a set of new revision states after a specified reference state.

    Args:
      depot: Name of the depot for the new revision states.
      revisions: List of revisions for the new revision states.
      reference_depot: Name of the depot for the reference revision state.
      reference_revision: Revision for the reference revision state.

    Returns:
      A list containing all created revision states in order as they were added.
    """
    ref_key = self._RevisionKey(reference_depot, reference_revision)
    ref_index = self.revision_index[ref_key]
    num_new_revisions = len(revisions)
    for entry in self.revision_states:
      if entry.index > ref_index:
        entry.index += num_new_revisions

    first_index = ref_index + 1
    for index, revision in enumerate(revisions, start=first_index):
      new_state = self._InitRevisionState(depot, revision, index)
      self.revision_states.insert(index, new_state)

    return self.revision_states[first_index:first_index + num_new_revisions]

  def GetRevisionStates(self):
    """Returns a copy of the list of the revision states."""
    return list(self.revision_states)