15fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain#! /usr/bin/python3
25fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain#
35fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# Copyright (C) 2017 The Android Open Source Project
45fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain#
55fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# Licensed under the Apache License, Version 2.0 (the "License");
65fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# you may not use this file except in compliance with the License.
75fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# You may obtain a copy of the License at
85fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain#
95fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain#     http://www.apache.org/licenses/LICENSE-2.0
105fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain#
115fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# Unless required by applicable law or agreed to in writing, software
125fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# distributed under the License is distributed on an "AS IS" BASIS,
135fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# See the License for the specific language governing permissions and
155fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# limitations under the License.
165fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
175fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain"""
185fa822dd1f22886a25515690fce7f8a4c40701b2Roland LevillainGenerate Java test files for test 648-many-direct-methods.
195fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain"""
205fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
215fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainimport os
225fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainimport sys
235fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainfrom pathlib import Path
245fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
255fa822dd1f22886a25515690fce7f8a4c40701b2Roland LevillainBUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
265fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainif BUILD_TOP is None:
275fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
285fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  sys.exit(1)
295fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
305fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# Allow us to import utils and mixins.
315fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainsys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
325fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
335fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainfrom testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
345fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainimport testgen.mixins as mixins
355fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
365fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainclass MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
375fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  """
385fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  A Main.java file containing the Main class and the main function. It will run
395fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  all the test functions we have.
405fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  """
415fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
425fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  MAIN_CLASS_TEMPLATE = """{copyright}
435fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainpublic class Main {{
445fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain{main_func}
455fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain{test_groups}
465fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
475fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain}}"""
485fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
495fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  MAIN_FUNCTION_TEMPLATE = """
505fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  public static void main(String[] args) {
515fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    System.out.println("passed");
525fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  }"""
535fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
545fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def __init__(self):
555fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
565fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Initialize this MainClass. We start out with no tests.
575fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
585fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    self.tests = set()
595fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
605fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def add_test_method(self, num):
615fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
625fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Add test method number 'num'
635fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
645fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    self.tests.add(TestMethod(num))
655fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
665fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def get_name(self):
675fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
685fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Get the name of this class
695fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
705fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    return "Main"
715fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
725fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def __str__(self):
735fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
745fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Print the MainClass Java code.
755fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
765fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    all_tests = sorted(self.tests)
775fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    test_groups = ""
785fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    for t in all_tests:
795fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain      test_groups += str(t)
805fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    main_func = self.MAIN_FUNCTION_TEMPLATE
815fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
825fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("java"),
835fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain                                           main_func = main_func,
845fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain                                           test_groups = test_groups)
855fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
865fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainclass TestMethod(mixins.Named, mixins.NameComparableMixin):
875fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  """
885fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  A function that represents a test method. Should only be
895fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  constructed by MainClass.add_test_method.
905fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  """
915fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
925fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  TEST_FUNCTION_TEMPLATE = """
935fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  public static void {fname}() {{}}"""
945fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
955fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def __init__(self, farg):
965fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
975fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Initialize a test method for the given argument.
985fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
995fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    self.farg = farg
1005fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
1015fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def get_name(self):
1025fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
1035fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Get the name of this test method.
1045fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
1055fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    return "method{:05d}".format(self.farg)
1065fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
1075fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  def __str__(self):
1085fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
1095fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    Print the Java code of this test method.
1105fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    """
1115fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name())
1125fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
1135fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# Number of generated test methods. This number has been chosen to
1145fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# make sure the number of direct methods in class Main is greater or
1155fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# equal to 2^16, and thus requires an *unsigned* 16-bit (short)
1165fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain# integer to be represented (b/33650497).
1175fa822dd1f22886a25515690fce7f8a4c40701b2Roland LevillainNUM_TEST_METHODS = 32768
1185fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
1195fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillaindef create_test_file():
1205fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  """
1215fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  Creates the object representing the test file. It just needs to be dumped.
1225fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  """
1235fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  mc = MainClass()
1245fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  for i in range(1, NUM_TEST_METHODS + 1):
1255fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    mc.add_test_method(i)
1265fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  return mc
1275fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
1285fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillaindef main(argv):
1295fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  java_dir = Path(argv[1])
1305fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  if not java_dir.exists() or not java_dir.is_dir():
1315fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    print("{} is not a valid Java dir".format(java_dir), file=sys.stderr)
1325fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain    sys.exit(1)
1335fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  mainclass = create_test_file()
1345fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  mainclass.dump(java_dir)
1355fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain
1365fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillainif __name__ == '__main__':
1375fa822dd1f22886a25515690fce7f8a4c40701b2Roland Levillain  main(sys.argv)
138