#!/usr/bin/env vpython3
#
# Copyright 2017 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.
"""Tests for java_deobfuscate."""

import argparse
import os
import subprocess
import sys
import tempfile
import unittest

# Set by command-line argument.
_JAVA_DEOBFUSCATE_PATH = None

LINE_PREFIXES = [
    '',
    # logcat -v threadtime
    '09-08 14:38:35.535 18029 18084 E qcom_sensors_hal: ',
    # logcat
    'W/GCM     (15158): ',
    'W/GCM     (  158): ',
]

TEST_MAP = """\
this.was.Deobfuscated -> FOO:
    int[] mFontFamily -> a
    1:3:void someMethod(int,android.os.Bundle):65:67 -> bar
never.Deobfuscated -> NOTFOO:
    int[] mFontFamily -> a
    1:3:void someMethod(int,android.os.Bundle):65:67 -> bar
"""

TEST_DATA = [
    '',
    'FOO',
    'FOO.bar',
    'Here is a FOO',
    'Here is a class FOO',
    'Here is a class FOO baz',
    'Here is a "FOO" baz',
    'Here is a type "FOO" baz',
    'Here is a "FOO.bar" baz',
    'SomeError: SomeFrameworkClass in isTestClass for FOO',
    'Here is a FOO.bar',
    'Here is a FOO.bar baz',
    'END FOO#bar',
    'new-instance 3810 (LSome/Framework/Class;) in LFOO;',
    'FOO: Error message',
    'Caused by: FOO: Error message',
    '\tat FOO.bar(PG:1)',
    '\t at\t FOO.bar\t (\t PG:\t 1\t )',
    ('Unable to start activity ComponentInfo{garbage.in/here.test}:'
     ' java.lang.NullPointerException: Attempt to invoke interface method'
     ' \'void FOO.bar(int,android.os.Bundle)\' on a null object reference'),
    ('Caused by: java.lang.NullPointerException: Attempt to read from field'
     ' \'int[] FOO.a\' on a null object reference'),
    'java.lang.VerifyError: FOO',
    ('java.lang.NoSuchFieldError: No instance field a of type '
     'Ljava/lang/Class; in class LFOO;'),
    'NOTFOO: Object of type FOO was not destroyed...',
]

EXPECTED_OUTPUT = [
    '',
    'this.was.Deobfuscated',
    'this.was.Deobfuscated.someMethod',
    'Here is a FOO',
    'Here is a class this.was.Deobfuscated',
    'Here is a class FOO baz',
    'Here is a "FOO" baz',
    'Here is a type "this.was.Deobfuscated" baz',
    'Here is a "this.was.Deobfuscated.someMethod" baz',
    'SomeError: SomeFrameworkClass in isTestClass for this.was.Deobfuscated',
    'Here is a this.was.Deobfuscated.someMethod',
    'Here is a FOO.bar baz',
    'END this.was.Deobfuscated#someMethod',
    'new-instance 3810 (LSome/Framework/Class;) in Lthis/was/Deobfuscated;',
    'this.was.Deobfuscated: Error message',
    'Caused by: this.was.Deobfuscated: Error message',
    '\tat this.was.Deobfuscated.someMethod(Deobfuscated.java:65)',
    ('\t at\t this.was.Deobfuscated.someMethod\t '
     '(\t Deobfuscated.java:\t 65\t )'),
    ('Unable to start activity ComponentInfo{garbage.in/here.test}:'
     ' java.lang.NullPointerException: Attempt to invoke interface method'
     ' \'void this.was.Deobfuscated.someMethod(int,android.os.Bundle)\' on a'
     ' null object reference'),
    ('Caused by: java.lang.NullPointerException: Attempt to read from field'
     ' \'int[] this.was.Deobfuscated.mFontFamily\' on a null object reference'),
    'java.lang.VerifyError: this.was.Deobfuscated',
    ('java.lang.NoSuchFieldError: No instance field mFontFamily of type '
     'Ljava/lang/Class; in class Lthis/was/Deobfuscated;'),
    'NOTFOO: Object of type this.was.Deobfuscated was not destroyed...',
]
TEST_DATA = [s + '\n' for s in TEST_DATA]
EXPECTED_OUTPUT = [s + '\n' for s in EXPECTED_OUTPUT]


class JavaDeobfuscateTest(unittest.TestCase):

  def __init__(self, *args, **kwargs):
    super(JavaDeobfuscateTest, self).__init__(*args, **kwargs)
    self._map_file = None

  def setUp(self):
    self._map_file = tempfile.NamedTemporaryFile()
    self._map_file.write(TEST_MAP)
    self._map_file.flush()

  def tearDown(self):
    if self._map_file:
      self._map_file.close()

  def _testImpl(self, input_lines=None, expected_output_lines=None,
                prefix=''):
    self.assertTrue(bool(input_lines) == bool(expected_output_lines))

    if not input_lines:
      input_lines = [prefix + x for x in TEST_DATA]
    if not expected_output_lines:
      expected_output_lines = [prefix + x for x in EXPECTED_OUTPUT]

    cmd = [_JAVA_DEOBFUSCATE_PATH, self._map_file.name]
    proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    proc_output, _ = proc.communicate(''.join(input_lines))
    actual_output_lines = proc_output.splitlines(True)
    for actual, expected in zip(actual_output_lines, expected_output_lines):
      self.assertTrue(
          actual == expected or actual.replace('bar', 'someMethod') == expected,
          msg=''.join([
              'Deobfuscation failed.\n',
              '  actual:   %s' % actual,
              '  expected: %s' % expected]))

  def testNoPrefix(self):
    self._testImpl(prefix='')

  def testThreadtimePrefix(self):
    self._testImpl(prefix='09-08 14:38:35.535 18029 18084 E qcom_sensors_hal: ')

  def testStandardPrefix(self):
    self._testImpl(prefix='W/GCM     (15158): ')

  def testStandardPrefixWithPadding(self):
    self._testImpl(prefix='W/GCM     (  158): ')

  @unittest.skip('causes java_deobfuscate to hang, see crbug.com/876539')
  def testIndefiniteHang(self):
    # Test for crbug.com/876539.
    self._testImpl(
        input_lines=[
            'VFY: unable to resolve virtual method 2: LFOO;'
                + '.onDescendantInvalidated '
                + '(Landroid/view/View;Landroid/view/View;)V',
        ],
        expected_output_lines=[
            'VFY: unable to resolve virtual method 2: Lthis.was.Deobfuscated;'
                + '.onDescendantInvalidated '
                + '(Landroid/view/View;Landroid/view/View;)V',
        ])


if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--java-deobfuscate-path', type=os.path.realpath,
                      required=True)
  known_args, unittest_args = parser.parse_known_args()
  _JAVA_DEOBFUSCATE_PATH = known_args.java_deobfuscate_path
  unittest_args = [sys.argv[0]] + unittest_args
  unittest.main(argv=unittest_args)
