11cb0ef41Sopenharmony_ci# Copyright 2021 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci# found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cifrom collections import deque
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_cifrom . import base
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciclass SequenceProc(base.TestProc):
111cb0ef41Sopenharmony_ci  """Processor ensuring heavy tests are sent sequentially into the execution
121cb0ef41Sopenharmony_ci  pipeline.
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci  The class keeps track of the number of tests in the pipeline marked heavy
151cb0ef41Sopenharmony_ci  and permits only a configurable amount. An excess amount is queued and sent
161cb0ef41Sopenharmony_ci  as soon as other heavy tests return.
171cb0ef41Sopenharmony_ci  """
181cb0ef41Sopenharmony_ci  def __init__(self, max_heavy):
191cb0ef41Sopenharmony_ci    """Initialize the processor.
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci    Args:
221cb0ef41Sopenharmony_ci      max_heavy: The maximum number of heavy tests that will be sent further
231cb0ef41Sopenharmony_ci                 down the pipeline simultaneously.
241cb0ef41Sopenharmony_ci    """
251cb0ef41Sopenharmony_ci    super(SequenceProc, self).__init__()
261cb0ef41Sopenharmony_ci    assert max_heavy > 0
271cb0ef41Sopenharmony_ci    self.max_heavy = max_heavy
281cb0ef41Sopenharmony_ci    self.n_heavy = 0
291cb0ef41Sopenharmony_ci    self.buffer = deque()
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  def next_test(self, test):
321cb0ef41Sopenharmony_ci    if test.is_heavy:
331cb0ef41Sopenharmony_ci      if self.n_heavy < self.max_heavy:
341cb0ef41Sopenharmony_ci        # Enough space to send more heavy tests. Check if the test is not
351cb0ef41Sopenharmony_ci        # filtered otherwise.
361cb0ef41Sopenharmony_ci        used = self._send_test(test)
371cb0ef41Sopenharmony_ci        if used:
381cb0ef41Sopenharmony_ci          self.n_heavy += 1
391cb0ef41Sopenharmony_ci        return used
401cb0ef41Sopenharmony_ci      else:
411cb0ef41Sopenharmony_ci        # Too many tests in the pipeline. Buffer the test and indicate that
421cb0ef41Sopenharmony_ci        # this test didn't end up in the execution queue (i.e. test loader
431cb0ef41Sopenharmony_ci        # will try to send more tests).
441cb0ef41Sopenharmony_ci        self.buffer.append(test)
451cb0ef41Sopenharmony_ci        return False
461cb0ef41Sopenharmony_ci    else:
471cb0ef41Sopenharmony_ci      return self._send_test(test)
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  def result_for(self, test, result):
501cb0ef41Sopenharmony_ci    if test.is_heavy:
511cb0ef41Sopenharmony_ci      # A heavy test finished computing. Try to send one from the buffer.
521cb0ef41Sopenharmony_ci      self.n_heavy -= 1
531cb0ef41Sopenharmony_ci      while self.buffer:
541cb0ef41Sopenharmony_ci        next_test = self.buffer.popleft()
551cb0ef41Sopenharmony_ci        if self._send_test(next_test):
561cb0ef41Sopenharmony_ci          self.n_heavy += 1
571cb0ef41Sopenharmony_ci          break
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci    self._send_result(test, result)
60