• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #!/usr/bin/python2.4
2 #
3 #
4 # Copyright 2009, The Android Open Source Project
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #     http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 
18 """Utility to create Android project files for tests."""
19 
20 # python imports
21 import datetime
22 import optparse
23 import os
24 import string
25 import sys
26 
27 # local imports
28 import android_mk
29 import android_manifest
30 
31 
32 class TestsConsts(object):
33   """Constants for test Android.mk and AndroidManifest.xml creation."""
34 
35   MK_BUILD_INCLUDE = "call all-makefiles-under,$(LOCAL_PATH)"
36   MK_BUILD_STRING = "\ninclude $(%s)\n" % MK_BUILD_INCLUDE
37   TEST_MANIFEST_TEMPLATE = """<?xml version="1.0" encoding="utf-8"?>
38 <!-- Copyright (C) $YEAR The Android Open Source Project
39 
40     Licensed under the Apache License, Version 2.0 (the "License");
41     you may not use this file except in compliance with the License.
42     You may obtain a copy of the License at
43 
44          http://www.apache.org/licenses/LICENSE-2.0
45 
46     Unless required by applicable law or agreed to in writing, software
47     distributed under the License is distributed on an "AS IS" BASIS,
48     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49     See the License for the specific language governing permissions and
50     limitations under the License.
51 -->
52 
53 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
54     package="$PACKAGE_NAME.tests">
55 
56     <application>
57         <uses-library android:name="android.test.runner" />
58     </application>
59 
60     <instrumentation android:name="android.test.InstrumentationTestRunner"
61         android:targetPackage="$PACKAGE_NAME"
62         android:label="Tests for $MODULE_NAME">
63     </instrumentation>
64 </manifest>
65 """
66   TEST_MK_TEMPLATE = """LOCAL_PATH := $$(call my-dir)
67 include $$(CLEAR_VARS)
68 
69 LOCAL_MODULE_TAGS := tests
70 
71 LOCAL_JAVA_LIBRARIES := android.test.runner
72 
73 LOCAL_SRC_FILES := $$(call all-java-files-under, src)
74 
75 LOCAL_PACKAGE_NAME := ${MODULE_NAME}Tests${CERTIFICATE}
76 
77 LOCAL_INSTRUMENTATION_FOR := ${MODULE_NAME}
78 
79 LOCAL_SDK_VERSION := current
80 
81 include $$(BUILD_PACKAGE)
82 """
83   TESTS_FOLDER = "tests"
84 
85 
86 def _GenerateTestManifest(manifest, module_name, mapping=None):
87   """Create and populate tests/AndroidManifest.xml with variable values from
88   Android.mk and AndroidManifest.xml.
89 
90   Does nothing if tests/AndroidManifest.xml already exists.
91 
92   Args:
93     manifest: AndroidManifest object for application manifest
94     module_name: module name used for labelling
95     mapping: optional user defined mapping of variable values, replaces values
96         extracted from AndroidManifest.xml
97   Raises:
98     IOError: tests/AndroidManifest.xml cannot be opened for writing
99   """
100   # skip if file already exists
101   tests_path = "%s/%s" % (manifest.GetAppPath(), TestsConsts.TESTS_FOLDER)
102   tests_manifest_path = "%s/%s" % (tests_path, manifest.FILENAME)
103   if os.path.exists(tests_manifest_path):
104     _PrintMessage("%s already exists, not overwritten" % tests_manifest_path)
105     return
106 
107   if not mapping:
108     package_name = manifest.GetPackageName()
109     mapping = {"PACKAGE_NAME":package_name, "MODULE_NAME":module_name,
110                "YEAR":datetime.date.today().year}
111   output = string.Template(TestsConsts.TEST_MANIFEST_TEMPLATE).substitute(mapping)
112 
113   # create tests folder if not existent
114   if not os.path.exists(tests_path):
115     os.mkdir(tests_path)
116 
117   # write tests/AndroidManifest.xml
118   tests_manifest = open(tests_manifest_path, mode="w")
119   tests_manifest.write(output)
120   tests_manifest.close()
121   _PrintMessage("Created %s" % tests_manifest_path)
122 
123 
124 def _GenerateTestMK(mk, app_path, mapping=None):
125   """Create and populate tests/Android.mk with variable values from Android.mk.
126 
127   Does nothing if tests/Android.mk already exists.
128 
129   Args:
130     mk: AndroidMK object for application makefile
131     app_path: path to the application being tested
132     mapping: optional user defined mapping of variable values, replaces
133         values stored in mk
134   Raises:
135     IOError: tests/Android.mk cannot be opened for writing
136   """
137   # skip if file already exists
138   tests_path = "%s/%s" % (app_path, TestsConsts.TESTS_FOLDER)
139   tests_mk_path = "%s/%s" % (tests_path, mk.FILENAME)
140   if os.path.exists(tests_mk_path):
141     _PrintMessage("%s already exists, not overwritten" % tests_mk_path)
142     return
143 
144   # append test build if not existent in makefile
145   if not mk.HasInclude(TestsConsts.MK_BUILD_INCLUDE):
146     mk_path = "%s/%s" % (app_path, mk.FILENAME)
147     mk_file = open(mk_path, mode="a")
148     mk_file.write(TestsConsts.MK_BUILD_STRING)
149     mk_file.close()
150 
151   # construct tests/Android.mk
152   # include certificate definition if existent in makefile
153   certificate = mk.GetVariable(mk.CERTIFICATE)
154   if certificate:
155     cert_definition = ("\n%s := %s" % (mk.CERTIFICATE, certificate))
156   else:
157     cert_definition = ""
158   if not mapping:
159     module_name = mk.GetVariable(mk.PACKAGE_NAME)
160     mapping = {"MODULE_NAME":module_name, "CERTIFICATE":cert_definition}
161   output = string.Template(TestsConsts.TEST_MK_TEMPLATE).substitute(mapping)
162 
163   # create tests folder if not existent
164   if not os.path.exists(tests_path):
165     os.mkdir(tests_path)
166 
167   # write tests/Android.mk to disk
168   tests_mk = open(tests_mk_path, mode="w")
169   tests_mk.write(output)
170   tests_mk.close()
171   _PrintMessage("Created %s" % tests_mk_path)
172 
173 
174 def _ParseArgs(argv):
175   """Parse the command line arguments.
176 
177   Args:
178     argv: the list of command line arguments
179   Returns:
180     a tuple of options and individual command line arguments.
181   """
182   parser = optparse.OptionParser(usage="%s <app_path>" % sys.argv[0])
183   options, args = parser.parse_args(argv)
184   if len(args) < 1:
185     _PrintError("Error: Incorrect syntax")
186     parser.print_usage()
187     sys.exit()
188   return (options, args)
189 
190 
191 def _PrintMessage(msg):
192   print >> sys.stdout, msg
193 
194 
195 def _PrintError(msg):
196   print >> sys.stderr, msg
197 
198 
199 def _ValidateInputFiles(mk, manifest):
200   """Verify that required variables are defined in input files.
201 
202   Args:
203     mk: AndroidMK object for application makefile
204     manifest: AndroidManifest object for application manifest
205   Raises:
206     RuntimeError: mk does not define LOCAL_PACKAGE_NAME or
207                   manifest does not define package variable
208   """
209   module_name = mk.GetVariable(mk.PACKAGE_NAME)
210   if not module_name:
211     raise RuntimeError("Variable %s missing from %s" %
212         (mk.PACKAGE_NAME, mk.FILENAME))
213 
214   package_name = manifest.GetPackageName()
215   if not package_name:
216     raise RuntimeError("Variable package missing from %s" % manifest.FILENAME)
217 
218 
219 def main(argv):
220   options, args = _ParseArgs(argv)
221   app_path = args[0];
222 
223   if not os.path.exists(app_path):
224     _PrintError("Error: Application path %s not found" % app_path)
225     sys.exit()
226 
227   try:
228     mk = android_mk.CreateAndroidMK(path=app_path)
229     manifest = android_manifest.AndroidManifest(app_path=app_path)
230     _ValidateInputFiles(mk, manifest)
231 
232     module_name = mk.GetVariable(mk.PACKAGE_NAME)
233     _GenerateTestMK(mk, app_path)
234     _GenerateTestManifest(manifest, module_name)
235   except Exception, e:
236     _PrintError("Error: %s" % e)
237     _PrintError("Error encountered, script aborted")
238     sys.exit()
239 
240   src_path = app_path + "/tests/src"
241   if not os.path.exists(src_path):
242     os.mkdir(src_path)
243 
244 
245 if __name__ == "__main__":
246   main(sys.argv[1:])
247