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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: testing/android/generate_native_test.py
diff --git a/testing/android/generate_native_test.py b/testing/android/generate_native_test.py
new file mode 100755
index 0000000000000000000000000000000000000000..5f027d1491052c901b16cca24ef921906a7f46a6
--- /dev/null
+++ b/testing/android/generate_native_test.py
@@ -0,0 +1,165 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# On Android we build unit test bundles as shared libraries. To run
+# tests, we launch a special "test runner" apk which loads the library
+# then jumps into it. Since java is required for many tests
+# (e.g. PathUtils.java), a "pure native" test bundle is inadequate.
+#
+# This script, generate_native_test.py, is used to generate the source
+# for an apk that wraps a unit test shared library bundle. That
+# allows us to have a single boiler-plate application be used across
+# all unit test bundles.
bulach 2012/04/12 15:51:42 as above, I'd suggest calling ant and building the
+
+import logging
+import optparse
+import os
+import re
+import shutil
+import sys
+
+
+class NativeTestApkGenerator(object):
+ """Generate a native test apk source tree.
+
+ TODO(jrg): develop this more so the activity name is replaced as
+ well. That will allow multiple test runners to be installed at the
+ same time. (The complication is that it involves renaming a java
+ class, which implies regeneration of a jni header, and on and on...)
+ """
+
+ # Files or directories we need to copy to create a complete apk test shell.
+ _SOURCE_FILES = ['AndroidManifest.xml',
+ 'native_test_apk.xml',
+ 'res', # res/values/strings.xml
+ 'java', # .../ChromeNativeTestActivity.java
+ ]
+
+ # Files in the destion directory that have a "replaceme" string
+ # which should be replaced by the basename of the shared library.
+ # Note we also update the filename if 'replaceme' is itself found in
+ # the filename.
+ _REPLACEME_FILES = ['AndroidManifest.xml',
+ 'native_test_apk.xml',
+ 'res/values/strings.xml']
+
+ def __init__(self, native_library, jars, output_directory):
+ self._native_library = native_library
+ self._jars = jars
+ self._output_directory = output_directory
+ self._root_name = None
+ if self._native_library:
+ self._root_name = self._LibraryRoot()
+ logging.warn('root name: %s' % self._root_name)
+
+
+ def _LibraryRoot(self):
+ """Return a root name for a shared library.
+
+ The root name should be suitable for substitution in apk files
+ like the manifest. For example, blah/foo/libbase_unittests.so
+ becomes base_unittests.
+ """
+ rootfinder = re.match('.?lib(.+).so',
+ os.path.basename(self._native_library))
+ if rootfinder:
+ return rootfinder.group(1)
+ else:
+ return None
+
+ def _CopyTemplateFiles(self):
+ """Copy files needed to build a new apk.
+
+ TODO(jrg): add more smarts so we don't change file timestamps if
+ the files don't change?
+ """
+ srcdir = os.path.dirname(os.path.realpath( __file__))
+ if not os.path.exists(self._output_directory):
+ os.makedirs(self._output_directory)
+ for f in self._SOURCE_FILES:
+ src = os.path.join(srcdir, f)
+ dest = os.path.join(self._output_directory, f)
+ if os.path.isfile(src):
+ if os.path.exists(dest):
+ os.remove(dest)
+ logging.warn('%s --> %s' % (src, dest))
+ shutil.copyfile(src, dest)
+ else: # directory
+ if os.path.exists(dest):
+ # One more sanity check since we're deleting a directory...
+ if not '/out/' in dest:
+ 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
+ shutil.rmtree(dest)
+ logging.warn('%s --> %s' % (src, dest))
+ shutil.copytree(src, dest)
+
+ def _ReplaceStrings(self):
+ """Replace 'replaceme' strings in generated files with a root libname.
+
+ If we have no root libname (e.g. no shlib was specified), do nothing.
+ """
+ if not self._root_name:
+ return
+ 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.
+ for f in self._REPLACEME_FILES:
+ dest = os.path.join(self._output_directory, f)
+ contents = open(dest).read()
+ contents = contents.replace('replaceme', self._root_name)
+ dest = dest.replace('replaceme', self._root_name) # update the filename!
+ open(dest, "w").write(contents)
+
+ def _CopyLibraryAndJars(self):
+ """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
+ if self._native_library:
+ destdir = os.path.join(self._output_directory, 'libs/armeabi')
+ if not os.path.exists(destdir):
+ os.makedirs(destdir)
+ dest = os.path.join(destdir, os.path.basename(self._native_library))
+ logging.warn('%s --> %s' % (self._native_library, dest))
+ shutil.copyfile(self._native_library, dest)
+ if self._jars:
+ destdir = os.path.join(self._output_directory, 'libs')
+ if not os.path.exists(destdir):
+ os.makedirs(destdir)
+ for jar in self._jars.split(','):
+ dest = os.path.join(destdir, os.path.basename(jar))
+ logging.warn('%s --> %s' % (jar, dest))
+ shutil.copyfile(jar, dest)
+
+ def CreateBundle(self):
+ self._CopyTemplateFiles()
+ self._ReplaceStrings()
+ self._CopyLibraryAndJars()
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('--verbose',
+ help='Be verbose')
+ parser.add_option('--native_library',
+ help='Full name of native shared library test bundle')
+ parser.add_option('--jars',
+ 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.
+ parser.add_option('--output',
+ help='Output directory for generated files.')
+ 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.
+
+ # It is not an error to specify no native library; the apk should
+ # still be generated and build. It will, however, print
+ # NATIVE_LOADER_FAILED wnen run.
Yaron 2012/04/12 01:29:53 s/wnen/when
John Grabowski 2012/04/13 01:11:37 Done.
+ if not options.output:
+ raise Exception('No output directory specified for generated files')
+
+ if options.verbose:
+ logging.basicConfig(level=logging.DEBUG, format=' %(message)s')
+
+ ntag = NativeTestApkGenerator(native_library=options.native_library,
+ jars=options.jars,
+ output_directory=options.output)
+ ntag.CreateBundle()
+ logging.warn('COMPLETE.')
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))

Powered by Google App Engine
This is Rietveld 408576698