#!/usr/bin/python3
#
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Generate Smali Main file from a classes.xml file.
"""

import os
import sys
from pathlib import Path

BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
if BUILD_TOP is None:
  print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
  sys.exit(1)

# Allow us to import utils and mixins.
sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))

from testgen.utils import get_copyright
import testgen.mixins as mixins

from collections import namedtuple
import itertools
import functools
import xml.etree.ElementTree as ET

class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
  """
  A mainclass and main method for this test.
  """

  MAIN_CLASS_TEMPLATE = """{copyright}
.class public LMain;
.super Ljava/lang/Object;

# class Main {{

.method public constructor <init>()V
    .registers 1
    invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
    return-void
.end method

{test_groups}

{test_funcs}

{main_func}

# }}
"""

  MAIN_FUNCTION_TEMPLATE = """
#   public static void main(String[] args) {{
.method public static main([Ljava/lang/String;)V
    .locals 2
    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;

    {test_group_invoke}

    return-void
.end method
#   }}
"""

  TEST_GROUP_INVOKE_TEMPLATE = """
#     {test_name}();
    invoke-static {{}}, {test_name}()V
"""

  def __init__(self):
    """
    Initialize this MainClass
    """
    self.tests = set()
    self.global_funcs = set()

  def add_instance(self, it):
    """
    Add an instance test for the given class
    """
    self.tests.add(it)

  def add_func(self, f):
    """
    Add a function to the class
    """
    self.global_funcs.add(f)

  def get_name(self):
    """
    Get the name of this class
    """
    return "Main"

  def __str__(self):
    """
    Print this class
    """
    all_tests = sorted(self.tests)
    test_invoke = ""
    test_groups = ""
    for t in all_tests:
      test_groups += str(t)
    for t in sorted(all_tests):
      test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
    main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)

    funcs = ""
    for f in self.global_funcs:
      funcs += str(f)
    return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
                                           test_groups=test_groups,
                                           main_func=main_func, test_funcs=funcs)


class InstanceTest(mixins.Named, mixins.NameComparableMixin):
  """
  A method that runs tests for a particular concrete type, It calls the test
  cases for running it in all possible ways.
  """

  INSTANCE_TEST_TEMPLATE = """
#   public static void {test_name}() {{
#     System.out.println("Testing for type {ty}");
#     String s = "{ty}";
#     {ty} v = new {ty}();
.method public static {test_name}()V
    .locals 3
    sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
    const-string v0, "Testing for type {ty}"
    invoke-virtual {{v2,v0}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V

    const-string v0, "{ty}"
    new-instance v1, L{ty};
    invoke-direct {{v1}}, L{ty};-><init>()V

    {invokes}

    const-string v0, "End testing for type {ty}"
    invoke-virtual {{v2,v0}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
    return-void
.end method
#     System.out.println("End testing for type {ty}");
#   }}
"""

  TEST_INVOKE_TEMPLATE = """
#     {fname}(s, v);
    invoke-static {{v0, v1}}, {fname}(Ljava/lang/String;L{farg};)V
"""

  def __init__(self, main, ty):
    """
    Initialize this test group for the given type
    """
    self.ty = ty
    self.main = main
    self.funcs = set()
    self.main.add_instance(self)

  def get_name(self):
    """
    Get the name of this test group
    """
    return "TEST_NAME_"+self.ty

  def add_func(self, f):
    """
    Add a test function to this test group
    """
    self.main.add_func(f)
    self.funcs.add(f)

  def __str__(self):
    """
    Returns the smali code for this function
    """
    func_invokes = ""
    for f in sorted(self.funcs, key=lambda a: (a.func, a.farg)):
      func_invokes += self.TEST_INVOKE_TEMPLATE.format(fname=f.get_name(),
                                                       farg=f.farg)

    return self.INSTANCE_TEST_TEMPLATE.format(test_name=self.get_name(), ty=self.ty,
                                              invokes=func_invokes)

class Func(mixins.Named, mixins.NameComparableMixin):
  """
  A single test case that attempts to invoke a function on receiver of a given type.
  """

  TEST_FUNCTION_TEMPLATE = """
#   public static void {fname}(String s, {farg} v) {{
#     try {{
#       System.out.printf("%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n", s, v.{callfunc}());
#       return;
#     }} catch (Error e) {{
#       System.out.printf("%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n", s);
#       e.printStackTrace(System.out);
#     }}
#   }}
.method public static {fname}(Ljava/lang/String;L{farg};)V
    .locals 7
    :call_{fname}_try_start
      const/4 v0, 2
      new-array v1,v0, [Ljava/lang/Object;
      const/4 v0, 0
      aput-object p0,v1,v0

      sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
      const-string v3, "%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n"

      invoke-{invoke_type} {{p1}}, L{farg};->{callfunc}()Ljava/lang/String;
      move-result-object v4
      const/4 v0, 1
      aput-object v4, v1, v0

      invoke-virtual {{v2,v3,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
      return-void
    :call_{fname}_try_end
    .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
    :error_{fname}_start
      move-exception v3
      const/4 v0, 1
      new-array v1,v0, [Ljava/lang/Object;
      const/4 v0, 0
      aput-object p0, v1, v0
      sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
      const-string v4, "%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n"
      invoke-virtual {{v2,v4,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
      invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
      return-void
.end method
"""

  def __init__(self, func, farg, invoke):
    """
    Initialize this test function for the given invoke type and argument
    """
    self.func = func
    self.farg = farg
    self.invoke = invoke

  def get_name(self):
    """
    Get the name of this test
    """
    return "Test_Func_{}_{}_{}".format(self.func, self.farg, self.invoke)

  def __str__(self):
    """
    Get the smali code for this test function
    """
    return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
                                              farg=self.farg,
                                              invoke_type=self.invoke,
                                              callfunc=self.func)

def flatten_classes(classes, c):
  """
  Iterate over all the classes 'c' can be used as
  """
  while c:
    yield c
    c = classes.get(c.super_class)

def flatten_class_methods(classes, c):
  """
  Iterate over all the methods 'c' can call
  """
  for c1 in flatten_classes(classes, c):
    yield from c1.methods

def flatten_interfaces(dat, c):
  """
  Iterate over all the interfaces 'c' transitively implements
  """
  def get_ifaces(cl):
    for i2 in cl.implements:
      yield dat.interfaces[i2]
      yield from get_ifaces(dat.interfaces[i2])

  for cl in flatten_classes(dat.classes, c):
    yield from get_ifaces(cl)

def flatten_interface_methods(dat, i):
  """
  Iterate over all the interface methods 'c' can call
  """
  yield from i.methods
  for i2 in flatten_interfaces(dat, i):
    yield from i2.methods

def make_main_class(dat):
  """
  Creates a Main.smali file that runs all the tests
  """
  m = MainClass()
  for c in dat.classes.values():
    i = InstanceTest(m, c.name)
    for clazz in flatten_classes(dat.classes, c):
      for meth in flatten_class_methods(dat.classes, clazz):
        i.add_func(Func(meth, clazz.name, 'virtual'))
      for iface in flatten_interfaces(dat, clazz):
        for meth in flatten_interface_methods(dat, iface):
          i.add_func(Func(meth, clazz.name, 'virtual'))
          i.add_func(Func(meth, iface.name, 'interface'))
  return m

class TestData(namedtuple("TestData", ['classes', 'interfaces'])):
  """
  A class representing the classes.xml document.
  """
  pass

class Clazz(namedtuple("Clazz", ["name", "methods", "super_class", "implements"])):
  """
  A class representing a class element in the classes.xml document.
  """
  pass

class IFace(namedtuple("IFace", ["name", "methods", "super_class", "implements"])):
  """
  A class representing an interface element in the classes.xml document.
  """
  pass

def parse_xml(xml):
  """
  Parse the xml description of this test.
  """
  classes = dict()
  ifaces  = dict()
  root = ET.fromstring(xml)
  for iface in root.find("interfaces"):
    name = iface.attrib['name']
    implements = [a.text for a in iface.find("implements")]
    methods = [a.text for a in iface.find("methods")]
    ifaces[name] = IFace(name = name,
                         super_class = iface.attrib['super'],
                         methods = methods,
                         implements = implements)
  for clazz in root.find('classes'):
    name = clazz.attrib['name']
    implements = [a.text for a in clazz.find("implements")]
    methods = [a.text for a in clazz.find("methods")]
    classes[name] = Clazz(name = name,
                          super_class = clazz.attrib['super'],
                          methods = methods,
                          implements = implements)
  return TestData(classes, ifaces)

def main(argv):
  smali_dir = Path(argv[1])
  if not smali_dir.exists() or not smali_dir.is_dir():
    print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
    sys.exit(1)
  class_data = parse_xml((smali_dir / "classes.xml").open().read())
  make_main_class(class_data).dump(smali_dir)

if __name__ == '__main__':
  main(sys.argv)
