Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: testing/android/generate_native_test.py

Issue 10051021: apk-based test runner work for android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 # On Android we build unit test bundles as shared libraries. To run
7 # tests, we launch a special "test runner" apk which loads the library
8 # then jumps into it. Since java is required for many tests
9 # (e.g. PathUtils.java), a "pure native" test bundle is inadequate.
10 #
11 # This script, generate_native_test.py, is used to generate the source
12 # for an apk that wraps a unit test shared library bundle. That
13 # allows us to have a single boiler-plate application be used across
14 # all unit test bundles.
bulach 2012/04/12 15:51:42 as above, I'd suggest calling ant and building the
15
16 import logging
17 import optparse
18 import os
19 import re
20 import shutil
21 import sys
22
23
24 class NativeTestApkGenerator(object):
25 """Generate a native test apk source tree.
26
27 TODO(jrg): develop this more so the activity name is replaced as
28 well. That will allow multiple test runners to be installed at the
29 same time. (The complication is that it involves renaming a java
30 class, which implies regeneration of a jni header, and on and on...)
31 """
32
33 # Files or directories we need to copy to create a complete apk test shell.
34 _SOURCE_FILES = ['AndroidManifest.xml',
35 'native_test_apk.xml',
36 'res', # res/values/strings.xml
37 'java', # .../ChromeNativeTestActivity.java
38 ]
39
40 # Files in the destion directory that have a "replaceme" string
41 # which should be replaced by the basename of the shared library.
42 # Note we also update the filename if 'replaceme' is itself found in
43 # the filename.
44 _REPLACEME_FILES = ['AndroidManifest.xml',
45 'native_test_apk.xml',
46 'res/values/strings.xml']
47
48 def __init__(self, native_library, jars, output_directory):
49 self._native_library = native_library
50 self._jars = jars
51 self._output_directory = output_directory
52 self._root_name = None
53 if self._native_library:
54 self._root_name = self._LibraryRoot()
55 logging.warn('root name: %s' % self._root_name)
56
57
58 def _LibraryRoot(self):
59 """Return a root name for a shared library.
60
61 The root name should be suitable for substitution in apk files
62 like the manifest. For example, blah/foo/libbase_unittests.so
63 becomes base_unittests.
64 """
65 rootfinder = re.match('.?lib(.+).so',
66 os.path.basename(self._native_library))
67 if rootfinder:
68 return rootfinder.group(1)
69 else:
70 return None
71
72 def _CopyTemplateFiles(self):
73 """Copy files needed to build a new apk.
74
75 TODO(jrg): add more smarts so we don't change file timestamps if
76 the files don't change?
77 """
78 srcdir = os.path.dirname(os.path.realpath( __file__))
79 if not os.path.exists(self._output_directory):
80 os.makedirs(self._output_directory)
81 for f in self._SOURCE_FILES:
82 src = os.path.join(srcdir, f)
83 dest = os.path.join(self._output_directory, f)
84 if os.path.isfile(src):
85 if os.path.exists(dest):
86 os.remove(dest)
87 logging.warn('%s --> %s' % (src, dest))
88 shutil.copyfile(src, dest)
89 else: # directory
90 if os.path.exists(dest):
91 # One more sanity check since we're deleting a directory...
92 if not '/out/' in dest:
93 raise Exception('Unbelievable output directory; bailing for safety')
bulach 2012/04/12 15:51:42 nit: probably best to do this sanity check at the
John Grabowski 2012/04/13 01:11:37 Makes me feel safer to do it "right before" the rm
94 shutil.rmtree(dest)
95 logging.warn('%s --> %s' % (src, dest))
96 shutil.copytree(src, dest)
97
98 def _ReplaceStrings(self):
99 """Replace 'replaceme' strings in generated files with a root libname.
100
101 If we have no root libname (e.g. no shlib was specified), do nothing.
102 """
103 if not self._root_name:
104 return
105 logging.warn('Replacing \'replaceme\' with ' + self._root_name)
bulach 2012/04/12 15:51:42 nit: use " inside the string, avoids escaping..
John Grabowski 2012/04/13 01:11:37 Done.
106 for f in self._REPLACEME_FILES:
107 dest = os.path.join(self._output_directory, f)
108 contents = open(dest).read()
109 contents = contents.replace('replaceme', self._root_name)
110 dest = dest.replace('replaceme', self._root_name) # update the filename!
111 open(dest, "w").write(contents)
112
113 def _CopyLibraryAndJars(self):
114 """Copy the shlib and jars into the apk (if relevant)"""
bulach 2012/04/12 15:51:42 not sure what you mean "into the apk".. the apk it
John Grabowski 2012/04/13 01:11:37 clarified
115 if self._native_library:
116 destdir = os.path.join(self._output_directory, 'libs/armeabi')
117 if not os.path.exists(destdir):
118 os.makedirs(destdir)
119 dest = os.path.join(destdir, os.path.basename(self._native_library))
120 logging.warn('%s --> %s' % (self._native_library, dest))
121 shutil.copyfile(self._native_library, dest)
122 if self._jars:
123 destdir = os.path.join(self._output_directory, 'libs')
124 if not os.path.exists(destdir):
125 os.makedirs(destdir)
126 for jar in self._jars.split(','):
127 dest = os.path.join(destdir, os.path.basename(jar))
128 logging.warn('%s --> %s' % (jar, dest))
129 shutil.copyfile(jar, dest)
130
131 def CreateBundle(self):
132 self._CopyTemplateFiles()
133 self._ReplaceStrings()
134 self._CopyLibraryAndJars()
135
136
137 def main(argv):
138 parser = optparse.OptionParser()
139 parser.add_option('--verbose',
140 help='Be verbose')
141 parser.add_option('--native_library',
142 help='Full name of native shared library test bundle')
143 parser.add_option('--jars',
144 help='Comma seperated list of jars to include')
bulach 2012/04/12 15:51:42 nit: instead of splitting here, maybe just use --j
John Grabowski 2012/04/13 01:11:37 Done.
145 parser.add_option('--output',
146 help='Output directory for generated files.')
147 options, args = parser.parse_args(argv) # pylint: disable=W0612
bulach 2012/04/12 15:51:42 is W0612 unused locals? would replacing args with
John Grabowski 2012/04/13 01:11:37 Done.
148
149 # It is not an error to specify no native library; the apk should
150 # still be generated and build. It will, however, print
151 # NATIVE_LOADER_FAILED wnen run.
Yaron 2012/04/12 01:29:53 s/wnen/when
John Grabowski 2012/04/13 01:11:37 Done.
152 if not options.output:
153 raise Exception('No output directory specified for generated files')
154
155 if options.verbose:
156 logging.basicConfig(level=logging.DEBUG, format=' %(message)s')
157
158 ntag = NativeTestApkGenerator(native_library=options.native_library,
159 jars=options.jars,
160 output_directory=options.output)
161 ntag.CreateBundle()
162 logging.warn('COMPLETE.')
163
164 if __name__ == '__main__':
165 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698