#!/usr/bin/env python
# Copyright 2016 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 subprocess
import sys
import unittest

import v8_foozzie
import v8_fuzz_config
import v8_suppressions

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
FOOZZIE = os.path.join(BASE_DIR, 'v8_foozzie.py')
TEST_DATA = os.path.join(BASE_DIR, 'testdata')


class ConfigTest(unittest.TestCase):
  def testExperiments(self):
    """Test that probabilities add up to 100 and that all config names exist.
    """
    EXPERIMENTS = v8_fuzz_config.FOOZZIE_EXPERIMENTS
    CONFIGS = v8_foozzie.CONFIGS
    assert sum(x[0] for x in EXPERIMENTS) == 100
    assert all(map(lambda x: x[1] in CONFIGS, EXPERIMENTS))
    assert all(map(lambda x: x[2] in CONFIGS, EXPERIMENTS))
    assert all(map(lambda x: x[3].endswith('d8'), EXPERIMENTS))

  def testConfig(self):
    """Smoke test how to choose experiments.

    When experiment distribution changes this test might change, too.
    """
    class Rng(object):
      def random(self):
        return 0.5
    self.assertEqual(
        [
          '--first-config=ignition',
          '--second-config=ignition_turbo',
          '--second-d8=d8',
          '--second-config-extra-flags=--stress-scavenge=100',
        ],
        v8_fuzz_config.Config('foo', Rng(), 42).choose_foozzie_flags(),
    )


class UnitTest(unittest.TestCase):
  def testDiff(self):
    # TODO(machenbach): Mock out suppression configuration.
    suppress = v8_suppressions.get_suppression(
        'x64', 'ignition', 'x64', 'ignition_turbo')
    one = ''
    two = ''
    diff = None, None
    self.assertEquals(diff, suppress.diff(one, two))

    one = 'a \n  b\nc();'
    two = 'a \n  b\nc();'
    diff = None, None
    self.assertEquals(diff, suppress.diff(one, two))

    # Ignore line before caret, caret position and error message.
    one = """
undefined
weird stuff
      ^
somefile.js: TypeError: undefined is not a function
  undefined
"""
    two = """
undefined
other weird stuff
            ^
somefile.js: TypeError: baz is not a function
  undefined
"""
    diff = None, None
    self.assertEquals(diff, suppress.diff(one, two))

    one = """
Still equal
Extra line
"""
    two = """
Still equal
"""
    diff = '- Extra line', None
    self.assertEquals(diff, suppress.diff(one, two))

    one = """
Still equal
"""
    two = """
Still equal
Extra line
"""
    diff = '+ Extra line', None
    self.assertEquals(diff, suppress.diff(one, two))

    one = """
undefined
somefile.js: TypeError: undefined is not a constructor
"""
    two = """
undefined
otherfile.js: TypeError: undefined is not a constructor
"""
    diff = """- somefile.js: TypeError: undefined is not a constructor
+ otherfile.js: TypeError: undefined is not a constructor""", None
    self.assertEquals(diff, suppress.diff(one, two))


def cut_verbose_output(stdout):
  # This removes first lines containing d8 commands.
  return '\n'.join(stdout.split('\n')[4:])


def run_foozzie(first_d8, second_d8, *extra_flags):
  return subprocess.check_output([
    sys.executable, FOOZZIE,
    '--random-seed', '12345',
    '--first-d8', os.path.join(TEST_DATA, first_d8),
    '--second-d8', os.path.join(TEST_DATA, second_d8),
    '--first-config', 'ignition',
    '--second-config', 'ignition_turbo',
    os.path.join(TEST_DATA, 'fuzz-123.js'),
  ] + list(extra_flags))


class SystemTest(unittest.TestCase):
  def testSyntaxErrorDiffPass(self):
    stdout = run_foozzie('test_d8_1.py', 'test_d8_2.py', '--skip-sanity-checks')
    self.assertEquals('# V8 correctness - pass\n', cut_verbose_output(stdout))

  def testDifferentOutputFail(self):
    with open(os.path.join(TEST_DATA, 'failure_output.txt')) as f:
      expected_output = f.read()
    with self.assertRaises(subprocess.CalledProcessError) as ctx:
      run_foozzie('test_d8_1.py', 'test_d8_3.py', '--skip-sanity-checks',
                  '--first-config-extra-flags=--flag1',
                  '--first-config-extra-flags=--flag2=0',
                  '--second-config-extra-flags=--flag3')
    e = ctx.exception
    self.assertEquals(v8_foozzie.RETURN_FAIL, e.returncode)
    self.assertEquals(expected_output, cut_verbose_output(e.output))

  def testSanityCheck(self):
    with open(os.path.join(TEST_DATA, 'sanity_check_output.txt')) as f:
      expected_output = f.read()
    with self.assertRaises(subprocess.CalledProcessError) as ctx:
      run_foozzie('test_d8_1.py', 'test_d8_3.py')
    e = ctx.exception
    self.assertEquals(v8_foozzie.RETURN_FAIL, e.returncode)
    self.assertEquals(expected_output, e.output)

if __name__ == '__main__':
  unittest.main()
