# Copyright 2018 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import re

from itertools import zip_longest

from . import base


class OutProc(base.ExpectedOutProc):
  def __init__(self, expected_outcomes, basepath, expected_fail,
               expected_filename, regenerate_expected_files):
    super(OutProc, self).__init__(expected_outcomes, expected_filename,
                                  regenerate_expected_files)
    self._basepath = basepath
    self._expected_fail = expected_fail

  def _is_failure_output(self, output):
    fail = output.exit_code != 0
    if fail != self._expected_fail:
      return True

    expected_lines = []
    # Can't use utils.ReadLinesFrom() here because it strips whitespace.
    with open(self._basepath + '.out') as f:
      for line in f:
        if line.startswith("#") or not line.strip():
          continue
        expected_lines.append(line)
    raw_lines = output.stdout.splitlines()
    actual_lines = [ s for s in raw_lines if not self._ignore_line(s) ]
    if len(expected_lines) != len(actual_lines):
      return True

    # Try .js first, and fall back to .mjs.
    # TODO(v8:9406): clean this up by never separating the path from
    # the extension in the first place.
    base_path = self._basepath + '.js'
    if not os.path.exists(base_path):
      base_path = self._basepath + '.mjs'

    env = {
      'basename': os.path.basename(base_path),
    }
    for (expected, actual) in zip_longest(
        expected_lines, actual_lines, fillvalue=''):
      pattern = re.escape(expected.rstrip() % env)
      pattern = pattern.replace('\\*', '.*')
      pattern = pattern.replace('\\{NUMBER\\}', '\d+(?:\.\d*)?')
      pattern = '^%s$' % pattern
      if not re.match(pattern, actual):
        return True
    return False

  def _ignore_line(self, string):
    """Ignore empty lines, valgrind output, Android output."""
    return (
      not string or
      not string.strip() or
      string.startswith("==") or
      string.startswith("**") or
      string.startswith("ANDROID") or
      # Android linker warning.
      string.startswith('WARNING: linker:')
    )