1#! /usr/bin/python3
2#
3# Copyright (C) 2017 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""
18Generate Java test files for test 648-many-direct-methods.
19"""
20
21import os
22import sys
23from pathlib import Path
24
25BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
26if BUILD_TOP is None:
27  print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
28  sys.exit(1)
29
30# Allow us to import utils and mixins.
31sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
32
33from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
34import testgen.mixins as mixins
35
36class MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
37  """
38  A Main.java file containing the Main class and the main function. It will run
39  all the test functions we have.
40  """
41
42  MAIN_CLASS_TEMPLATE = """{copyright}
43public class Main {{
44{main_func}
45{test_groups}
46
47}}"""
48
49  MAIN_FUNCTION_TEMPLATE = """
50  public static void main(String[] args) {
51    System.out.println("passed");
52  }"""
53
54  def __init__(self):
55    """
56    Initialize this MainClass. We start out with no tests.
57    """
58    self.tests = set()
59
60  def add_test_method(self, num):
61    """
62    Add test method number 'num'
63    """
64    self.tests.add(TestMethod(num))
65
66  def get_name(self):
67    """
68    Get the name of this class
69    """
70    return "Main"
71
72  def __str__(self):
73    """
74    Print the MainClass Java code.
75    """
76    all_tests = sorted(self.tests)
77    test_groups = ""
78    for t in all_tests:
79      test_groups += str(t)
80    main_func = self.MAIN_FUNCTION_TEMPLATE
81
82    return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("java"),
83                                           main_func = main_func,
84                                           test_groups = test_groups)
85
86class TestMethod(mixins.Named, mixins.NameComparableMixin):
87  """
88  A function that represents a test method. Should only be
89  constructed by MainClass.add_test_method.
90  """
91
92  TEST_FUNCTION_TEMPLATE = """
93  public static void {fname}() {{}}"""
94
95  def __init__(self, farg):
96    """
97    Initialize a test method for the given argument.
98    """
99    self.farg = farg
100
101  def get_name(self):
102    """
103    Get the name of this test method.
104    """
105    return "method{:05d}".format(self.farg)
106
107  def __str__(self):
108    """
109    Print the Java code of this test method.
110    """
111    return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name())
112
113# Number of generated test methods. This number has been chosen to
114# make sure the number of direct methods in class Main is greater or
115# equal to 2^16, and thus requires an *unsigned* 16-bit (short)
116# integer to be represented (b/33650497).
117NUM_TEST_METHODS = 32768
118
119def create_test_file():
120  """
121  Creates the object representing the test file. It just needs to be dumped.
122  """
123  mc = MainClass()
124  for i in range(1, NUM_TEST_METHODS + 1):
125    mc.add_test_method(i)
126  return mc
127
128def main(argv):
129  java_dir = Path(argv[1])
130  if not java_dir.exists() or not java_dir.is_dir():
131    print("{} is not a valid Java dir".format(java_dir), file=sys.stderr)
132    sys.exit(1)
133  mainclass = create_test_file()
134  mainclass.dump(java_dir)
135
136if __name__ == '__main__':
137  main(sys.argv)
138