blob: 2fc3a3cffde6c0f15d8e5b253f374264097062c3 [file] [log] [blame]
Jack Wang2abd80a2009-06-29 18:47:03 -07001#!/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
21import datetime
22import optparse
23import os
24import string
25import sys
26
27# local imports
28import android_mk
29import android_manifest
30
31
32class 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)
67include $$(CLEAR_VARS)
68
69LOCAL_MODULE_TAGS := tests
70
71LOCAL_JAVA_LIBRARIES := android.test.runner
72
73LOCAL_SRC_FILES := $$(call all-java-files-under, src)
74
75LOCAL_PACKAGE_NAME := ${MODULE_NAME}Tests${CERTIFICATE}
76
77LOCAL_INSTRUMENTATION_FOR := ${MODULE_NAME}
78
79LOCAL_SDK_VERSION := current
80
81include $$(BUILD_PACKAGE)
82"""
83 TESTS_FOLDER = "tests"
84
85
86def _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.app_path, 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
124def _GenerateTestMK(mk, 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 mapping: optional user defined mapping of variable values, replaces
132 values stored in mk
133 Raises:
134 IOError: tests/Android.mk cannot be opened for writing
135 """
136 # skip if file already exists
137 tests_path = "%s/%s" % (mk.app_path, TestsConsts.TESTS_FOLDER)
138 tests_mk_path = "%s/%s" % (tests_path, mk.FILENAME)
139 if os.path.exists(tests_mk_path):
140 _PrintMessage("%s already exists, not overwritten" % tests_mk_path)
141 return
142
143 # append test build if not existent in makefile
144 if not mk.HasInclude(TestsConsts.MK_BUILD_INCLUDE):
145 mk_path = "%s/%s" % (mk.app_path, mk.FILENAME)
146 mk_file = open(mk_path, mode="a")
147 mk_file.write(TestsConsts.MK_BUILD_STRING)
148 mk_file.close()
149
150 # construct tests/Android.mk
151 # include certificate definition if existent in makefile
152 certificate = mk.GetVariable(mk.CERTIFICATE)
153 if certificate:
154 cert_definition = ("\n%s := %s" % (mk.CERTIFICATE, certificate))
155 else:
156 cert_definition = ""
157 if not mapping:
158 module_name = mk.GetVariable(mk.PACKAGE_NAME)
159 mapping = {"MODULE_NAME":module_name, "CERTIFICATE":cert_definition}
160 output = string.Template(TestsConsts.TEST_MK_TEMPLATE).substitute(mapping)
161
162 # create tests folder if not existent
163 if not os.path.exists(tests_path):
164 os.mkdir(tests_path)
165
166 # write tests/Android.mk to disk
167 tests_mk = open(tests_mk_path, mode="w")
168 tests_mk.write(output)
169 tests_mk.close()
170 _PrintMessage("Created %s" % tests_mk_path)
171
172
173def _ParseArgs(argv):
174 """Parse the command line arguments.
175
176 Args:
177 argv: the list of command line arguments
178 Returns:
179 a tuple of options and individual command line arguments.
180 """
181 parser = optparse.OptionParser(usage="%s <app_path>" % sys.argv[0])
182 options, args = parser.parse_args(argv)
183 if len(args) < 1:
184 _PrintError("Error: Incorrect syntax")
185 parser.print_usage()
186 sys.exit()
187 return (options, args)
188
189
190def _PrintMessage(msg):
191 print >> sys.stdout, msg
192
193
194def _PrintError(msg):
195 print >> sys.stderr, msg
196
197
198def _ValidateInputFiles(mk, manifest):
199 """Verify that required variables are defined in input files.
200
201 Args:
202 mk: AndroidMK object for application makefile
203 manifest: AndroidManifest object for application manifest
204 Raises:
205 RuntimeError: mk does not define LOCAL_PACKAGE_NAME or
206 manifest does not define package variable
207 """
208 module_name = mk.GetVariable(mk.PACKAGE_NAME)
209 if not module_name:
210 raise RuntimeError("Variable %s missing from %s" %
211 (mk.PACKAGE_NAME, mk.FILENAME))
212
213 package_name = manifest.GetPackageName()
214 if not package_name:
215 raise RuntimeError("Variable package missing from %s" % manifest.FILENAME)
216
217
218def main(argv):
219 options, args = _ParseArgs(argv)
220 app_path = args[0];
221
222 if not os.path.exists(app_path):
223 _PrintError("Error: Application path %s not found" % app_path)
224 sys.exit()
225
226 try:
227 mk = android_mk.AndroidMK(app_path=app_path)
228 manifest = android_manifest.AndroidManifest(app_path=app_path)
229 _ValidateInputFiles(mk, manifest)
230
231 module_name = mk.GetVariable(mk.PACKAGE_NAME)
232 _GenerateTestMK(mk)
233 _GenerateTestManifest(manifest, module_name)
234 except Exception, e:
235 _PrintError("Error: %s" % e)
236 _PrintError("Error encountered, script aborted")
237 sys.exit()
238
239 src_path = app_path + "/tests/src"
240 if not os.path.exists(src_path):
241 os.mkdir(src_path)
242
243
244if __name__ == "__main__":
245 main(sys.argv[1:])