blob: 572f8b6a49fb1b9a49005486049e06406d4a5b1b [file] [log] [blame]
Brett Chabot59b47782009-10-21 17:23:01 -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 find instrumentation test definitions from file system."""
19
20# python imports
21import os
Brett Chabot59b47782009-10-21 17:23:01 -070022
23# local imports
24import android_build
Brett Chabot59b47782009-10-21 17:23:01 -070025import android_mk
Brett Chabotbb5918e2011-06-17 17:07:12 -070026import gtest
Brett Chabot59b47782009-10-21 17:23:01 -070027import instrumentation_test
28import logger
29
30
31class TestWalker(object):
Brett Chabotbb5918e2011-06-17 17:07:12 -070032 """Finds Android tests from filesystem."""
Brett Chabot59b47782009-10-21 17:23:01 -070033
34 def FindTests(self, path):
Brett Chabotbb5918e2011-06-17 17:07:12 -070035 """Gets list of Android tests found at given path.
Brett Chabot59b47782009-10-21 17:23:01 -070036
Brett Chabotbb5918e2011-06-17 17:07:12 -070037 Tests are created from info found in Android.mk and AndroidManifest.xml
38 files relative to the given path.
39
40 Currently supported tests are:
41 - Android application tests run via instrumentation
42 - native C/C++ tests using GTest framework. (note Android.mk must follow
43 expected GTest template)
Brett Chabot59b47782009-10-21 17:23:01 -070044
45 FindTests will first scan sub-folders of path for tests. If none are found,
Brett Chabotbb5918e2011-06-17 17:07:12 -070046 it will scan the file system upwards until a valid test Android.mk is found
Brett Chabot59b47782009-10-21 17:23:01 -070047 or the Android build root is reached.
48
49 Some sample values for path:
50 - a parent directory containing many tests:
51 ie development/samples will return tests for instrumentation's in ApiDemos,
52 ApiDemos/tests, Notepad/tests etc
53 - a java test class file
54 ie ApiDemos/tests/src/../ApiDemosTest.java will return a test for
55 the instrumentation in ApiDemos/tests, with the class name filter set to
56 ApiDemosTest
57 - a java package directory
58 ie ApiDemos/tests/src/com/example/android/apis will return a test for
59 the instrumentation in ApiDemos/tests, with the java package filter set
60 to com.example.android.apis.
61
Brett Chabotbb5918e2011-06-17 17:07:12 -070062 TODO: add GTest examples
63
Brett Chabot59b47782009-10-21 17:23:01 -070064 Args:
65 path: file system path to search
66
67 Returns:
68 list of test suites that support operations defined by
69 test_suite.AbstractTestSuite
70 """
71 if not os.path.exists(path):
72 logger.Log('%s does not exist' % path)
73 return []
Brian Carlstrom90218ac2010-04-09 16:29:17 -070074 realpath = os.path.realpath(path)
Brett Chabot59b47782009-10-21 17:23:01 -070075 # ensure path is in ANDROID_BUILD_ROOT
Brian Carlstrom90218ac2010-04-09 16:29:17 -070076 self._build_top = os.path.realpath(android_build.GetTop())
77 if not self._IsPathInBuildTree(realpath):
Brett Chabot59b47782009-10-21 17:23:01 -070078 logger.Log('%s is not a sub-directory of build root %s' %
79 (path, self._build_top))
80 return []
81
82 # first, assume path is a parent directory, which specifies to run all
83 # tests within this directory
Brian Carlstrom90218ac2010-04-09 16:29:17 -070084 tests = self._FindSubTests(realpath, [])
Brett Chabot59b47782009-10-21 17:23:01 -070085 if not tests:
86 logger.SilentLog('No tests found within %s, searching upwards' % path)
Brian Carlstrom90218ac2010-04-09 16:29:17 -070087 tests = self._FindUpstreamTests(realpath)
Brett Chabot59b47782009-10-21 17:23:01 -070088 return tests
89
90 def _IsPathInBuildTree(self, path):
91 """Return true if given path is within current Android build tree.
92
93 Args:
94 path: absolute file system path
95
96 Returns:
97 True if path is within Android build tree
98 """
99 return os.path.commonprefix([self._build_top, path]) == self._build_top
100
101 def _MakePathRelativeToBuild(self, path):
102 """Convert given path to one relative to build tree root.
103
104 Args:
105 path: absolute file system path to convert.
106
107 Returns:
108 The converted path relative to build tree root.
109
110 Raises:
111 ValueError: if path is not within build tree
112 """
113 if not self._IsPathInBuildTree(path):
114 raise ValueError
115 build_path_len = len(self._build_top) + 1
116 # return string with common build_path removed
117 return path[build_path_len:]
118
Brett Chabotbb5918e2011-06-17 17:07:12 -0700119 def _FindSubTests(self, path, tests, upstream_build_path=None):
Brett Chabot59b47782009-10-21 17:23:01 -0700120 """Recursively finds all tests within given path.
121
122 Args:
123 path: absolute file system path to check
124 tests: current list of found tests
Brett Chabotbb5918e2011-06-17 17:07:12 -0700125 upstream_build_path: the parent directory where Android.mk that builds
126 sub-folders was found
Brett Chabot59b47782009-10-21 17:23:01 -0700127
128 Returns:
129 updated list of tests
130 """
131 if not os.path.isdir(path):
132 return tests
Brett Chabotbb5918e2011-06-17 17:07:12 -0700133 android_mk_parser = android_mk.CreateAndroidMK(path)
134 if android_mk_parser:
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700135 build_rel_path = self._MakePathRelativeToBuild(path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700136 if not upstream_build_path:
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700137 # haven't found a parent makefile which builds this dir. Use current
138 # dir as build path
Brett Chabotbb5918e2011-06-17 17:07:12 -0700139 tests.extend(self._CreateSuites(
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700140 android_mk_parser, path, build_rel_path))
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700141 else:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700142 tests.extend(self._CreateSuites(android_mk_parser, path,
143 upstream_build_path))
144 # Try to build as much of original path as possible, so
145 # keep track of upper-most parent directory where Android.mk was found
146 # that has rule to build sub-directory makefiles.
147 # this is also necessary in case of overlapping tests
148 # ie if a test exists at 'foo' directory and 'foo/sub', attempting to
149 # build both 'foo' and 'foo/sub' will fail.
150
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700151 if android_mk_parser.HasInclude('call all-makefiles-under,$(LOCAL_PATH)'):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700152 # found rule to build sub-directories. The parent path can be used,
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700153 # or if not set, use current path
Brett Chabotbb5918e2011-06-17 17:07:12 -0700154 if not upstream_build_path:
155 upstream_build_path = self._MakePathRelativeToBuild(path)
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700156 else:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700157 upstream_build_path = None
158 for filename in os.listdir(path):
159 self._FindSubTests(os.path.join(path, filename), tests,
160 upstream_build_path)
Brett Chabot59b47782009-10-21 17:23:01 -0700161 return tests
162
163 def _FindUpstreamTests(self, path):
164 """Find tests defined upward from given path.
165
166 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700167 path: the location to start searching.
Brett Chabot59b47782009-10-21 17:23:01 -0700168
169 Returns:
170 list of test_suite.AbstractTestSuite found, may be empty
171 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700172 factory = self._FindUpstreamTestFactory(path)
173 if factory:
174 return factory.CreateTests(sub_tests_path=path)
175 else:
176 return []
Brett Chabot59b47782009-10-21 17:23:01 -0700177
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700178 def _GetTestFactory(self, android_mk_parser, path, build_path):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700179 """Get the test factory for given makefile.
Brett Chabot59b47782009-10-21 17:23:01 -0700180
Brett Chabotbb5918e2011-06-17 17:07:12 -0700181 If given path is a valid tests build path, will return the TestFactory
182 for creating tests.
Brett Chabot59b47782009-10-21 17:23:01 -0700183
184 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700185 android_mk_parser: the android mk to evaluate
186 path: the filesystem path of the makefile
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700187 build_path: filesystem path for the directory
188 to build when running tests, relative to source root.
Brett Chabot59b47782009-10-21 17:23:01 -0700189
190 Returns:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700191 the TestFactory or None if path is not a valid tests build path
Brett Chabot59b47782009-10-21 17:23:01 -0700192 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700193 if android_mk_parser.HasGTest():
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700194 return gtest.GTestFactory(path, build_path)
Brett Chabotecfcc7d2011-07-17 14:04:37 -0700195 elif instrumentation_test.HasInstrumentationTest(path):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700196 return instrumentation_test.InstrumentationTestFactory(path,
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700197 build_path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700198 else:
199 # somewhat unusual, but will continue searching
200 logger.SilentLog('Found makefile at %s, but did not detect any tests.'
201 % path)
Brett Chabot59b47782009-10-21 17:23:01 -0700202
Brett Chabot59b47782009-10-21 17:23:01 -0700203 return None
204
Brett Chabotbb5918e2011-06-17 17:07:12 -0700205 def _GetTestFactoryForPath(self, path):
206 """Get the test factory for given path.
Brett Chabot59b47782009-10-21 17:23:01 -0700207
Brett Chabotbb5918e2011-06-17 17:07:12 -0700208 If given path is a valid tests build path, will return the TestFactory
209 for creating tests.
Brett Chabot59b47782009-10-21 17:23:01 -0700210
211 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700212 path: the filesystem path to evaluate
Brett Chabot59b47782009-10-21 17:23:01 -0700213
214 Returns:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700215 the TestFactory or None if path is not a valid tests build path
Brett Chabot59b47782009-10-21 17:23:01 -0700216 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700217 android_mk_parser = android_mk.CreateAndroidMK(path)
218 if android_mk_parser:
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700219 build_path = self._MakePathRelativeToBuild(path)
220 return self._GetTestFactory(android_mk_parser, path, build_path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700221 else:
222 return None
Brett Chabot59b47782009-10-21 17:23:01 -0700223
Brett Chabotbb5918e2011-06-17 17:07:12 -0700224 def _FindUpstreamTestFactory(self, path):
225 """Recursively searches filesystem upwards for a test factory.
Brett Chabot59b47782009-10-21 17:23:01 -0700226
227 Args:
228 path: file system path to search
229
230 Returns:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700231 the TestFactory found or None
Brett Chabot59b47782009-10-21 17:23:01 -0700232 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700233 factory = self._GetTestFactoryForPath(path)
234 if factory:
235 return factory
Brett Chabot59b47782009-10-21 17:23:01 -0700236 dirpath = os.path.dirname(path)
237 if self._IsPathInBuildTree(path):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700238 return self._FindUpstreamTestFactory(dirpath)
239 logger.Log('A tests Android.mk was not found')
Brett Chabot59b47782009-10-21 17:23:01 -0700240 return None
241
Brett Chabotbb5918e2011-06-17 17:07:12 -0700242 def _CreateSuites(self, android_mk_parser, path, upstream_build_path):
243 """Creates TestSuites from a AndroidMK.
Brett Chabot59b47782009-10-21 17:23:01 -0700244
245 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700246 android_mk_parser: the AndroidMK
247 path: absolute file system path of the makefile to evaluate
248 upstream_build_path: the build path to use for test. This can be
249 different than the 'path', in cases where an upstream makefile
250 is being used.
Brett Chabot59b47782009-10-21 17:23:01 -0700251
252 Returns:
253 the list of tests created
254 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700255 factory = self._GetTestFactory(android_mk_parser, path,
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700256 build_path=upstream_build_path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700257 if factory:
258 return factory.CreateTests(path)
259 else:
260 return []