blob: fa6ea1baac75fa6da33f350d028039e0adfe993e [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))
Brett Chabot8ac51182012-09-19 07:35:35 -0700144 # TODO: remove this logic, and rely on caller to collapse build
145 # paths via make_tree
146
Brett Chabotbb5918e2011-06-17 17:07:12 -0700147 # Try to build as much of original path as possible, so
148 # keep track of upper-most parent directory where Android.mk was found
149 # that has rule to build sub-directory makefiles.
150 # this is also necessary in case of overlapping tests
151 # ie if a test exists at 'foo' directory and 'foo/sub', attempting to
152 # build both 'foo' and 'foo/sub' will fail.
153
Brett Chabot8ac51182012-09-19 07:35:35 -0700154 if android_mk_parser.IncludesMakefilesUnder():
Brett Chabotbb5918e2011-06-17 17:07:12 -0700155 # found rule to build sub-directories. The parent path can be used,
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700156 # or if not set, use current path
Brett Chabotbb5918e2011-06-17 17:07:12 -0700157 if not upstream_build_path:
158 upstream_build_path = self._MakePathRelativeToBuild(path)
Brett Chabot12c6d3f2010-07-29 15:27:30 -0700159 else:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700160 upstream_build_path = None
161 for filename in os.listdir(path):
162 self._FindSubTests(os.path.join(path, filename), tests,
163 upstream_build_path)
Brett Chabot59b47782009-10-21 17:23:01 -0700164 return tests
165
166 def _FindUpstreamTests(self, path):
167 """Find tests defined upward from given path.
168
169 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700170 path: the location to start searching.
Brett Chabot59b47782009-10-21 17:23:01 -0700171
172 Returns:
173 list of test_suite.AbstractTestSuite found, may be empty
174 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700175 factory = self._FindUpstreamTestFactory(path)
176 if factory:
177 return factory.CreateTests(sub_tests_path=path)
178 else:
179 return []
Brett Chabot59b47782009-10-21 17:23:01 -0700180
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700181 def _GetTestFactory(self, android_mk_parser, path, build_path):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700182 """Get the test factory for given makefile.
Brett Chabot59b47782009-10-21 17:23:01 -0700183
Brett Chabotbb5918e2011-06-17 17:07:12 -0700184 If given path is a valid tests build path, will return the TestFactory
185 for creating tests.
Brett Chabot59b47782009-10-21 17:23:01 -0700186
187 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700188 android_mk_parser: the android mk to evaluate
189 path: the filesystem path of the makefile
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700190 build_path: filesystem path for the directory
191 to build when running tests, relative to source root.
Brett Chabot59b47782009-10-21 17:23:01 -0700192
193 Returns:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700194 the TestFactory or None if path is not a valid tests build path
Brett Chabot59b47782009-10-21 17:23:01 -0700195 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700196 if android_mk_parser.HasGTest():
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700197 return gtest.GTestFactory(path, build_path)
Brett Chabotecfcc7d2011-07-17 14:04:37 -0700198 elif instrumentation_test.HasInstrumentationTest(path):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700199 return instrumentation_test.InstrumentationTestFactory(path,
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700200 build_path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700201 else:
202 # somewhat unusual, but will continue searching
203 logger.SilentLog('Found makefile at %s, but did not detect any tests.'
204 % path)
Brett Chabot59b47782009-10-21 17:23:01 -0700205
Brett Chabot59b47782009-10-21 17:23:01 -0700206 return None
207
Brett Chabotbb5918e2011-06-17 17:07:12 -0700208 def _GetTestFactoryForPath(self, path):
209 """Get the test factory for given path.
Brett Chabot59b47782009-10-21 17:23:01 -0700210
Brett Chabotbb5918e2011-06-17 17:07:12 -0700211 If given path is a valid tests build path, will return the TestFactory
212 for creating tests.
Brett Chabot59b47782009-10-21 17:23:01 -0700213
214 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700215 path: the filesystem path to evaluate
Brett Chabot59b47782009-10-21 17:23:01 -0700216
217 Returns:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700218 the TestFactory or None if path is not a valid tests build path
Brett Chabot59b47782009-10-21 17:23:01 -0700219 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700220 android_mk_parser = android_mk.CreateAndroidMK(path)
221 if android_mk_parser:
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700222 build_path = self._MakePathRelativeToBuild(path)
223 return self._GetTestFactory(android_mk_parser, path, build_path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700224 else:
225 return None
Brett Chabot59b47782009-10-21 17:23:01 -0700226
Brett Chabotbb5918e2011-06-17 17:07:12 -0700227 def _FindUpstreamTestFactory(self, path):
228 """Recursively searches filesystem upwards for a test factory.
Brett Chabot59b47782009-10-21 17:23:01 -0700229
230 Args:
231 path: file system path to search
232
233 Returns:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700234 the TestFactory found or None
Brett Chabot59b47782009-10-21 17:23:01 -0700235 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700236 factory = self._GetTestFactoryForPath(path)
237 if factory:
238 return factory
Brett Chabot59b47782009-10-21 17:23:01 -0700239 dirpath = os.path.dirname(path)
240 if self._IsPathInBuildTree(path):
Brett Chabotbb5918e2011-06-17 17:07:12 -0700241 return self._FindUpstreamTestFactory(dirpath)
242 logger.Log('A tests Android.mk was not found')
Brett Chabot59b47782009-10-21 17:23:01 -0700243 return None
244
Brett Chabotbb5918e2011-06-17 17:07:12 -0700245 def _CreateSuites(self, android_mk_parser, path, upstream_build_path):
246 """Creates TestSuites from a AndroidMK.
Brett Chabot59b47782009-10-21 17:23:01 -0700247
248 Args:
Brett Chabotbb5918e2011-06-17 17:07:12 -0700249 android_mk_parser: the AndroidMK
250 path: absolute file system path of the makefile to evaluate
251 upstream_build_path: the build path to use for test. This can be
252 different than the 'path', in cases where an upstream makefile
253 is being used.
Brett Chabot59b47782009-10-21 17:23:01 -0700254
255 Returns:
256 the list of tests created
257 """
Brett Chabotbb5918e2011-06-17 17:07:12 -0700258 factory = self._GetTestFactory(android_mk_parser, path,
Brett Chabotb0fd2cf2011-08-01 16:11:43 -0700259 build_path=upstream_build_path)
Brett Chabotbb5918e2011-06-17 17:07:12 -0700260 if factory:
261 return factory.CreateTests(path)
262 else:
263 return []