• 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
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:])
246