11cb0ef41Sopenharmony_ci#!/usr/bin/env python3
21cb0ef41Sopenharmony_ci# Copyright 2017 the V8 project authors. All rights reserved.
31cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
41cb0ef41Sopenharmony_ci# found in the LICENSE file.
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci"""
71cb0ef41Sopenharmony_ciWrapper script for verify-predictable mode. D8 is expected to be compiled with
81cb0ef41Sopenharmony_civ8_enable_verify_predictable.
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciThe actual test command is expected to be passed to this wraper as is. E.g.:
111cb0ef41Sopenharmony_cipredictable_wrapper.py path/to/d8 --test --predictable --flag1 --flag2
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciThe command is run up to three times and the printed allocation hash is
141cb0ef41Sopenharmony_cicompared. Differences are reported as errors.
151cb0ef41Sopenharmony_ci"""
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci# for py2/py3 compatibility
191cb0ef41Sopenharmony_cifrom __future__ import absolute_import
201cb0ef41Sopenharmony_cifrom __future__ import print_function
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciimport sys
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cifrom testrunner.local import command
251cb0ef41Sopenharmony_cifrom testrunner.local import utils
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciMAX_TRIES = 3
291cb0ef41Sopenharmony_ciTIMEOUT = 120
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci# Predictable mode works only when run on the host os.
321cb0ef41Sopenharmony_cicommand.setup(utils.GuessOS(), None)
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cidef maybe_decode(message):
351cb0ef41Sopenharmony_ci  if not isinstance(message, str):
361cb0ef41Sopenharmony_ci    return message.decode()
371cb0ef41Sopenharmony_ci  return message
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_cidef main(args):
411cb0ef41Sopenharmony_ci  def allocation_str(stdout):
421cb0ef41Sopenharmony_ci    for line in reversed((stdout or '').splitlines()):
431cb0ef41Sopenharmony_ci      if maybe_decode(line).startswith('### Allocations = '):
441cb0ef41Sopenharmony_ci        return line
451cb0ef41Sopenharmony_ci    return None
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  cmd = command.Command(
481cb0ef41Sopenharmony_ci      args[0], args[1:], timeout=TIMEOUT, handle_sigterm=True)
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  previous_allocations = None
511cb0ef41Sopenharmony_ci  for run in range(1, MAX_TRIES + 1):
521cb0ef41Sopenharmony_ci    print('### Predictable run #%d' % run)
531cb0ef41Sopenharmony_ci    output = cmd.execute()
541cb0ef41Sopenharmony_ci    if output.stdout:
551cb0ef41Sopenharmony_ci      print('### Stdout:')
561cb0ef41Sopenharmony_ci      print(output.stdout)
571cb0ef41Sopenharmony_ci    if output.stderr:
581cb0ef41Sopenharmony_ci      print('### Stderr:')
591cb0ef41Sopenharmony_ci      print(output.stderr)
601cb0ef41Sopenharmony_ci    print('### Return code: %s' % output.exit_code)
611cb0ef41Sopenharmony_ci    if output.HasTimedOut():
621cb0ef41Sopenharmony_ci      # If we get a timeout in any run, we are in an unpredictable state. Just
631cb0ef41Sopenharmony_ci      # report it as a failure and don't rerun.
641cb0ef41Sopenharmony_ci      print('### Test timed out')
651cb0ef41Sopenharmony_ci      return 1
661cb0ef41Sopenharmony_ci    allocations = allocation_str(output.stdout)
671cb0ef41Sopenharmony_ci    if not allocations:
681cb0ef41Sopenharmony_ci      print ('### Test had no allocation output. Ensure this is built '
691cb0ef41Sopenharmony_ci             'with v8_enable_verify_predictable and that '
701cb0ef41Sopenharmony_ci             '--verify-predictable is passed at the cmd line.')
711cb0ef41Sopenharmony_ci      return 2
721cb0ef41Sopenharmony_ci    if previous_allocations and previous_allocations != allocations:
731cb0ef41Sopenharmony_ci      print('### Allocations differ')
741cb0ef41Sopenharmony_ci      return 3
751cb0ef41Sopenharmony_ci    if run >= MAX_TRIES:
761cb0ef41Sopenharmony_ci      # No difference on the last run -> report a success.
771cb0ef41Sopenharmony_ci      return 0
781cb0ef41Sopenharmony_ci    previous_allocations = allocations
791cb0ef41Sopenharmony_ci  # Unreachable.
801cb0ef41Sopenharmony_ci  assert False
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ciif __name__ == '__main__':
841cb0ef41Sopenharmony_ci  sys.exit(main(sys.argv[1:]))
85