1a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond#!/usr/bin/env python
25bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond
35bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Copyright (C) 2016 The Android Open Source Project
45bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#
55bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Licensed under the Apache License, Version 2.0 (the "License");
65bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# you may not use this file except in compliance with the License.
75bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# You may obtain a copy of the License at
85bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#
95bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#      http://www.apache.org/licenses/LICENSE-2.0
105bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond#
115bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Unless required by applicable law or agreed to in writing, software
125bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# distributed under the License is distributed on an "AS IS" BASIS,
135bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# See the License for the specific language governing permissions and
155bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# limitations under the License.
165bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond
17dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo'''This script will run one specific test.'''
18a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondfrom __future__ import print_function, absolute_import
19dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
20a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondimport os
21dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport sys
22dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport atexit
23dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport inspect
24dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport logging
25a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondimport argparse
26a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondimport warnings
27dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
28dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport harness
29dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness import util_constants
30dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness import util_log
31dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness import util_warnings
32dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness.util_functions import load_py_module
33dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness.util_lldb import UtilLLDB
34dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness.exception import DisconnectedException
35a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondfrom harness.exception import TestSuiteException, TestIgnoredException
36dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom harness.util_timer import Timer
37dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
38dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
39a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondclass TestState(object):
40a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    '''Simple mutable mapping (like namedtuple)'''
41a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    def __init__(self, **kwargs):
42a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        for key, val in kwargs.items():
43a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            setattr(self, key, val)
44a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
45a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
46dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _test_pre_run(state):
47dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''This function is called before a test is executed (setup).
48dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
49dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
50a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        state: Test suite state collection, instance of TestState.
51dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
52dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Returns:
53dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        True if the pre_run step completed without error. Currently the pre-run
54dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        will launch the target test binary on the device and attach an
55dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        lldb-server to it in platform mode.
56dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
57dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Raises:
58dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        AssertionError: If an assertion fails.
59dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        TestSuiteException: Previous processes of this apk required for this
60dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                            test could not be killed.
61dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
62dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.test
63dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.bundle
64dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
65dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    log = util_log.get_logger()
66dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    log.info('running: {0}'.format(state.name))
67dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
68dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    # Remove any cached NDK scripts between tests
69dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    state.bundle.delete_ndk_cache()
70dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
71dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    # query our test case for the remote target app it needs
72a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    # First try the legacy behaviour
73a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    try:
74a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        target_name = state.test.get_bundle_target()
75a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        warnings.warn("get_bundle_target() is deprecated and will be removed soon"
76a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                      " - use the `bundle_target` dictionary attribute instead")
77a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    except AttributeError:
78a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        try:
79a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            target_name = state.test.bundle_target[state.bundle_type]
80a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        except KeyError:
81a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            raise TestIgnoredException()
82a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
83a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    if target_name is None:
84dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # test case doesn't require a remote process to debug
85dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return True
86dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    else:
87dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # find the pid of our remote test process
88dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        state.pid = state.bundle.launch(target_name)
89dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not state.pid:
90dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            log.error('unable to get pid of target')
91dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return False
92dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        state.android.kill_servers()
93dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # spawn lldb platform on the target device
94dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        state.android.launch_lldb_platform(state.device_port)
95dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return True
96dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
97dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
98dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _test_post_run(state):
99dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''This function is called after a test is executed (cleanup).
100dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
101dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
102a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        state: Test suite state collection, instance of TestState.
103dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
104dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Raises:
105dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        AssertionError: If an assertion fails.
106dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
107dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.test
108dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.bundle
109dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
110a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    try:
111a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        target_name = state.test.get_bundle_target()
112a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        warnings.warn("get_bundle_target() is deprecated and will be removed soon"
113a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                      " - use the `bundle_target` dictionary attribute instead")
114a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    except AttributeError:
115a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        try:
116a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            target_name = state.test.bundle_target[state.bundle_type]
117a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        except KeyError:
118a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            raise TestIgnoredException()
119a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
120a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
121dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    if target_name:
122dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if state.bundle.is_apk(target_name):
123dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            state.android.stop_app(state.bundle.get_package(target_name))
124dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
125dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            state.android.kill_process(target_name)
126dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
127dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
128dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _test_run(state):
129a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    '''Execute a single test suite.
130dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
131dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
132a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        state: test suite state collection, instance of TestState.
133dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
134dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Returns:
135dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        True: if the test case ran successfully and passed.
136dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        False: if the test case failed or suffered an error.
137dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
138dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Raises:
139dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        AssertionError: If an assertion fails.
140dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
141dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.lldb
142dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.lldb_module
143dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    assert state.test
144dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
145a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    test_failures = state.test.run(state.lldb, state.pid, state.lldb_module)
146a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
147a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    if test_failures:
148a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        log = util_log.get_logger()
149a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        for test, err in test_failures:
150a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            log.error('test %s:%s failed: %r' % (state.name, test, err))
151a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
152dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        return False
153dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
154dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    return True
155dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
156dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
157dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _initialise_timer(android, interval):
158dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''Start a 'timeout' timer, to catch stalled execution.
159dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
160dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    This function will start a timer that will act as a timeout killing this
161dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    test session if a test becomes un-responsive.
162dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
163dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
164dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        android: current instance of harness.UtilAndroid
165dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        interval: the interval for the timeout, in seconds
166dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
167dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Returns:
168dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        The instance of the Timer class that was created.
169dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
170dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
171dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    def on_timeout():
172dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        '''This is a callback function that will fire if a test takes longer
173dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        then a threshold time to complete.'''
174dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # Clean up the android properties
175dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        android.reset_all_props()
176dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # pylint: disable=protected-access
177dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        sys.stdout.flush()
178dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # hard exit to force kill all threads that may block our exit
179dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        os._exit(util_constants.RC_TEST_TIMEOUT)
180dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
181dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    timer = Timer(interval, on_timeout)
182dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    timer.start()
183dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    atexit.register(Timer.stop, timer)
184dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    return timer
185dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
186dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
187dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _quit_test(num, timer):
188dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''This function will exit making sure the timeout thread is killed.
189dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
190dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
191dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        num: An integer specifying the exit status, 0 meaning "successful
192dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo             termination".
193dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        timer: The current Timer instance.
194dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
195dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    if timer:
196dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        timer.stop()
197dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    sys.stdout.flush()
198dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    sys.exit(num)
199dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
200dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
201dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _execute_test(state):
202a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    '''Execute a test suite.
203dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
204dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
205a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        state: The current TestState object.
206dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
207dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    log = util_log.get_logger()
208dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
209a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    state.test.setup(state.android)
210dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    try:
211dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not _test_pre_run(state):
212dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise TestSuiteException('test_pre_run() failed')
213dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if not _test_run(state):
214dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            raise TestSuiteException('test_run() failed')
215dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        _test_post_run(state)
216dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        log.info('Test passed')
217dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
218dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    finally:
219dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        state.test.post_run()
220a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        state.test.teardown(state.android)
221dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
222dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
223dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef _get_test_case_class(module):
224dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''Inspect a test case module and return the test case class.
225dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
226dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Args:
227dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        module: A loaded test case module.
228dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
229a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    # We consider only subclasses of TestCase that have `test_` methods`
230a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    log = util_log.get_logger()
231a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    log.debug("loading test suites from %r", module)
232a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    for name, klass in inspect.getmembers(module, inspect.isclass):
233a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        for attr in dir(klass):
234a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            if attr.startswith('test_'):
235a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                log.info("Found test class %r", name)
236a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                return klass
237a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        else:
238a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            log.debug("class %r has no test_ methods", name)
239dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    return None
240dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
241dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
242dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef get_test_dir(test_name):
243dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    ''' Get the directory that contains a test with a given name.
244dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
245dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Returns:
246dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        A string that is the directory containing the test.
247dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
248dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    Raises:
249dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        TestSuiteException: If a test with this name does not exist.
250dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''
251dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    tests_dir = os.path.dirname(os.path.realpath(__file__))
252dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    for sub_dir in os.listdir(tests_dir):
253dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        current_test_dir = os.path.join(tests_dir, sub_dir)
254dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if (os.path.isdir(current_test_dir) and
255dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            test_name in os.listdir(current_test_dir)):
256dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            return current_test_dir
257dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
258dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    raise TestSuiteException(
259dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        'unable to find test: {0}'.format(test_name))
260dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
261dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
262dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef main():
263dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    '''Test runner entry point.'''
264dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
265dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    # re-open stdout with no buffering
266dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
267dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
268dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    android = None
269dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    timer = None
270dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    log = None
271dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
272a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    # parse the command line (positional arguments only)
273a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    truthy = lambda x: x.lower() in ('true', '1')
274a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    parser = argparse.ArgumentParser("Run a single RenderScript TestSuite against lldb")
275a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    for name, formatter in (
276a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('test_name', str),
277a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('log_file_path', str),
278a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('adb_path', str),
279a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('lldb_server_path_device', str),
280a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('aosp_product_path', str),
281a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('device_port', int),
282a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('device', str),
283a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('print_to_stdout', truthy),
284a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('verbose', truthy),
285a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('wimpy', truthy),
286a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('timeout', int),
287a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond       ('bundle_type', str),
288a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    ):
289a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        parser.add_argument(name, type=formatter)
290a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
291a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    args = parser.parse_args()
292dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
293a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    try:
294dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # create utility classes
295a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        harness.util_log.initialise(
296a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            '%s(%s)' % (args.test_name, args.bundle_type),
297a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            print_to_stdout=args.print_to_stdout,
298a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            level=logging.INFO if not args.verbose else logging.DEBUG,
299a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            file_path=args.log_file_path,
300dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            file_mode='a'
301dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        )
302dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        log = util_log.get_logger()
303dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        log.debug('Logger initialised')
304dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
305a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        android = harness.UtilAndroid(args.adb_path,
306a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                                      args.lldb_server_path_device,
307a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                                      args.device)
308dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
309dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # start the timeout counter
310a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        timer = _initialise_timer(android, args.timeout)
311dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
312dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # startup lldb and register teardown handler
313dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        atexit.register(UtilLLDB.stop)
314dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        UtilLLDB.start()
315dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
316a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        current_test_dir = get_test_dir(args.test_name)
317dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
318dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # load a test case module
319dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        test_module = load_py_module(os.path.join(current_test_dir,
320a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                                                  args.test_name))
321a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
322dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
323dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # inspect the test module and locate our test case class
324dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        test_class = _get_test_case_class(test_module)
325dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
326dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # if our test inherits from TestBaseRemote, check we have a valid device
327dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if (hasattr(test_module, "TestBaseRemote") and
328dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            issubclass(test_class, test_module.TestBaseRemote)):
329dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            android.validate_device()
330dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
331dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # create an instance of our test case
332a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        test_inst = test_class(
333a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            args.device_port,
334a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            args.device,
335a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            timer,
336a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            args.bundle_type,
337a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            wimpy=args.wimpy
338a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        )
339dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
340dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # instantiate a test target bundle
341a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        bundle = harness.UtilBundle(android, args.aosp_product_path)
342dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
343dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        # execute the test case
344dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        try:
345dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            for _ in range(2):
346dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                try:
347dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    # create an lldb instance
348dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    lldb = UtilLLDB.create_debugger()
349dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
350dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    # create state object to encapsulate instances
351a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
352a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                    state = TestState(
353a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         android=android,
354a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         bundle=bundle,
355a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         lldb=lldb,
356a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         lldb_module=UtilLLDB.get_module(),
357a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         test=test_inst,
358a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         pid=None,
359a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         name=args.test_name,
360a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         device_port=args.device_port,
361a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                         bundle_type=args.bundle_type
362a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond                    )
363dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
364dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    util_warnings.redirect_warnings()
365dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
366dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    _execute_test(state)
367dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
368dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    # tear down the lldb instance
369dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    UtilLLDB.destroy_debugger(lldb)
370dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    break
371dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                except DisconnectedException as error:
372dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    log.warning(error)
373dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                    log.warning('Trying again.')
374dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            else:
375dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                log.fatal('Not trying again, maximum retries exceeded.')
376dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                raise TestSuiteException('Lost connection to lldb-server')
377dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
378dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        finally:
379dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            util_warnings.restore_warnings()
380dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
381dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        _quit_test(util_constants.RC_TEST_OK, timer)
382dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
383dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    except AssertionError:
384dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if log:
385dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            log.critical('Internal test suite error', exc_info=1)
386dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        print('Internal test suite error', file=sys.stderr)
387dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        _quit_test(util_constants.RC_TEST_FATAL, timer)
388dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
389a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    except TestIgnoredException:
390a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        if log:
391a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            log.warn("test ignored")
392a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond        _quit_test(util_constants.RC_TEST_IGNORED, timer)
393a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond
394dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    except TestSuiteException as error:
395dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if log:
396dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            log.exception(str(error))
397dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
398a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond            print(error, file=sys.stderr)
39974de4db187fc370c9b6625134ae39df6655e7d72Luke Drummond        _quit_test(util_constants.RC_TEST_FAIL, timer)
400dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
401dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    # use a global exception handler to be sure that we will
402dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    # exit safely and correctly
403dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    except Exception:
404dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if log:
405dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            log.exception('INTERNAL ERROR')
406dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        else:
407dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            import traceback
408dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            print('Exception {0}'.format(traceback.format_exc()),
409dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo                  file=sys.stderr)
410dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        _quit_test(util_constants.RC_TEST_FATAL, timer)
411dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
412dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    finally:
413dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if android:
414dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            android.reset_all_props()
415dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo        if timer:
416dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo            timer.stop()
417dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
418dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo
419dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo# execution trampoline
420dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoif __name__ == '__main__':
421a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond    print(' '.join(sys.argv))
422dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo    main()
423