1"""
2LLDB module which provides the abstract base class of lldb test case.
3
4The concrete subclass can override lldbtest.TesBase in order to inherit the
5common behavior for unitest.TestCase.setUp/tearDown implemented in this file.
6
7The subclass should override the attribute mydir in order for the python runtime
8to locate the individual test cases when running as part of a large test suite
9or when running each test case as a separate python invocation.
10
11./dotest.py provides a test driver which sets up the environment to run the
12entire of part of the test suite .  Example:
13
14# Exercises the test suite in the types directory....
15/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types
16...
17
18Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42'
19Command invoked: python ./dotest.py -A x86_64 types
20compilers=['clang']
21
22Configuration: arch=x86_64 compiler=clang
23----------------------------------------------------------------------
24Collected 72 tests
25
26........................................................................
27----------------------------------------------------------------------
28Ran 72 tests in 135.468s
29
30OK
31$
32"""
33
34from __future__ import print_function
35from __future__ import absolute_import
36
37# System modules
38import abc
39import collections
40import gc
41import glob
42import os, sys, traceback
43import os.path
44import re
45import signal
46from subprocess import *
47import time
48import types
49
50# Third-party modules
51import unittest2
52from six import add_metaclass
53from six import StringIO as SixStringIO
54from six.moves.urllib import parse as urlparse
55import six
56
57# LLDB modules
58import lldb
59from . import lldbtest_config
60from . import lldbutil
61from . import test_categories
62
63# dosep.py starts lots and lots of dotest instances
64# This option helps you find if two (or more) dotest instances are using the same
65# directory at the same time
66# Enable it to cause test failures and stderr messages if dotest instances try to run in
67# the same directory simultaneously
68# it is disabled by default because it litters the test directories with ".dirlock" files
69debug_confirm_directory_exclusivity = False
70
71# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
72# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
73
74# By default, traceAlways is False.
75if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
76    traceAlways = True
77else:
78    traceAlways = False
79
80# By default, doCleanup is True.
81if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
82    doCleanup = False
83else:
84    doCleanup = True
85
86
87#
88# Some commonly used assert messages.
89#
90
91COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
92
93CURRENT_EXECUTABLE_SET = "Current executable set successfully"
94
95PROCESS_IS_VALID = "Process is valid"
96
97PROCESS_KILLED = "Process is killed successfully"
98
99PROCESS_EXITED = "Process exited successfully"
100
101PROCESS_STOPPED = "Process status should be stopped"
102
103RUN_SUCCEEDED = "Process is launched successfully"
104
105RUN_COMPLETED = "Process exited successfully"
106
107BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
108
109BREAKPOINT_CREATED = "Breakpoint created successfully"
110
111BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
112
113BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
114
115BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
116
117BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
118
119BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
120
121MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable."
122
123OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
124
125SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
126
127STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
128
129STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
130
131STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion"
132
133STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
134
135STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
136    STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
137
138STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
139
140STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
141
142STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
143
144STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
145
146STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
147
148DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
149
150VALID_BREAKPOINT = "Got a valid breakpoint"
151
152VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
153
154VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
155
156VALID_FILESPEC = "Got a valid filespec"
157
158VALID_MODULE = "Got a valid module"
159
160VALID_PROCESS = "Got a valid process"
161
162VALID_SYMBOL = "Got a valid symbol"
163
164VALID_TARGET = "Got a valid target"
165
166VALID_PLATFORM = "Got a valid platform"
167
168VALID_TYPE = "Got a valid type"
169
170VALID_VARIABLE = "Got a valid variable"
171
172VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
173
174WATCHPOINT_CREATED = "Watchpoint created successfully"
175
176def CMD_MSG(str):
177    '''A generic "Command '%s' returns successfully" message generator.'''
178    return "Command '%s' returns successfully" % str
179
180def COMPLETION_MSG(str_before, str_after):
181    '''A generic message generator for the completion mechanism.'''
182    return "'%s' successfully completes to '%s'" % (str_before, str_after)
183
184def EXP_MSG(str, exe):
185    '''A generic "'%s' returns expected result" message generator if exe.
186    Otherwise, it generates "'%s' matches expected result" message.'''
187    return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
188
189def SETTING_MSG(setting):
190    '''A generic "Value of setting '%s' is correct" message generator.'''
191    return "Value of setting '%s' is correct" % setting
192
193def EnvArray():
194    """Returns an env variable array from the os.environ map object."""
195    return list(map(lambda k,v: k+"="+v, list(os.environ.keys()), list(os.environ.values())))
196
197def line_number(filename, string_to_match):
198    """Helper function to return the line number of the first matched string."""
199    with open(filename, 'r') as f:
200        for i, line in enumerate(f):
201            if line.find(string_to_match) != -1:
202                # Found our match.
203                return i+1
204    raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
205
206def pointer_size():
207    """Return the pointer size of the host system."""
208    import ctypes
209    a_pointer = ctypes.c_void_p(0xffff)
210    return 8 * ctypes.sizeof(a_pointer)
211
212def is_exe(fpath):
213    """Returns true if fpath is an executable."""
214    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
215
216def which(program):
217    """Returns the full path to a program; None otherwise."""
218    fpath, fname = os.path.split(program)
219    if fpath:
220        if is_exe(program):
221            return program
222    else:
223        for path in os.environ["PATH"].split(os.pathsep):
224            exe_file = os.path.join(path, program)
225            if is_exe(exe_file):
226                return exe_file
227    return None
228
229class recording(SixStringIO):
230    """
231    A nice little context manager for recording the debugger interactions into
232    our session object.  If trace flag is ON, it also emits the interactions
233    into the stderr.
234    """
235    def __init__(self, test, trace):
236        """Create a SixStringIO instance; record the session obj and trace flag."""
237        SixStringIO.__init__(self)
238        # The test might not have undergone the 'setUp(self)' phase yet, so that
239        # the attribute 'session' might not even exist yet.
240        self.session = getattr(test, "session", None) if test else None
241        self.trace = trace
242
243    def __enter__(self):
244        """
245        Context management protocol on entry to the body of the with statement.
246        Just return the SixStringIO object.
247        """
248        return self
249
250    def __exit__(self, type, value, tb):
251        """
252        Context management protocol on exit from the body of the with statement.
253        If trace is ON, it emits the recordings into stderr.  Always add the
254        recordings to our session object.  And close the SixStringIO object, too.
255        """
256        if self.trace:
257            print(self.getvalue(), file=sys.stderr)
258        if self.session:
259            print(self.getvalue(), file=self.session)
260        self.close()
261
262@add_metaclass(abc.ABCMeta)
263class _BaseProcess(object):
264
265    @abc.abstractproperty
266    def pid(self):
267        """Returns process PID if has been launched already."""
268
269    @abc.abstractmethod
270    def launch(self, executable, args):
271        """Launches new process with given executable and args."""
272
273    @abc.abstractmethod
274    def terminate(self):
275        """Terminates previously launched process.."""
276
277class _LocalProcess(_BaseProcess):
278
279    def __init__(self, trace_on):
280        self._proc = None
281        self._trace_on = trace_on
282        self._delayafterterminate = 0.1
283
284    @property
285    def pid(self):
286        return self._proc.pid
287
288    def launch(self, executable, args):
289        self._proc = Popen([executable] + args,
290                           stdout = open(os.devnull) if not self._trace_on else None,
291                           stdin = PIPE)
292
293    def terminate(self):
294        if self._proc.poll() == None:
295            # Terminate _proc like it does the pexpect
296            signals_to_try = [sig for sig in ['SIGHUP', 'SIGCONT', 'SIGINT'] if sig in dir(signal)]
297            for sig in signals_to_try:
298                try:
299                    self._proc.send_signal(getattr(signal, sig))
300                    time.sleep(self._delayafterterminate)
301                    if self._proc.poll() != None:
302                        return
303                except ValueError:
304                    pass  # Windows says SIGINT is not a valid signal to send
305            self._proc.terminate()
306            time.sleep(self._delayafterterminate)
307            if self._proc.poll() != None:
308                return
309            self._proc.kill()
310            time.sleep(self._delayafterterminate)
311
312    def poll(self):
313        return self._proc.poll()
314
315class _RemoteProcess(_BaseProcess):
316
317    def __init__(self, install_remote):
318        self._pid = None
319        self._install_remote = install_remote
320
321    @property
322    def pid(self):
323        return self._pid
324
325    def launch(self, executable, args):
326        if self._install_remote:
327            src_path = executable
328            dst_path = lldbutil.append_to_process_working_directory(os.path.basename(executable))
329
330            dst_file_spec = lldb.SBFileSpec(dst_path, False)
331            err = lldb.remote_platform.Install(lldb.SBFileSpec(src_path, True), dst_file_spec)
332            if err.Fail():
333                raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (src_path, dst_path, err))
334        else:
335            dst_path = executable
336            dst_file_spec = lldb.SBFileSpec(executable, False)
337
338        launch_info = lldb.SBLaunchInfo(args)
339        launch_info.SetExecutableFile(dst_file_spec, True)
340        launch_info.SetWorkingDirectory(lldb.remote_platform.GetWorkingDirectory())
341
342        # Redirect stdout and stderr to /dev/null
343        launch_info.AddSuppressFileAction(1, False, True)
344        launch_info.AddSuppressFileAction(2, False, True)
345
346        err = lldb.remote_platform.Launch(launch_info)
347        if err.Fail():
348            raise Exception("remote_platform.Launch('%s', '%s') failed: %s" % (dst_path, args, err))
349        self._pid = launch_info.GetProcessID()
350
351    def terminate(self):
352        lldb.remote_platform.Kill(self._pid)
353
354# From 2.7's subprocess.check_output() convenience function.
355# Return a tuple (stdoutdata, stderrdata).
356def system(commands, **kwargs):
357    r"""Run an os command with arguments and return its output as a byte string.
358
359    If the exit code was non-zero it raises a CalledProcessError.  The
360    CalledProcessError object will have the return code in the returncode
361    attribute and output in the output attribute.
362
363    The arguments are the same as for the Popen constructor.  Example:
364
365    >>> check_output(["ls", "-l", "/dev/null"])
366    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'
367
368    The stdout argument is not allowed as it is used internally.
369    To capture standard error in the result, use stderr=STDOUT.
370
371    >>> check_output(["/bin/sh", "-c",
372    ...               "ls -l non_existent_file ; exit 0"],
373    ...              stderr=STDOUT)
374    'ls: non_existent_file: No such file or directory\n'
375    """
376
377    # Assign the sender object to variable 'test' and remove it from kwargs.
378    test = kwargs.pop('sender', None)
379
380    # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo']
381    commandList = [' '.join(x) for x in commands]
382    output = ""
383    error = ""
384    for shellCommand in commandList:
385        if 'stdout' in kwargs:
386            raise ValueError('stdout argument not allowed, it will be overridden.')
387        if 'shell' in kwargs and kwargs['shell']==False:
388            raise ValueError('shell=False not allowed')
389        process = Popen(shellCommand, stdout=PIPE, stderr=PIPE, shell=True, **kwargs)
390        pid = process.pid
391        this_output, this_error = process.communicate()
392        retcode = process.poll()
393
394        # Enable trace on failure return while tracking down FreeBSD buildbot issues
395        trace = traceAlways
396        if not trace and retcode and sys.platform.startswith("freebsd"):
397            trace = True
398
399        with recording(test, trace) as sbuf:
400            print(file=sbuf)
401            print("os command:", shellCommand, file=sbuf)
402            print("with pid:", pid, file=sbuf)
403            print("stdout:", this_output, file=sbuf)
404            print("stderr:", this_error, file=sbuf)
405            print("retcode:", retcode, file=sbuf)
406            print(file=sbuf)
407
408        if retcode:
409            cmd = kwargs.get("args")
410            if cmd is None:
411                cmd = shellCommand
412            raise CalledProcessError(retcode, cmd)
413        output = output + this_output
414        error = error + this_error
415    return (output, error)
416
417def getsource_if_available(obj):
418    """
419    Return the text of the source code for an object if available.  Otherwise,
420    a print representation is returned.
421    """
422    import inspect
423    try:
424        return inspect.getsource(obj)
425    except:
426        return repr(obj)
427
428def builder_module():
429    if sys.platform.startswith("freebsd"):
430        return __import__("builder_freebsd")
431    return __import__("builder_" + sys.platform)
432
433def run_adb_command(cmd, device_id):
434    device_id_args = []
435    if device_id:
436        device_id_args = ["-s", device_id]
437    full_cmd = ["adb"] + device_id_args + cmd
438    p = Popen(full_cmd, stdout=PIPE, stderr=PIPE)
439    stdout, stderr = p.communicate()
440    return p.returncode, stdout, stderr
441
442def append_android_envs(dictionary):
443    if dictionary is None:
444        dictionary = {}
445    dictionary["OS"] = "Android"
446    if android_device_api() >= 16:
447        dictionary["PIE"] = 1
448    return dictionary
449
450def target_is_android():
451    if not hasattr(target_is_android, 'result'):
452        triple = lldb.DBG.GetSelectedPlatform().GetTriple()
453        match = re.match(".*-.*-.*-android", triple)
454        target_is_android.result = match is not None
455    return target_is_android.result
456
457def android_device_api():
458    if not hasattr(android_device_api, 'result'):
459        assert lldb.platform_url is not None
460        device_id = None
461        parsed_url = urlparse.urlparse(lldb.platform_url)
462        if parsed_url.scheme == "adb":
463            device_id = parsed_url.netloc.split(":")[0]
464        retcode, stdout, stderr = run_adb_command(
465            ["shell", "getprop", "ro.build.version.sdk"], device_id)
466        if retcode == 0:
467            android_device_api.result = int(stdout)
468        else:
469            raise LookupError(
470                ">>> Unable to determine the API level of the Android device.\n"
471                ">>> stdout:\n%s\n"
472                ">>> stderr:\n%s\n" % (stdout, stderr))
473    return android_device_api.result
474
475#
476# Decorators for categorizing test cases.
477#
478from functools import wraps
479def add_test_categories(cat):
480    """Decorate an item with test categories"""
481    cat = test_categories.validate(cat, True)
482    def impl(func):
483        func.getCategories = lambda test: cat
484        return func
485    return impl
486
487def benchmarks_test(func):
488    """Decorate the item as a benchmarks test."""
489    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
490        raise Exception("@benchmarks_test can only be used to decorate a test method")
491    @wraps(func)
492    def wrapper(self, *args, **kwargs):
493        if not lldb.just_do_benchmarks_test:
494            self.skipTest("benchmarks tests")
495        return func(self, *args, **kwargs)
496
497    # Mark this function as such to separate them from the regular tests.
498    wrapper.__benchmarks_test__ = True
499    return wrapper
500
501def no_debug_info_test(func):
502    """Decorate the item as a test what don't use any debug info. If this annotation is specified
503       then the test runner won't generate a separate test for each debug info format. """
504    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
505        raise Exception("@no_debug_info_test can only be used to decorate a test method")
506    @wraps(func)
507    def wrapper(self, *args, **kwargs):
508        return func(self, *args, **kwargs)
509
510    # Mark this function as such to separate them from the regular tests.
511    wrapper.__no_debug_info_test__ = True
512    return wrapper
513
514def dsym_test(func):
515    """Decorate the item as a dsym test."""
516    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
517        raise Exception("@dsym_test can only be used to decorate a test method")
518    @wraps(func)
519    def wrapper(self, *args, **kwargs):
520        if lldb.dont_do_dsym_test:
521            self.skipTest("dsym tests")
522        return func(self, *args, **kwargs)
523
524    # Mark this function as such to separate them from the regular tests.
525    wrapper.__dsym_test__ = True
526    return wrapper
527
528def dwarf_test(func):
529    """Decorate the item as a dwarf test."""
530    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
531        raise Exception("@dwarf_test can only be used to decorate a test method")
532    @wraps(func)
533    def wrapper(self, *args, **kwargs):
534        if lldb.dont_do_dwarf_test:
535            self.skipTest("dwarf tests")
536        return func(self, *args, **kwargs)
537
538    # Mark this function as such to separate them from the regular tests.
539    wrapper.__dwarf_test__ = True
540    return wrapper
541
542def dwo_test(func):
543    """Decorate the item as a dwo test."""
544    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
545        raise Exception("@dwo_test can only be used to decorate a test method")
546    @wraps(func)
547    def wrapper(self, *args, **kwargs):
548        if lldb.dont_do_dwo_test:
549            self.skipTest("dwo tests")
550        return func(self, *args, **kwargs)
551
552    # Mark this function as such to separate them from the regular tests.
553    wrapper.__dwo_test__ = True
554    return wrapper
555
556def debugserver_test(func):
557    """Decorate the item as a debugserver test."""
558    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
559        raise Exception("@debugserver_test can only be used to decorate a test method")
560    @wraps(func)
561    def wrapper(self, *args, **kwargs):
562        if lldb.dont_do_debugserver_test:
563            self.skipTest("debugserver tests")
564        return func(self, *args, **kwargs)
565
566    # Mark this function as such to separate them from the regular tests.
567    wrapper.__debugserver_test__ = True
568    return wrapper
569
570def llgs_test(func):
571    """Decorate the item as a lldb-server test."""
572    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
573        raise Exception("@llgs_test can only be used to decorate a test method")
574    @wraps(func)
575    def wrapper(self, *args, **kwargs):
576        if lldb.dont_do_llgs_test:
577            self.skipTest("llgs tests")
578        return func(self, *args, **kwargs)
579
580    # Mark this function as such to separate them from the regular tests.
581    wrapper.__llgs_test__ = True
582    return wrapper
583
584def not_remote_testsuite_ready(func):
585    """Decorate the item as a test which is not ready yet for remote testsuite."""
586    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
587        raise Exception("@not_remote_testsuite_ready can only be used to decorate a test method")
588    @wraps(func)
589    def wrapper(self, *args, **kwargs):
590        if lldb.lldbtest_remote_sandbox or lldb.remote_platform:
591            self.skipTest("not ready for remote testsuite")
592        return func(self, *args, **kwargs)
593
594    # Mark this function as such to separate them from the regular tests.
595    wrapper.__not_ready_for_remote_testsuite_test__ = True
596    return wrapper
597
598def expectedFailure(expected_fn, bugnumber=None):
599    def expectedFailure_impl(func):
600        @wraps(func)
601        def wrapper(*args, **kwargs):
602            from unittest2 import case
603            self = args[0]
604            if expected_fn(self):
605                xfail_func = unittest2.expectedFailure(func)
606                xfail_func(*args, **kwargs)
607            else:
608                func(*args, **kwargs)
609        return wrapper
610    # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments
611    # return decorator in this case, so it will be used to decorating original method
612    if six.callable(bugnumber):
613        return expectedFailure_impl(bugnumber)
614    else:
615        return expectedFailure_impl
616
617# provide a function to xfail on defined oslist, compiler version, and archs
618# if none is specified for any argument, that argument won't be checked and thus means for all
619# for example,
620# @expectedFailureAll, xfail for all platform/compiler/arch,
621# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture
622# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386
623def expectedFailureAll(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, triple=None, debug_info=None):
624    def fn(self):
625        return ((oslist is None or self.getPlatform() in oslist) and
626                (compiler is None or (compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version))) and
627                self.expectedArch(archs) and
628                (triple is None or re.match(triple, lldb.DBG.GetSelectedPlatform().GetTriple())) and
629                (debug_info is None or self.debug_info in debug_info))
630    return expectedFailure(fn, bugnumber)
631
632def expectedFailureDwarf(bugnumber=None):
633    return expectedFailureAll(bugnumber=bugnumber, debug_info="dwarf")
634
635def expectedFailureDwo(bugnumber=None):
636    return expectedFailureAll(bugnumber=bugnumber, debug_info="dwo")
637
638def expectedFailureDsym(bugnumber=None):
639    return expectedFailureAll(bugnumber=bugnumber, debug_info="dsym")
640
641def expectedFailureCompiler(compiler, compiler_version=None, bugnumber=None):
642    if compiler_version is None:
643        compiler_version=['=', None]
644    return expectedFailureAll(bugnumber=bugnumber, compiler=compiler, compiler_version=compiler_version)
645
646# to XFAIL a specific clang versions, try this
647# @expectedFailureClang('bugnumber', ['<=', '3.4'])
648def expectedFailureClang(bugnumber=None, compiler_version=None):
649    return expectedFailureCompiler('clang', compiler_version, bugnumber)
650
651def expectedFailureGcc(bugnumber=None, compiler_version=None):
652    return expectedFailureCompiler('gcc', compiler_version, bugnumber)
653
654def expectedFailureIcc(bugnumber=None):
655    return expectedFailureCompiler('icc', None, bugnumber)
656
657def expectedFailureArch(arch, bugnumber=None):
658    def fn(self):
659        return arch in self.getArchitecture()
660    return expectedFailure(fn, bugnumber)
661
662def expectedFailurei386(bugnumber=None):
663    return expectedFailureArch('i386', bugnumber)
664
665def expectedFailurex86_64(bugnumber=None):
666    return expectedFailureArch('x86_64', bugnumber)
667
668def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None):
669    def fn(self):
670        return (self.getPlatform() in oslist and
671                self.expectedCompiler(compilers) and
672                (debug_info is None or self.debug_info in debug_info))
673    return expectedFailure(fn, bugnumber)
674
675def expectedFailureHostOS(oslist, bugnumber=None, compilers=None):
676    def fn(self):
677        return (getHostPlatform() in oslist and
678                self.expectedCompiler(compilers))
679    return expectedFailure(fn, bugnumber)
680
681def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None):
682    # For legacy reasons, we support both "darwin" and "macosx" as OS X triples.
683    return expectedFailureOS(getDarwinOSTriples(), bugnumber, compilers, debug_info=debug_info)
684
685def expectedFailureFreeBSD(bugnumber=None, compilers=None, debug_info=None):
686    return expectedFailureOS(['freebsd'], bugnumber, compilers, debug_info=debug_info)
687
688def expectedFailureLinux(bugnumber=None, compilers=None, debug_info=None):
689    return expectedFailureOS(['linux'], bugnumber, compilers, debug_info=debug_info)
690
691def expectedFailureWindows(bugnumber=None, compilers=None, debug_info=None):
692    return expectedFailureOS(['windows'], bugnumber, compilers, debug_info=debug_info)
693
694def expectedFailureHostWindows(bugnumber=None, compilers=None):
695    return expectedFailureHostOS(['windows'], bugnumber, compilers)
696
697def matchAndroid(api_levels=None, archs=None):
698    def match(self):
699        if not target_is_android():
700            return False
701        if archs is not None and self.getArchitecture() not in archs:
702            return False
703        if api_levels is not None and android_device_api() not in api_levels:
704            return False
705        return True
706    return match
707
708
709def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):
710    """ Mark a test as xfail for Android.
711
712    Arguments:
713        bugnumber - The LLVM pr associated with the problem.
714        api_levels - A sequence of numbers specifying the Android API levels
715            for which a test is expected to fail. None means all API level.
716        arch - A sequence of architecture names specifying the architectures
717            for which a test is expected to fail. None means all architectures.
718    """
719    return expectedFailure(matchAndroid(api_levels, archs), bugnumber)
720
721# if the test passes on the first try, we're done (success)
722# if the test fails once, then passes on the second try, raise an ExpectedFailure
723# if the test fails twice in a row, re-throw the exception from the second test run
724def expectedFlakey(expected_fn, bugnumber=None):
725    def expectedFailure_impl(func):
726        @wraps(func)
727        def wrapper(*args, **kwargs):
728            from unittest2 import case
729            self = args[0]
730            try:
731                func(*args, **kwargs)
732            # don't retry if the test case is already decorated with xfail or skip
733            except (case._ExpectedFailure, case.SkipTest, case._UnexpectedSuccess):
734                raise
735            except Exception:
736                if expected_fn(self):
737                    # before retry, run tearDown for previous run and setup for next
738                    try:
739                        self.tearDown()
740                        self.setUp()
741                        func(*args, **kwargs)
742                    except Exception:
743                        # oh snap! two failures in a row, record a failure/error
744                        raise
745                    # record the expected failure
746                    raise case._ExpectedFailure(sys.exc_info(), bugnumber)
747                else:
748                    raise
749        return wrapper
750    # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments
751    # return decorator in this case, so it will be used to decorating original method
752    if six.callable(bugnumber):
753        return expectedFailure_impl(bugnumber)
754    else:
755        return expectedFailure_impl
756
757def expectedFlakeyDwarf(bugnumber=None):
758    def fn(self):
759        return self.debug_info == "dwarf"
760    return expectedFlakey(fn, bugnumber)
761
762def expectedFlakeyDsym(bugnumber=None):
763    def fn(self):
764        return self.debug_info == "dwarf"
765    return expectedFlakey(fn, bugnumber)
766
767def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
768    def fn(self):
769        return (self.getPlatform() in oslist and
770                self.expectedCompiler(compilers))
771    return expectedFlakey(fn, bugnumber)
772
773def expectedFlakeyDarwin(bugnumber=None, compilers=None):
774    # For legacy reasons, we support both "darwin" and "macosx" as OS X triples.
775    return expectedFlakeyOS(getDarwinOSTriples(), bugnumber, compilers)
776
777def expectedFlakeyLinux(bugnumber=None, compilers=None):
778    return expectedFlakeyOS(['linux'], bugnumber, compilers)
779
780def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):
781    return expectedFlakeyOS(['freebsd'], bugnumber, compilers)
782
783def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None):
784    if compiler_version is None:
785        compiler_version=['=', None]
786    def fn(self):
787        return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version)
788    return expectedFlakey(fn, bugnumber)
789
790# @expectedFlakeyClang('bugnumber', ['<=', '3.4'])
791def expectedFlakeyClang(bugnumber=None, compiler_version=None):
792    return expectedFlakeyCompiler('clang', compiler_version, bugnumber)
793
794# @expectedFlakeyGcc('bugnumber', ['<=', '3.4'])
795def expectedFlakeyGcc(bugnumber=None, compiler_version=None):
796    return expectedFlakeyCompiler('gcc', compiler_version, bugnumber)
797
798def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):
799    return expectedFlakey(matchAndroid(api_levels, archs), bugnumber)
800
801def skipIfRemote(func):
802    """Decorate the item to skip tests if testing remotely."""
803    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
804        raise Exception("@skipIfRemote can only be used to decorate a test method")
805    @wraps(func)
806    def wrapper(*args, **kwargs):
807        from unittest2 import case
808        if lldb.remote_platform:
809            self = args[0]
810            self.skipTest("skip on remote platform")
811        else:
812            func(*args, **kwargs)
813    return wrapper
814
815def skipUnlessListedRemote(remote_list=None):
816    def myImpl(func):
817        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
818            raise Exception("@skipIfRemote can only be used to decorate a "
819                            "test method")
820
821        @wraps(func)
822        def wrapper(*args, **kwargs):
823            if remote_list and lldb.remote_platform:
824                self = args[0]
825                triple = self.dbg.GetSelectedPlatform().GetTriple()
826                for r in remote_list:
827                    if r in triple:
828                        func(*args, **kwargs)
829                        return
830                self.skipTest("skip on remote platform %s" % str(triple))
831            else:
832                func(*args, **kwargs)
833        return wrapper
834
835    return myImpl
836
837def skipIfRemoteDueToDeadlock(func):
838    """Decorate the item to skip tests if testing remotely due to the test deadlocking."""
839    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
840        raise Exception("@skipIfRemote can only be used to decorate a test method")
841    @wraps(func)
842    def wrapper(*args, **kwargs):
843        from unittest2 import case
844        if lldb.remote_platform:
845            self = args[0]
846            self.skipTest("skip on remote platform (deadlocks)")
847        else:
848            func(*args, **kwargs)
849    return wrapper
850
851def skipIfNoSBHeaders(func):
852    """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""
853    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
854        raise Exception("@skipIfNoSBHeaders can only be used to decorate a test method")
855    @wraps(func)
856    def wrapper(*args, **kwargs):
857        from unittest2 import case
858        self = args[0]
859        if sys.platform.startswith("darwin"):
860            header = os.path.join(os.environ["LLDB_LIB_DIR"], 'LLDB.framework', 'Versions','Current','Headers','LLDB.h')
861        else:
862            header = os.path.join(os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h")
863        platform = sys.platform
864        if not os.path.exists(header):
865            self.skipTest("skip because LLDB.h header not found")
866        else:
867            func(*args, **kwargs)
868    return wrapper
869
870def skipIfiOSSimulator(func):
871    """Decorate the item to skip tests that should be skipped on the iOS Simulator."""
872    return unittest2.skipIf(hasattr(lldb, 'remote_platform_name') and lldb.remote_platform_name == 'ios-simulator', 'skip on the iOS Simulator')(func)
873
874def skipIfFreeBSD(func):
875    """Decorate the item to skip tests that should be skipped on FreeBSD."""
876    return skipIfPlatform(["freebsd"])(func)
877
878def getDarwinOSTriples():
879    return ['darwin', 'macosx', 'ios']
880
881def skipIfDarwin(func):
882    """Decorate the item to skip tests that should be skipped on Darwin."""
883    return skipIfPlatform(getDarwinOSTriples())(func)
884
885def skipIfLinux(func):
886    """Decorate the item to skip tests that should be skipped on Linux."""
887    return skipIfPlatform(["linux"])(func)
888
889def skipUnlessHostLinux(func):
890    """Decorate the item to skip tests that should be skipped on any non Linux host."""
891    return skipUnlessHostPlatform(["linux"])(func)
892
893def skipIfWindows(func):
894    """Decorate the item to skip tests that should be skipped on Windows."""
895    return skipIfPlatform(["windows"])(func)
896
897def skipIfHostWindows(func):
898    """Decorate the item to skip tests that should be skipped on Windows."""
899    return skipIfHostPlatform(["windows"])(func)
900
901def skipUnlessWindows(func):
902    """Decorate the item to skip tests that should be skipped on any non-Windows platform."""
903    return skipUnlessPlatform(["windows"])(func)
904
905def skipUnlessDarwin(func):
906    """Decorate the item to skip tests that should be skipped on any non Darwin platform."""
907    return skipUnlessPlatform(getDarwinOSTriples())(func)
908
909def skipUnlessGoInstalled(func):
910    """Decorate the item to skip tests when no Go compiler is available."""
911    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
912        raise Exception("@skipIfGcc can only be used to decorate a test method")
913    @wraps(func)
914    def wrapper(*args, **kwargs):
915        from unittest2 import case
916        self = args[0]
917        compiler = self.getGoCompilerVersion()
918        if not compiler:
919            self.skipTest("skipping because go compiler not found")
920        else:
921            # Ensure the version is the minimum version supported by
922            # the LLDB go support.
923            match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler)
924            if not match_version:
925                # Couldn't determine version.
926                self.skipTest(
927                    "skipping because go version could not be parsed "
928                    "out of {}".format(compiler))
929            else:
930                from distutils.version import StrictVersion
931                min_strict_version = StrictVersion("1.4.0")
932                compiler_strict_version = StrictVersion(match_version.group(1))
933                if compiler_strict_version < min_strict_version:
934                    self.skipTest(
935                        "skipping because available go version ({}) does "
936                        "not meet minimum required go version ({})".format(
937                            compiler_strict_version,
938                            min_strict_version))
939            func(*args, **kwargs)
940    return wrapper
941
942def getPlatform():
943    """Returns the target platform which the tests are running on."""
944    platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
945    if platform.startswith('freebsd'):
946        platform = 'freebsd'
947    return platform
948
949def getHostPlatform():
950    """Returns the host platform running the test suite."""
951    # Attempts to return a platform name matching a target Triple platform.
952    if sys.platform.startswith('linux'):
953        return 'linux'
954    elif sys.platform.startswith('win32'):
955        return 'windows'
956    elif sys.platform.startswith('darwin'):
957        return 'darwin'
958    elif sys.platform.startswith('freebsd'):
959        return 'freebsd'
960    else:
961        return sys.platform
962
963def platformIsDarwin():
964    """Returns true if the OS triple for the selected platform is any valid apple OS"""
965    return getPlatform() in getDarwinOSTriples()
966
967def skipIfHostIncompatibleWithRemote(func):
968    """Decorate the item to skip tests if binaries built on this host are incompatible."""
969    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
970        raise Exception("@skipIfHostIncompatibleWithRemote can only be used to decorate a test method")
971    @wraps(func)
972    def wrapper(*args, **kwargs):
973        from unittest2 import case
974        self = args[0]
975        host_arch = self.getLldbArchitecture()
976        host_platform = getHostPlatform()
977        target_arch = self.getArchitecture()
978        target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform()
979        if not (target_arch == 'x86_64' and host_arch == 'i386') and host_arch != target_arch:
980            self.skipTest("skipping because target %s is not compatible with host architecture %s" % (target_arch, host_arch))
981        elif target_platform != host_platform:
982            self.skipTest("skipping because target is %s but host is %s" % (target_platform, host_platform))
983        else:
984            func(*args, **kwargs)
985    return wrapper
986
987def skipIfHostPlatform(oslist):
988    """Decorate the item to skip tests if running on one of the listed host platforms."""
989    return unittest2.skipIf(getHostPlatform() in oslist,
990                            "skip on %s" % (", ".join(oslist)))
991
992def skipUnlessHostPlatform(oslist):
993    """Decorate the item to skip tests unless running on one of the listed host platforms."""
994    return unittest2.skipUnless(getHostPlatform() in oslist,
995                                "requires on of %s" % (", ".join(oslist)))
996
997def skipUnlessArch(archlist):
998    """Decorate the item to skip tests unless running on one of the listed architectures."""
999    def myImpl(func):
1000        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1001            raise Exception("@skipUnlessArch can only be used to decorate a test method")
1002
1003        @wraps(func)
1004        def wrapper(*args, **kwargs):
1005            self = args[0]
1006            if self.getArchitecture() not in archlist:
1007                self.skipTest("skipping for architecture %s (requires one of %s)" %
1008                    (self.getArchitecture(), ", ".join(archlist)))
1009            else:
1010                func(*args, **kwargs)
1011        return wrapper
1012
1013    return myImpl
1014
1015def skipIfPlatform(oslist):
1016    """Decorate the item to skip tests if running on one of the listed platforms."""
1017    return unittest2.skipIf(getPlatform() in oslist,
1018                            "skip on %s" % (", ".join(oslist)))
1019
1020def skipUnlessPlatform(oslist):
1021    """Decorate the item to skip tests unless running on one of the listed platforms."""
1022    return unittest2.skipUnless(getPlatform() in oslist,
1023                                "requires on of %s" % (", ".join(oslist)))
1024
1025def skipIfLinuxClang(func):
1026    """Decorate the item to skip tests that should be skipped if building on
1027       Linux with clang.
1028    """
1029    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1030        raise Exception("@skipIfLinuxClang can only be used to decorate a test method")
1031    @wraps(func)
1032    def wrapper(*args, **kwargs):
1033        from unittest2 import case
1034        self = args[0]
1035        compiler = self.getCompiler()
1036        platform = self.getPlatform()
1037        if "clang" in compiler and platform == "linux":
1038            self.skipTest("skipping because Clang is used on Linux")
1039        else:
1040            func(*args, **kwargs)
1041    return wrapper
1042
1043# provide a function to skip on defined oslist, compiler version, and archs
1044# if none is specified for any argument, that argument won't be checked and thus means for all
1045# for example,
1046# @skipIf, skip for all platform/compiler/arch,
1047# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture
1048# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386
1049
1050# TODO: refactor current code, to make skipIfxxx functions to call this function
1051def skipIf(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, debug_info=None):
1052    def fn(self):
1053        return ((oslist is None or self.getPlatform() in oslist) and
1054                (compiler is None or (compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version))) and
1055                self.expectedArch(archs) and
1056                (debug_info is None or self.debug_info in debug_info))
1057    return skipTestIfFn(fn, bugnumber, skipReason="skipping because os:%s compiler: %s %s arch: %s debug info: %s"%(oslist, compiler, compiler_version, archs, debug_info))
1058
1059def skipIfDebugInfo(bugnumber=None, debug_info=None):
1060    return skipIf(bugnumber=bugnumber, debug_info=debug_info)
1061
1062def skipIfDWO(bugnumber=None):
1063    return skipIfDebugInfo(bugnumber, ["dwo"])
1064
1065def skipIfDwarf(bugnumber=None):
1066    return skipIfDebugInfo(bugnumber, ["dwarf"])
1067
1068def skipIfDsym(bugnumber=None):
1069    return skipIfDebugInfo(bugnumber, ["dsym"])
1070
1071def skipTestIfFn(expected_fn, bugnumber=None, skipReason=None):
1072    def skipTestIfFn_impl(func):
1073        @wraps(func)
1074        def wrapper(*args, **kwargs):
1075            from unittest2 import case
1076            self = args[0]
1077            if expected_fn(self):
1078               self.skipTest(skipReason)
1079            else:
1080                func(*args, **kwargs)
1081        return wrapper
1082    if six.callable(bugnumber):
1083        return skipTestIfFn_impl(bugnumber)
1084    else:
1085        return skipTestIfFn_impl
1086
1087def skipIfGcc(func):
1088    """Decorate the item to skip tests that should be skipped if building with gcc ."""
1089    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1090        raise Exception("@skipIfGcc can only be used to decorate a test method")
1091    @wraps(func)
1092    def wrapper(*args, **kwargs):
1093        from unittest2 import case
1094        self = args[0]
1095        compiler = self.getCompiler()
1096        if "gcc" in compiler:
1097            self.skipTest("skipping because gcc is the test compiler")
1098        else:
1099            func(*args, **kwargs)
1100    return wrapper
1101
1102def skipIfIcc(func):
1103    """Decorate the item to skip tests that should be skipped if building with icc ."""
1104    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1105        raise Exception("@skipIfIcc can only be used to decorate a test method")
1106    @wraps(func)
1107    def wrapper(*args, **kwargs):
1108        from unittest2 import case
1109        self = args[0]
1110        compiler = self.getCompiler()
1111        if "icc" in compiler:
1112            self.skipTest("skipping because icc is the test compiler")
1113        else:
1114            func(*args, **kwargs)
1115    return wrapper
1116
1117def skipIfi386(func):
1118    """Decorate the item to skip tests that should be skipped if building 32-bit."""
1119    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1120        raise Exception("@skipIfi386 can only be used to decorate a test method")
1121    @wraps(func)
1122    def wrapper(*args, **kwargs):
1123        from unittest2 import case
1124        self = args[0]
1125        if "i386" == self.getArchitecture():
1126            self.skipTest("skipping because i386 is not a supported architecture")
1127        else:
1128            func(*args, **kwargs)
1129    return wrapper
1130
1131def skipIfTargetAndroid(api_levels=None, archs=None):
1132    """Decorator to skip tests when the target is Android.
1133
1134    Arguments:
1135        api_levels - The API levels for which the test should be skipped. If
1136            it is None, then the test will be skipped for all API levels.
1137        arch - A sequence of architecture names specifying the architectures
1138            for which a test is skipped. None means all architectures.
1139    """
1140    def myImpl(func):
1141        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1142            raise Exception("@skipIfTargetAndroid can only be used to "
1143                            "decorate a test method")
1144        @wraps(func)
1145        def wrapper(*args, **kwargs):
1146            from unittest2 import case
1147            self = args[0]
1148            if matchAndroid(api_levels, archs)(self):
1149                self.skipTest("skiped on Android target with API %d and architecture %s" %
1150                        (android_device_api(), self.getArchitecture()))
1151            func(*args, **kwargs)
1152        return wrapper
1153    return myImpl
1154
1155def skipUnlessCompilerRt(func):
1156    """Decorate the item to skip tests if testing remotely."""
1157    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1158        raise Exception("@skipUnless can only be used to decorate a test method")
1159    @wraps(func)
1160    def wrapper(*args, **kwargs):
1161        from unittest2 import case
1162        import os.path
1163        compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "projects", "compiler-rt")
1164        if not os.path.exists(compilerRtPath):
1165            self = args[0]
1166            self.skipTest("skip if compiler-rt not found")
1167        else:
1168            func(*args, **kwargs)
1169    return wrapper
1170
1171class _PlatformContext(object):
1172    """Value object class which contains platform-specific options."""
1173
1174    def __init__(self, shlib_environment_var, shlib_prefix, shlib_extension):
1175        self.shlib_environment_var = shlib_environment_var
1176        self.shlib_prefix = shlib_prefix
1177        self.shlib_extension = shlib_extension
1178
1179
1180class Base(unittest2.TestCase):
1181    """
1182    Abstract base for performing lldb (see TestBase) or other generic tests (see
1183    BenchBase for one example).  lldbtest.Base works with the test driver to
1184    accomplish things.
1185
1186    """
1187
1188    # The concrete subclass should override this attribute.
1189    mydir = None
1190
1191    # Keep track of the old current working directory.
1192    oldcwd = None
1193
1194    @staticmethod
1195    def compute_mydir(test_file):
1196        '''Subclasses should call this function to correctly calculate the required "mydir" attribute as follows:
1197
1198            mydir = TestBase.compute_mydir(__file__)'''
1199        test_dir = os.path.dirname(test_file)
1200        return test_dir[len(os.environ["LLDB_TEST"])+1:]
1201
1202    def TraceOn(self):
1203        """Returns True if we are in trace mode (tracing detailed test execution)."""
1204        return traceAlways
1205
1206    @classmethod
1207    def setUpClass(cls):
1208        """
1209        Python unittest framework class setup fixture.
1210        Do current directory manipulation.
1211        """
1212        # Fail fast if 'mydir' attribute is not overridden.
1213        if not cls.mydir or len(cls.mydir) == 0:
1214            raise Exception("Subclasses must override the 'mydir' attribute.")
1215
1216        # Save old working directory.
1217        cls.oldcwd = os.getcwd()
1218
1219        # Change current working directory if ${LLDB_TEST} is defined.
1220        # See also dotest.py which sets up ${LLDB_TEST}.
1221        if ("LLDB_TEST" in os.environ):
1222            full_dir = os.path.join(os.environ["LLDB_TEST"], cls.mydir)
1223            if traceAlways:
1224                print("Change dir to:", full_dir, file=sys.stderr)
1225            os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
1226
1227        if debug_confirm_directory_exclusivity:
1228            import lock
1229            cls.dir_lock = lock.Lock(os.path.join(full_dir, ".dirlock"))
1230            try:
1231                cls.dir_lock.try_acquire()
1232                # write the class that owns the lock into the lock file
1233                cls.dir_lock.handle.write(cls.__name__)
1234            except IOError as ioerror:
1235                # nothing else should have this directory lock
1236                # wait here until we get a lock
1237                cls.dir_lock.acquire()
1238                # read the previous owner from the lock file
1239                lock_id = cls.dir_lock.handle.read()
1240                print("LOCK ERROR: {} wants to lock '{}' but it is already locked by '{}'".format(cls.__name__, full_dir, lock_id), file=sys.stderr)
1241                raise ioerror
1242
1243        # Set platform context.
1244        if platformIsDarwin():
1245            cls.platformContext = _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib')
1246        elif getPlatform() == "linux" or getPlatform() == "freebsd":
1247            cls.platformContext = _PlatformContext('LD_LIBRARY_PATH', 'lib', 'so')
1248        else:
1249            cls.platformContext = None
1250
1251    @classmethod
1252    def tearDownClass(cls):
1253        """
1254        Python unittest framework class teardown fixture.
1255        Do class-wide cleanup.
1256        """
1257
1258        if doCleanup and not lldb.skip_build_and_cleanup:
1259            # First, let's do the platform-specific cleanup.
1260            module = builder_module()
1261            module.cleanup()
1262
1263            # Subclass might have specific cleanup function defined.
1264            if getattr(cls, "classCleanup", None):
1265                if traceAlways:
1266                    print("Call class-specific cleanup function for class:", cls, file=sys.stderr)
1267                try:
1268                    cls.classCleanup()
1269                except:
1270                    exc_type, exc_value, exc_tb = sys.exc_info()
1271                    traceback.print_exception(exc_type, exc_value, exc_tb)
1272
1273        if debug_confirm_directory_exclusivity:
1274            cls.dir_lock.release()
1275            del cls.dir_lock
1276
1277        # Restore old working directory.
1278        if traceAlways:
1279            print("Restore dir to:", cls.oldcwd, file=sys.stderr)
1280        os.chdir(cls.oldcwd)
1281
1282    @classmethod
1283    def skipLongRunningTest(cls):
1284        """
1285        By default, we skip long running test case.
1286        This can be overridden by passing '-l' to the test driver (dotest.py).
1287        """
1288        if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
1289            return False
1290        else:
1291            return True
1292
1293    def enableLogChannelsForCurrentTest(self):
1294        if len(lldbtest_config.channels) == 0:
1295            return
1296
1297        # if debug channels are specified in lldbtest_config.channels,
1298        # create a new set of log files for every test
1299        log_basename = self.getLogBasenameForCurrentTest()
1300
1301        # confirm that the file is writeable
1302        host_log_path = "{}-host.log".format(log_basename)
1303        open(host_log_path, 'w').close()
1304
1305        log_enable = "log enable -Tpn -f {} ".format(host_log_path)
1306        for channel_with_categories in lldbtest_config.channels:
1307            channel_then_categories = channel_with_categories.split(' ', 1)
1308            channel = channel_then_categories[0]
1309            if len(channel_then_categories) > 1:
1310                categories = channel_then_categories[1]
1311            else:
1312                categories = "default"
1313
1314            if channel == "gdb-remote":
1315                # communicate gdb-remote categories to debugserver
1316                os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories
1317
1318            self.ci.HandleCommand(log_enable + channel_with_categories, self.res)
1319            if not self.res.Succeeded():
1320                raise Exception('log enable failed (check LLDB_LOG_OPTION env variable)')
1321
1322        # Communicate log path name to debugserver & lldb-server
1323        server_log_path = "{}-server.log".format(log_basename)
1324        open(server_log_path, 'w').close()
1325        os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path
1326
1327        # Communicate channels to lldb-server
1328        os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels)
1329
1330        if len(lldbtest_config.channels) == 0:
1331            return
1332
1333    def disableLogChannelsForCurrentTest(self):
1334        # close all log files that we opened
1335        for channel_and_categories in lldbtest_config.channels:
1336            # channel format - <channel-name> [<category0> [<category1> ...]]
1337            channel = channel_and_categories.split(' ', 1)[0]
1338            self.ci.HandleCommand("log disable " + channel, self.res)
1339            if not self.res.Succeeded():
1340                raise Exception('log disable failed (check LLDB_LOG_OPTION env variable)')
1341
1342    def setUp(self):
1343        """Fixture for unittest test case setup.
1344
1345        It works with the test driver to conditionally skip tests and does other
1346        initializations."""
1347        #import traceback
1348        #traceback.print_stack()
1349
1350        if "LIBCXX_PATH" in os.environ:
1351            self.libcxxPath = os.environ["LIBCXX_PATH"]
1352        else:
1353            self.libcxxPath = None
1354
1355        if "LLDBMI_EXEC" in os.environ:
1356            self.lldbMiExec = os.environ["LLDBMI_EXEC"]
1357        else:
1358            self.lldbMiExec = None
1359
1360        # If we spawn an lldb process for test (via pexpect), do not load the
1361        # init file unless told otherwise.
1362        if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]:
1363            self.lldbOption = ""
1364        else:
1365            self.lldbOption = "--no-lldbinit"
1366
1367        # Assign the test method name to self.testMethodName.
1368        #
1369        # For an example of the use of this attribute, look at test/types dir.
1370        # There are a bunch of test cases under test/types and we don't want the
1371        # module cacheing subsystem to be confused with executable name "a.out"
1372        # used for all the test cases.
1373        self.testMethodName = self._testMethodName
1374
1375        # Benchmarks test is decorated with @benchmarks_test,
1376        # which also sets the "__benchmarks_test__" attribute of the
1377        # function object to True.
1378        try:
1379            if lldb.just_do_benchmarks_test:
1380                testMethod = getattr(self, self._testMethodName)
1381                if getattr(testMethod, "__benchmarks_test__", False):
1382                    pass
1383                else:
1384                    self.skipTest("non benchmarks test")
1385        except AttributeError:
1386            pass
1387
1388        # This is for the case of directly spawning 'lldb'/'gdb' and interacting
1389        # with it using pexpect.
1390        self.child = None
1391        self.child_prompt = "(lldb) "
1392        # If the child is interacting with the embedded script interpreter,
1393        # there are two exits required during tear down, first to quit the
1394        # embedded script interpreter and second to quit the lldb command
1395        # interpreter.
1396        self.child_in_script_interpreter = False
1397
1398        # These are for customized teardown cleanup.
1399        self.dict = None
1400        self.doTearDownCleanup = False
1401        # And in rare cases where there are multiple teardown cleanups.
1402        self.dicts = []
1403        self.doTearDownCleanups = False
1404
1405        # List of spawned subproces.Popen objects
1406        self.subprocesses = []
1407
1408        # List of forked process PIDs
1409        self.forkedProcessPids = []
1410
1411        # Create a string buffer to record the session info, to be dumped into a
1412        # test case specific file if test failure is encountered.
1413        self.log_basename = self.getLogBasenameForCurrentTest()
1414
1415        session_file = "{}.log".format(self.log_basename)
1416        # Python 3 doesn't support unbuffered I/O in text mode.  Open buffered.
1417        self.session = open(session_file, "w")
1418
1419        # Optimistically set __errored__, __failed__, __expected__ to False
1420        # initially.  If the test errored/failed, the session info
1421        # (self.session) is then dumped into a session specific file for
1422        # diagnosis.
1423        self.__cleanup_errored__ = False
1424        self.__errored__    = False
1425        self.__failed__     = False
1426        self.__expected__   = False
1427        # We are also interested in unexpected success.
1428        self.__unexpected__ = False
1429        # And skipped tests.
1430        self.__skipped__ = False
1431
1432        # See addTearDownHook(self, hook) which allows the client to add a hook
1433        # function to be run during tearDown() time.
1434        self.hooks = []
1435
1436        # See HideStdout(self).
1437        self.sys_stdout_hidden = False
1438
1439        if self.platformContext:
1440            # set environment variable names for finding shared libraries
1441            self.dylibPath = self.platformContext.shlib_environment_var
1442
1443        # Create the debugger instance if necessary.
1444        try:
1445            self.dbg = lldb.DBG
1446        except AttributeError:
1447            self.dbg = lldb.SBDebugger.Create()
1448
1449        if not self.dbg:
1450            raise Exception('Invalid debugger instance')
1451
1452        # Retrieve the associated command interpreter instance.
1453        self.ci = self.dbg.GetCommandInterpreter()
1454        if not self.ci:
1455            raise Exception('Could not get the command interpreter')
1456
1457        # And the result object.
1458        self.res = lldb.SBCommandReturnObject()
1459
1460        self.enableLogChannelsForCurrentTest()
1461
1462    def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
1463        """Perform the run hooks to bring lldb debugger to the desired state.
1464
1465        By default, expect a pexpect spawned child and child prompt to be
1466        supplied (use_cmd_api=False).  If use_cmd_api is true, ignore the child
1467        and child prompt and use self.runCmd() to run the hooks one by one.
1468
1469        Note that child is a process spawned by pexpect.spawn().  If not, your
1470        test case is mostly likely going to fail.
1471
1472        See also dotest.py where lldb.runHooks are processed/populated.
1473        """
1474        if not lldb.runHooks:
1475            self.skipTest("No runhooks specified for lldb, skip the test")
1476        if use_cmd_api:
1477            for hook in lldb.runhooks:
1478                self.runCmd(hook)
1479        else:
1480            if not child or not child_prompt:
1481                self.fail("Both child and child_prompt need to be defined.")
1482            for hook in lldb.runHooks:
1483                child.sendline(hook)
1484                child.expect_exact(child_prompt)
1485
1486    def setAsync(self, value):
1487        """ Sets async mode to True/False and ensures it is reset after the testcase completes."""
1488        old_async = self.dbg.GetAsync()
1489        self.dbg.SetAsync(value)
1490        self.addTearDownHook(lambda: self.dbg.SetAsync(old_async))
1491
1492    def cleanupSubprocesses(self):
1493        # Ensure any subprocesses are cleaned up
1494        for p in self.subprocesses:
1495            p.terminate()
1496            del p
1497        del self.subprocesses[:]
1498        # Ensure any forked processes are cleaned up
1499        for pid in self.forkedProcessPids:
1500            if os.path.exists("/proc/" + str(pid)):
1501                os.kill(pid, signal.SIGTERM)
1502
1503    def spawnSubprocess(self, executable, args=[], install_remote=True):
1504        """ Creates a subprocess.Popen object with the specified executable and arguments,
1505            saves it in self.subprocesses, and returns the object.
1506            NOTE: if using this function, ensure you also call:
1507
1508              self.addTearDownHook(self.cleanupSubprocesses)
1509
1510            otherwise the test suite will leak processes.
1511        """
1512        proc = _RemoteProcess(install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn())
1513        proc.launch(executable, args)
1514        self.subprocesses.append(proc)
1515        return proc
1516
1517    def forkSubprocess(self, executable, args=[]):
1518        """ Fork a subprocess with its own group ID.
1519            NOTE: if using this function, ensure you also call:
1520
1521              self.addTearDownHook(self.cleanupSubprocesses)
1522
1523            otherwise the test suite will leak processes.
1524        """
1525        child_pid = os.fork()
1526        if child_pid == 0:
1527            # If more I/O support is required, this can be beefed up.
1528            fd = os.open(os.devnull, os.O_RDWR)
1529            os.dup2(fd, 1)
1530            os.dup2(fd, 2)
1531            # This call causes the child to have its of group ID
1532            os.setpgid(0,0)
1533            os.execvp(executable, [executable] + args)
1534        # Give the child time to get through the execvp() call
1535        time.sleep(0.1)
1536        self.forkedProcessPids.append(child_pid)
1537        return child_pid
1538
1539    def HideStdout(self):
1540        """Hide output to stdout from the user.
1541
1542        During test execution, there might be cases where we don't want to show the
1543        standard output to the user.  For example,
1544
1545            self.runCmd(r'''sc print("\n\n\tHello!\n")''')
1546
1547        tests whether command abbreviation for 'script' works or not.  There is no
1548        need to show the 'Hello' output to the user as long as the 'script' command
1549        succeeds and we are not in TraceOn() mode (see the '-t' option).
1550
1551        In this case, the test method calls self.HideStdout(self) to redirect the
1552        sys.stdout to a null device, and restores the sys.stdout upon teardown.
1553
1554        Note that you should only call this method at most once during a test case
1555        execution.  Any subsequent call has no effect at all."""
1556        if self.sys_stdout_hidden:
1557            return
1558
1559        self.sys_stdout_hidden = True
1560        old_stdout = sys.stdout
1561        sys.stdout = open(os.devnull, 'w')
1562        def restore_stdout():
1563            sys.stdout = old_stdout
1564        self.addTearDownHook(restore_stdout)
1565
1566    # =======================================================================
1567    # Methods for customized teardown cleanups as well as execution of hooks.
1568    # =======================================================================
1569
1570    def setTearDownCleanup(self, dictionary=None):
1571        """Register a cleanup action at tearDown() time with a dictinary"""
1572        self.dict = dictionary
1573        self.doTearDownCleanup = True
1574
1575    def addTearDownCleanup(self, dictionary):
1576        """Add a cleanup action at tearDown() time with a dictinary"""
1577        self.dicts.append(dictionary)
1578        self.doTearDownCleanups = True
1579
1580    def addTearDownHook(self, hook):
1581        """
1582        Add a function to be run during tearDown() time.
1583
1584        Hooks are executed in a first come first serve manner.
1585        """
1586        if six.callable(hook):
1587            with recording(self, traceAlways) as sbuf:
1588                print("Adding tearDown hook:", getsource_if_available(hook), file=sbuf)
1589            self.hooks.append(hook)
1590
1591        return self
1592
1593    def deletePexpectChild(self):
1594        # This is for the case of directly spawning 'lldb' and interacting with it
1595        # using pexpect.
1596        if self.child and self.child.isalive():
1597            import pexpect
1598            with recording(self, traceAlways) as sbuf:
1599                print("tearing down the child process....", file=sbuf)
1600            try:
1601                if self.child_in_script_interpreter:
1602                    self.child.sendline('quit()')
1603                    self.child.expect_exact(self.child_prompt)
1604                self.child.sendline('settings set interpreter.prompt-on-quit false')
1605                self.child.sendline('quit')
1606                self.child.expect(pexpect.EOF)
1607            except (ValueError, pexpect.ExceptionPexpect):
1608                # child is already terminated
1609                pass
1610            except OSError as exception:
1611                import errno
1612                if exception.errno != errno.EIO:
1613                    # unexpected error
1614                    raise
1615                # child is already terminated
1616                pass
1617            finally:
1618                # Give it one final blow to make sure the child is terminated.
1619                self.child.close()
1620
1621    def tearDown(self):
1622        """Fixture for unittest test case teardown."""
1623        #import traceback
1624        #traceback.print_stack()
1625
1626        self.deletePexpectChild()
1627
1628        # Check and run any hook functions.
1629        for hook in reversed(self.hooks):
1630            with recording(self, traceAlways) as sbuf:
1631                print("Executing tearDown hook:", getsource_if_available(hook), file=sbuf)
1632            import inspect
1633            hook_argc = len(inspect.getargspec(hook).args)
1634            if hook_argc == 0 or getattr(hook,'im_self',None):
1635                hook()
1636            elif hook_argc == 1:
1637                hook(self)
1638            else:
1639                hook() # try the plain call and hope it works
1640
1641        del self.hooks
1642
1643        # Perform registered teardown cleanup.
1644        if doCleanup and self.doTearDownCleanup:
1645            self.cleanup(dictionary=self.dict)
1646
1647        # In rare cases where there are multiple teardown cleanups added.
1648        if doCleanup and self.doTearDownCleanups:
1649            if self.dicts:
1650                for dict in reversed(self.dicts):
1651                    self.cleanup(dictionary=dict)
1652
1653        self.disableLogChannelsForCurrentTest()
1654
1655    # =========================================================
1656    # Various callbacks to allow introspection of test progress
1657    # =========================================================
1658
1659    def markError(self):
1660        """Callback invoked when an error (unexpected exception) errored."""
1661        self.__errored__ = True
1662        with recording(self, False) as sbuf:
1663            # False because there's no need to write "ERROR" to the stderr twice.
1664            # Once by the Python unittest framework, and a second time by us.
1665            print("ERROR", file=sbuf)
1666
1667    def markCleanupError(self):
1668        """Callback invoked when an error occurs while a test is cleaning up."""
1669        self.__cleanup_errored__ = True
1670        with recording(self, False) as sbuf:
1671            # False because there's no need to write "CLEANUP_ERROR" to the stderr twice.
1672            # Once by the Python unittest framework, and a second time by us.
1673            print("CLEANUP_ERROR", file=sbuf)
1674
1675    def markFailure(self):
1676        """Callback invoked when a failure (test assertion failure) occurred."""
1677        self.__failed__ = True
1678        with recording(self, False) as sbuf:
1679            # False because there's no need to write "FAIL" to the stderr twice.
1680            # Once by the Python unittest framework, and a second time by us.
1681            print("FAIL", file=sbuf)
1682
1683    def markExpectedFailure(self,err,bugnumber):
1684        """Callback invoked when an expected failure/error occurred."""
1685        self.__expected__ = True
1686        with recording(self, False) as sbuf:
1687            # False because there's no need to write "expected failure" to the
1688            # stderr twice.
1689            # Once by the Python unittest framework, and a second time by us.
1690            if bugnumber == None:
1691                print("expected failure", file=sbuf)
1692            else:
1693                print("expected failure (problem id:" + str(bugnumber) + ")", file=sbuf)
1694
1695    def markSkippedTest(self):
1696        """Callback invoked when a test is skipped."""
1697        self.__skipped__ = True
1698        with recording(self, False) as sbuf:
1699            # False because there's no need to write "skipped test" to the
1700            # stderr twice.
1701            # Once by the Python unittest framework, and a second time by us.
1702            print("skipped test", file=sbuf)
1703
1704    def markUnexpectedSuccess(self, bugnumber):
1705        """Callback invoked when an unexpected success occurred."""
1706        self.__unexpected__ = True
1707        with recording(self, False) as sbuf:
1708            # False because there's no need to write "unexpected success" to the
1709            # stderr twice.
1710            # Once by the Python unittest framework, and a second time by us.
1711            if bugnumber == None:
1712                print("unexpected success", file=sbuf)
1713            else:
1714                print("unexpected success (problem id:" + str(bugnumber) + ")", file=sbuf)
1715
1716    def getRerunArgs(self):
1717        return " -f %s.%s" % (self.__class__.__name__, self._testMethodName)
1718
1719    def getLogBasenameForCurrentTest(self, prefix=None):
1720        """
1721        returns a partial path that can be used as the beginning of the name of multiple
1722        log files pertaining to this test
1723
1724        <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method>
1725        """
1726        dname = os.path.join(os.environ["LLDB_TEST"],
1727                     os.environ["LLDB_SESSION_DIRNAME"])
1728        if not os.path.isdir(dname):
1729            os.mkdir(dname)
1730
1731        compiler = self.getCompiler()
1732
1733        if compiler[1] == ':':
1734            compiler = compiler[2:]
1735        if os.path.altsep is not None:
1736            compiler = compiler.replace(os.path.altsep, os.path.sep)
1737
1738        fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), "_".join(compiler.split(os.path.sep)))
1739        if len(fname) > 200:
1740            fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), compiler.split(os.path.sep)[-1])
1741
1742        if prefix is not None:
1743            fname = "{}-{}".format(prefix, fname)
1744
1745        return os.path.join(dname, fname)
1746
1747    def dumpSessionInfo(self):
1748        """
1749        Dump the debugger interactions leading to a test error/failure.  This
1750        allows for more convenient postmortem analysis.
1751
1752        See also LLDBTestResult (dotest.py) which is a singlton class derived
1753        from TextTestResult and overwrites addError, addFailure, and
1754        addExpectedFailure methods to allow us to to mark the test instance as
1755        such.
1756        """
1757
1758        # We are here because self.tearDown() detected that this test instance
1759        # either errored or failed.  The lldb.test_result singleton contains
1760        # two lists (erros and failures) which get populated by the unittest
1761        # framework.  Look over there for stack trace information.
1762        #
1763        # The lists contain 2-tuples of TestCase instances and strings holding
1764        # formatted tracebacks.
1765        #
1766        # See http://docs.python.org/library/unittest.html#unittest.TestResult.
1767
1768        # output tracebacks into session
1769        pairs = []
1770        if self.__errored__:
1771            pairs = lldb.test_result.errors
1772            prefix = 'Error'
1773        elif self.__cleanup_errored__:
1774            pairs = lldb.test_result.cleanup_errors
1775            prefix = 'CleanupError'
1776        elif self.__failed__:
1777            pairs = lldb.test_result.failures
1778            prefix = 'Failure'
1779        elif self.__expected__:
1780            pairs = lldb.test_result.expectedFailures
1781            prefix = 'ExpectedFailure'
1782        elif self.__skipped__:
1783            prefix = 'SkippedTest'
1784        elif self.__unexpected__:
1785            prefix = 'UnexpectedSuccess'
1786        else:
1787            prefix = 'Success'
1788
1789        if not self.__unexpected__ and not self.__skipped__:
1790            for test, traceback in pairs:
1791                if test is self:
1792                    print(traceback, file=self.session)
1793
1794        # put footer (timestamp/rerun instructions) into session
1795        testMethod = getattr(self, self._testMethodName)
1796        if getattr(testMethod, "__benchmarks_test__", False):
1797            benchmarks = True
1798        else:
1799            benchmarks = False
1800
1801        import datetime
1802        print("Session info generated @", datetime.datetime.now().ctime(), file=self.session)
1803        print("To rerun this test, issue the following command from the 'test' directory:\n", file=self.session)
1804        print("./dotest.py %s -v %s %s" % (self.getRunOptions(),
1805                                                 ('+b' if benchmarks else '-t'),
1806                                                 self.getRerunArgs()), file=self.session)
1807        self.session.close()
1808        del self.session
1809
1810        # process the log files
1811        log_files_for_this_test = glob.glob(self.log_basename + "*")
1812
1813        if prefix != 'Success' or lldbtest_config.log_success:
1814            # keep all log files, rename them to include prefix
1815            dst_log_basename = self.getLogBasenameForCurrentTest(prefix)
1816            for src in log_files_for_this_test:
1817                if os.path.isfile(src):
1818                    dst = src.replace(self.log_basename, dst_log_basename)
1819                    if os.name == "nt" and os.path.isfile(dst):
1820                        # On Windows, renaming a -> b will throw an exception if b exists.  On non-Windows platforms
1821                        # it silently replaces the destination.  Ultimately this means that atomic renames are not
1822                        # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the
1823                        # destination first if it already exists.
1824                        os.remove(dst)
1825
1826                    os.rename(src, dst)
1827        else:
1828            # success!  (and we don't want log files) delete log files
1829            for log_file in log_files_for_this_test:
1830                try:
1831                    os.unlink(log_file)
1832                except:
1833                    # We've seen consistent unlink failures on Windows, perhaps because the
1834                    # just-created log file is being scanned by anti-virus.  Empirically, this
1835                    # sleep-and-retry approach allows tests to succeed much more reliably.
1836                    # Attempts to figure out exactly what process was still holding a file handle
1837                    # have failed because running instrumentation like Process Monitor seems to
1838                    # slow things down enough that the problem becomes much less consistent.
1839                    time.sleep(0.5)
1840                    os.unlink(log_file)
1841
1842    # ====================================================
1843    # Config. methods supported through a plugin interface
1844    # (enables reading of the current test configuration)
1845    # ====================================================
1846
1847    def getArchitecture(self):
1848        """Returns the architecture in effect the test suite is running with."""
1849        module = builder_module()
1850        arch = module.getArchitecture()
1851        if arch == 'amd64':
1852            arch = 'x86_64'
1853        return arch
1854
1855    def getLldbArchitecture(self):
1856        """Returns the architecture of the lldb binary."""
1857        if not hasattr(self, 'lldbArchitecture'):
1858
1859            # spawn local process
1860            command = [
1861                lldbtest_config.lldbExec,
1862                "-o",
1863                "file " + lldbtest_config.lldbExec,
1864                "-o",
1865                "quit"
1866            ]
1867
1868            output = check_output(command)
1869            str = output.decode("utf-8");
1870
1871            for line in str.splitlines():
1872                m = re.search("Current executable set to '.*' \\((.*)\\)\\.", line)
1873                if m:
1874                    self.lldbArchitecture = m.group(1)
1875                    break
1876
1877        return self.lldbArchitecture
1878
1879    def getCompiler(self):
1880        """Returns the compiler in effect the test suite is running with."""
1881        module = builder_module()
1882        return module.getCompiler()
1883
1884    def getCompilerBinary(self):
1885        """Returns the compiler binary the test suite is running with."""
1886        return self.getCompiler().split()[0]
1887
1888    def getCompilerVersion(self):
1889        """ Returns a string that represents the compiler version.
1890            Supports: llvm, clang.
1891        """
1892        from .lldbutil import which
1893        version = 'unknown'
1894
1895        compiler = self.getCompilerBinary()
1896        version_output = system([[which(compiler), "-v"]])[1]
1897        for line in version_output.split(os.linesep):
1898            m = re.search('version ([0-9\.]+)', line)
1899            if m:
1900                version = m.group(1)
1901        return version
1902
1903    def getGoCompilerVersion(self):
1904        """ Returns a string that represents the go compiler version, or None if go is not found.
1905        """
1906        compiler = which("go")
1907        if compiler:
1908            version_output = system([[compiler, "version"]])[0]
1909            for line in version_output.split(os.linesep):
1910                m = re.search('go version (devel|go\\S+)', line)
1911                if m:
1912                    return m.group(1)
1913        return None
1914
1915    def platformIsDarwin(self):
1916        """Returns true if the OS triple for the selected platform is any valid apple OS"""
1917        return platformIsDarwin()
1918
1919    def getPlatform(self):
1920        """Returns the target platform the test suite is running on."""
1921        return getPlatform()
1922
1923    def isIntelCompiler(self):
1924        """ Returns true if using an Intel (ICC) compiler, false otherwise. """
1925        return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]])
1926
1927    def expectedCompilerVersion(self, compiler_version):
1928        """Returns True iff compiler_version[1] matches the current compiler version.
1929           Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1930           Any operator other than the following defaults to an equality test:
1931             '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
1932        """
1933        if (compiler_version == None):
1934            return True
1935        operator = str(compiler_version[0])
1936        version = compiler_version[1]
1937
1938        if (version == None):
1939            return True
1940        if (operator == '>'):
1941            return self.getCompilerVersion() > version
1942        if (operator == '>=' or operator == '=>'):
1943            return self.getCompilerVersion() >= version
1944        if (operator == '<'):
1945            return self.getCompilerVersion() < version
1946        if (operator == '<=' or operator == '=<'):
1947            return self.getCompilerVersion() <= version
1948        if (operator == '!=' or operator == '!' or operator == 'not'):
1949            return str(version) not in str(self.getCompilerVersion())
1950        return str(version) in str(self.getCompilerVersion())
1951
1952    def expectedCompiler(self, compilers):
1953        """Returns True iff any element of compilers is a sub-string of the current compiler."""
1954        if (compilers == None):
1955            return True
1956
1957        for compiler in compilers:
1958            if compiler in self.getCompiler():
1959                return True
1960
1961        return False
1962
1963    def expectedArch(self, archs):
1964        """Returns True iff any element of archs is a sub-string of the current architecture."""
1965        if (archs == None):
1966            return True
1967
1968        for arch in archs:
1969            if arch in self.getArchitecture():
1970                return True
1971
1972        return False
1973
1974    def getRunOptions(self):
1975        """Command line option for -A and -C to run this test again, called from
1976        self.dumpSessionInfo()."""
1977        arch = self.getArchitecture()
1978        comp = self.getCompiler()
1979        if arch:
1980            option_str = "-A " + arch
1981        else:
1982            option_str = ""
1983        if comp:
1984            option_str += " -C " + comp
1985        return option_str
1986
1987    # ==================================================
1988    # Build methods supported through a plugin interface
1989    # ==================================================
1990
1991    def getstdlibFlag(self):
1992        """ Returns the proper -stdlib flag, or empty if not required."""
1993        if self.platformIsDarwin() or self.getPlatform() == "freebsd":
1994            stdlibflag = "-stdlib=libc++"
1995        else:
1996            stdlibflag = ""
1997        return stdlibflag
1998
1999    def getstdFlag(self):
2000        """ Returns the proper stdflag. """
2001        if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
2002          stdflag = "-std=c++0x"
2003        else:
2004          stdflag = "-std=c++11"
2005        return stdflag
2006
2007    def buildDriver(self, sources, exe_name):
2008        """ Platform-specific way to build a program that links with LLDB (via the liblldb.so
2009            or LLDB.framework).
2010        """
2011
2012        stdflag = self.getstdFlag()
2013        stdlibflag = self.getstdlibFlag()
2014
2015        lib_dir = os.environ["LLDB_LIB_DIR"]
2016        if sys.platform.startswith("darwin"):
2017            dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB')
2018            d = {'CXX_SOURCES' : sources,
2019                 'EXE' : exe_name,
2020                 'CFLAGS_EXTRAS' : "%s %s" % (stdflag, stdlibflag),
2021                 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir,
2022                 'LD_EXTRAS' : "%s -Wl,-rpath,%s" % (dsym, lib_dir),
2023                }
2024        elif sys.platform.startswith('freebsd') or sys.platform.startswith("linux") or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile':
2025            d = {'CXX_SOURCES' : sources,
2026                 'EXE' : exe_name,
2027                 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2028                 'LD_EXTRAS' : "-L%s -llldb" % lib_dir}
2029        elif sys.platform.startswith('win'):
2030            d = {'CXX_SOURCES' : sources,
2031                 'EXE' : exe_name,
2032                 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2033                 'LD_EXTRAS' : "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]}
2034        if self.TraceOn():
2035            print("Building LLDB Driver (%s) from sources %s" % (exe_name, sources))
2036
2037        self.buildDefault(dictionary=d)
2038
2039    def buildLibrary(self, sources, lib_name):
2040        """Platform specific way to build a default library. """
2041
2042        stdflag = self.getstdFlag()
2043
2044        lib_dir = os.environ["LLDB_LIB_DIR"]
2045        if self.platformIsDarwin():
2046            dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB')
2047            d = {'DYLIB_CXX_SOURCES' : sources,
2048                 'DYLIB_NAME' : lib_name,
2049                 'CFLAGS_EXTRAS' : "%s -stdlib=libc++" % stdflag,
2050                 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir,
2051                 'LD_EXTRAS' : "%s -Wl,-rpath,%s -dynamiclib" % (dsym, lib_dir),
2052                }
2053        elif self.getPlatform() == 'freebsd' or self.getPlatform() == 'linux' or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile':
2054            d = {'DYLIB_CXX_SOURCES' : sources,
2055                 'DYLIB_NAME' : lib_name,
2056                 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2057                 'LD_EXTRAS' : "-shared -L%s -llldb" % lib_dir}
2058        elif self.getPlatform() == 'windows':
2059            d = {'DYLIB_CXX_SOURCES' : sources,
2060                 'DYLIB_NAME' : lib_name,
2061                 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2062                 'LD_EXTRAS' : "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]}
2063        if self.TraceOn():
2064            print("Building LLDB Library (%s) from sources %s" % (lib_name, sources))
2065
2066        self.buildDefault(dictionary=d)
2067
2068    def buildProgram(self, sources, exe_name):
2069        """ Platform specific way to build an executable from C/C++ sources. """
2070        d = {'CXX_SOURCES' : sources,
2071             'EXE' : exe_name}
2072        self.buildDefault(dictionary=d)
2073
2074    def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
2075        """Platform specific way to build the default binaries."""
2076        if lldb.skip_build_and_cleanup:
2077            return
2078        module = builder_module()
2079        if target_is_android():
2080            dictionary = append_android_envs(dictionary)
2081        if not module.buildDefault(self, architecture, compiler, dictionary, clean):
2082            raise Exception("Don't know how to build default binary")
2083
2084    def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
2085        """Platform specific way to build binaries with dsym info."""
2086        if lldb.skip_build_and_cleanup:
2087            return
2088        module = builder_module()
2089        if not module.buildDsym(self, architecture, compiler, dictionary, clean):
2090            raise Exception("Don't know how to build binary with dsym")
2091
2092    def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
2093        """Platform specific way to build binaries with dwarf maps."""
2094        if lldb.skip_build_and_cleanup:
2095            return
2096        module = builder_module()
2097        if target_is_android():
2098            dictionary = append_android_envs(dictionary)
2099        if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
2100            raise Exception("Don't know how to build binary with dwarf")
2101
2102    def buildDwo(self, architecture=None, compiler=None, dictionary=None, clean=True):
2103        """Platform specific way to build binaries with dwarf maps."""
2104        if lldb.skip_build_and_cleanup:
2105            return
2106        module = builder_module()
2107        if target_is_android():
2108            dictionary = append_android_envs(dictionary)
2109        if not module.buildDwo(self, architecture, compiler, dictionary, clean):
2110            raise Exception("Don't know how to build binary with dwo")
2111
2112    def buildGo(self):
2113        """Build the default go binary.
2114        """
2115        system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']])
2116
2117    def signBinary(self, binary_path):
2118        if sys.platform.startswith("darwin"):
2119            codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path)
2120            call(codesign_cmd, shell=True)
2121
2122    def findBuiltClang(self):
2123        """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
2124        paths_to_try = [
2125          "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang",
2126          "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang",
2127          "llvm-build/Release/x86_64/Release/bin/clang",
2128          "llvm-build/Debug/x86_64/Debug/bin/clang",
2129        ]
2130        lldb_root_path = os.path.join(os.path.dirname(__file__), "..")
2131        for p in paths_to_try:
2132            path = os.path.join(lldb_root_path, p)
2133            if os.path.exists(path):
2134                return path
2135
2136        # Tries to find clang at the same folder as the lldb
2137        path = os.path.join(os.path.dirname(lldbtest_config.lldbExec), "clang")
2138        if os.path.exists(path):
2139            return path
2140
2141        return os.environ["CC"]
2142
2143    def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False):
2144        """ Returns a dictionary (which can be provided to build* functions above) which
2145            contains OS-specific build flags.
2146        """
2147        cflags = ""
2148        ldflags = ""
2149
2150        # On Mac OS X, unless specifically requested to use libstdc++, use libc++
2151        if not use_libstdcxx and self.platformIsDarwin():
2152            use_libcxx = True
2153
2154        if use_libcxx and self.libcxxPath:
2155            cflags += "-stdlib=libc++ "
2156            if self.libcxxPath:
2157                libcxxInclude = os.path.join(self.libcxxPath, "include")
2158                libcxxLib = os.path.join(self.libcxxPath, "lib")
2159                if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib):
2160                    cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (libcxxInclude, libcxxLib, libcxxLib)
2161
2162        if use_cpp11:
2163            cflags += "-std="
2164            if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
2165                cflags += "c++0x"
2166            else:
2167                cflags += "c++11"
2168        if self.platformIsDarwin() or self.getPlatform() == "freebsd":
2169            cflags += " -stdlib=libc++"
2170        elif "clang" in self.getCompiler():
2171            cflags += " -stdlib=libstdc++"
2172
2173        return {'CFLAGS_EXTRAS' : cflags,
2174                'LD_EXTRAS' : ldflags,
2175               }
2176
2177    def cleanup(self, dictionary=None):
2178        """Platform specific way to do cleanup after build."""
2179        if lldb.skip_build_and_cleanup:
2180            return
2181        module = builder_module()
2182        if not module.cleanup(self, dictionary):
2183            raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
2184
2185    def getLLDBLibraryEnvVal(self):
2186        """ Returns the path that the OS-specific library search environment variable
2187            (self.dylibPath) should be set to in order for a program to find the LLDB
2188            library. If an environment variable named self.dylibPath is already set,
2189            the new path is appended to it and returned.
2190        """
2191        existing_library_path = os.environ[self.dylibPath] if self.dylibPath in os.environ else None
2192        lib_dir = os.environ["LLDB_LIB_DIR"]
2193        if existing_library_path:
2194            return "%s:%s" % (existing_library_path, lib_dir)
2195        elif sys.platform.startswith("darwin"):
2196            return os.path.join(lib_dir, 'LLDB.framework')
2197        else:
2198            return lib_dir
2199
2200    def getLibcPlusPlusLibs(self):
2201        if self.getPlatform() == 'freebsd' or self.getPlatform() == 'linux':
2202            return ['libc++.so.1']
2203        else:
2204            return ['libc++.1.dylib','libc++abi.dylib']
2205
2206# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
2207# We change the test methods to create a new test method for each test for each debug info we are
2208# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
2209# the new test method we remove the old method at the same time.
2210class LLDBTestCaseFactory(type):
2211    def __new__(cls, name, bases, attrs):
2212        newattrs = {}
2213        for attrname, attrvalue in attrs.items():
2214            if attrname.startswith("test") and not getattr(attrvalue, "__no_debug_info_test__", False):
2215                @dsym_test
2216                @wraps(attrvalue)
2217                def dsym_test_method(self, attrvalue=attrvalue):
2218                    self.debug_info = "dsym"
2219                    return attrvalue(self)
2220                dsym_method_name = attrname + "_dsym"
2221                dsym_test_method.__name__ = dsym_method_name
2222                newattrs[dsym_method_name] = dsym_test_method
2223
2224                @dwarf_test
2225                @wraps(attrvalue)
2226                def dwarf_test_method(self, attrvalue=attrvalue):
2227                    self.debug_info = "dwarf"
2228                    return attrvalue(self)
2229                dwarf_method_name = attrname + "_dwarf"
2230                dwarf_test_method.__name__ = dwarf_method_name
2231                newattrs[dwarf_method_name] = dwarf_test_method
2232
2233                @dwo_test
2234                @wraps(attrvalue)
2235                def dwo_test_method(self, attrvalue=attrvalue):
2236                    self.debug_info = "dwo"
2237                    return attrvalue(self)
2238                dwo_method_name = attrname + "_dwo"
2239                dwo_test_method.__name__ = dwo_method_name
2240                newattrs[dwo_method_name] = dwo_test_method
2241            else:
2242                newattrs[attrname] = attrvalue
2243        return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs)
2244
2245# Setup the metaclass for this class to change the list of the test methods when a new class is loaded
2246@add_metaclass(LLDBTestCaseFactory)
2247class TestBase(Base):
2248    """
2249    This abstract base class is meant to be subclassed.  It provides default
2250    implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
2251    among other things.
2252
2253    Important things for test class writers:
2254
2255        - Overwrite the mydir class attribute, otherwise your test class won't
2256          run.  It specifies the relative directory to the top level 'test' so
2257          the test harness can change to the correct working directory before
2258          running your test.
2259
2260        - The setUp method sets up things to facilitate subsequent interactions
2261          with the debugger as part of the test.  These include:
2262              - populate the test method name
2263              - create/get a debugger set with synchronous mode (self.dbg)
2264              - get the command interpreter from with the debugger (self.ci)
2265              - create a result object for use with the command interpreter
2266                (self.res)
2267              - plus other stuffs
2268
2269        - The tearDown method tries to perform some necessary cleanup on behalf
2270          of the test to return the debugger to a good state for the next test.
2271          These include:
2272              - execute any tearDown hooks registered by the test method with
2273                TestBase.addTearDownHook(); examples can be found in
2274                settings/TestSettings.py
2275              - kill the inferior process associated with each target, if any,
2276                and, then delete the target from the debugger's target list
2277              - perform build cleanup before running the next test method in the
2278                same test class; examples of registering for this service can be
2279                found in types/TestIntegerTypes.py with the call:
2280                    - self.setTearDownCleanup(dictionary=d)
2281
2282        - Similarly setUpClass and tearDownClass perform classwise setup and
2283          teardown fixtures.  The tearDownClass method invokes a default build
2284          cleanup for the entire test class;  also, subclasses can implement the
2285          classmethod classCleanup(cls) to perform special class cleanup action.
2286
2287        - The instance methods runCmd and expect are used heavily by existing
2288          test cases to send a command to the command interpreter and to perform
2289          string/pattern matching on the output of such command execution.  The
2290          expect method also provides a mode to peform string/pattern matching
2291          without running a command.
2292
2293        - The build methods buildDefault, buildDsym, and buildDwarf are used to
2294          build the binaries used during a particular test scenario.  A plugin
2295          should be provided for the sys.platform running the test suite.  The
2296          Mac OS X implementation is located in plugins/darwin.py.
2297    """
2298
2299    # Maximum allowed attempts when launching the inferior process.
2300    # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
2301    maxLaunchCount = 3;
2302
2303    # Time to wait before the next launching attempt in second(s).
2304    # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
2305    timeWaitNextLaunch = 1.0;
2306
2307    def doDelay(self):
2308        """See option -w of dotest.py."""
2309        if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
2310            os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
2311            waitTime = 1.0
2312            if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ:
2313                waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"])
2314            time.sleep(waitTime)
2315
2316    # Returns the list of categories to which this test case belongs
2317    # by default, look for a ".categories" file, and read its contents
2318    # if no such file exists, traverse the hierarchy - we guarantee
2319    # a .categories to exist at the top level directory so we do not end up
2320    # looping endlessly - subclasses are free to define their own categories
2321    # in whatever way makes sense to them
2322    def getCategories(self):
2323        import inspect
2324        import os.path
2325        folder = inspect.getfile(self.__class__)
2326        folder = os.path.dirname(folder)
2327        while folder != '/':
2328                categories_file_name = os.path.join(folder,".categories")
2329                if os.path.exists(categories_file_name):
2330                        categories_file = open(categories_file_name,'r')
2331                        categories = categories_file.readline()
2332                        categories_file.close()
2333                        categories = str.replace(categories,'\n','')
2334                        categories = str.replace(categories,'\r','')
2335                        return categories.split(',')
2336                else:
2337                        folder = os.path.dirname(folder)
2338                        continue
2339
2340    def setUp(self):
2341        #import traceback
2342        #traceback.print_stack()
2343
2344        # Works with the test driver to conditionally skip tests via decorators.
2345        Base.setUp(self)
2346
2347        try:
2348            if lldb.blacklist:
2349                className = self.__class__.__name__
2350                classAndMethodName = "%s.%s" % (className, self._testMethodName)
2351                if className in lldb.blacklist:
2352                    self.skipTest(lldb.blacklist.get(className))
2353                elif classAndMethodName in lldb.blacklist:
2354                    self.skipTest(lldb.blacklist.get(classAndMethodName))
2355        except AttributeError:
2356            pass
2357
2358        # Insert some delay between successive test cases if specified.
2359        self.doDelay()
2360
2361        if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
2362            self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
2363
2364        if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
2365            self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
2366
2367        #
2368        # Warning: MAJOR HACK AHEAD!
2369        # If we are running testsuite remotely (by checking lldb.lldbtest_remote_sandbox),
2370        # redefine the self.dbg.CreateTarget(filename) method to execute a "file filename"
2371        # command, instead.  See also runCmd() where it decorates the "file filename" call
2372        # with additional functionality when running testsuite remotely.
2373        #
2374        if lldb.lldbtest_remote_sandbox:
2375            def DecoratedCreateTarget(arg):
2376                self.runCmd("file %s" % arg)
2377                target = self.dbg.GetSelectedTarget()
2378                #
2379                # SBtarget.LaunchSimple () currently not working for remote platform?
2380                # johnny @ 04/23/2012
2381                #
2382                def DecoratedLaunchSimple(argv, envp, wd):
2383                    self.runCmd("run")
2384                    return target.GetProcess()
2385                target.LaunchSimple = DecoratedLaunchSimple
2386
2387                return target
2388            self.dbg.CreateTarget = DecoratedCreateTarget
2389            if self.TraceOn():
2390                print("self.dbg.Create is redefined to:\n%s" % getsource_if_available(DecoratedCreateTarget))
2391
2392        # We want our debugger to be synchronous.
2393        self.dbg.SetAsync(False)
2394
2395        # Retrieve the associated command interpreter instance.
2396        self.ci = self.dbg.GetCommandInterpreter()
2397        if not self.ci:
2398            raise Exception('Could not get the command interpreter')
2399
2400        # And the result object.
2401        self.res = lldb.SBCommandReturnObject()
2402
2403        # Run global pre-flight code, if defined via the config file.
2404        if lldb.pre_flight:
2405            lldb.pre_flight(self)
2406
2407        if lldb.remote_platform and lldb.remote_platform_working_dir:
2408            remote_test_dir = lldbutil.join_remote_paths(
2409                    lldb.remote_platform_working_dir,
2410                    self.getArchitecture(),
2411                    str(self.test_number),
2412                    self.mydir)
2413            error = lldb.remote_platform.MakeDirectory(remote_test_dir, 448) # 448 = 0o700
2414            if error.Success():
2415                lldb.remote_platform.SetWorkingDirectory(remote_test_dir)
2416
2417                # This function removes all files from the current working directory while leaving
2418                # the directories in place. The cleaup is required to reduce the disk space required
2419                # by the test suit while leaving the directories untached is neccessary because
2420                # sub-directories might belong to an other test
2421                def clean_working_directory():
2422                    # TODO: Make it working on Windows when we need it for remote debugging support
2423                    # TODO: Replace the heuristic to remove the files with a logic what collects the
2424                    # list of files we have to remove during test runs.
2425                    shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir)
2426                    lldb.remote_platform.Run(shell_cmd)
2427                self.addTearDownHook(clean_working_directory)
2428            else:
2429                print("error: making remote directory '%s': %s" % (remote_test_dir, error))
2430
2431    def registerSharedLibrariesWithTarget(self, target, shlibs):
2432        '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
2433
2434        Any modules in the target that have their remote install file specification set will
2435        get uploaded to the remote host. This function registers the local copies of the
2436        shared libraries with the target and sets their remote install locations so they will
2437        be uploaded when the target is run.
2438        '''
2439        if not shlibs or not self.platformContext:
2440            return None
2441
2442        shlib_environment_var = self.platformContext.shlib_environment_var
2443        shlib_prefix = self.platformContext.shlib_prefix
2444        shlib_extension = '.' + self.platformContext.shlib_extension
2445
2446        working_dir = self.get_process_working_directory()
2447        environment = ['%s=%s' % (shlib_environment_var, working_dir)]
2448        # Add any shared libraries to our target if remote so they get
2449        # uploaded into the working directory on the remote side
2450        for name in shlibs:
2451            # The path can be a full path to a shared library, or a make file name like "Foo" for
2452            # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
2453            # basename like "libFoo.so". So figure out which one it is and resolve the local copy
2454            # of the shared library accordingly
2455            if os.path.exists(name):
2456                local_shlib_path = name # name is the full path to the local shared library
2457            else:
2458                # Check relative names
2459                local_shlib_path = os.path.join(os.getcwd(), shlib_prefix + name + shlib_extension)
2460                if not os.path.exists(local_shlib_path):
2461                    local_shlib_path = os.path.join(os.getcwd(), name + shlib_extension)
2462                    if not os.path.exists(local_shlib_path):
2463                        local_shlib_path = os.path.join(os.getcwd(), name)
2464
2465                # Make sure we found the local shared library in the above code
2466                self.assertTrue(os.path.exists(local_shlib_path))
2467
2468            # Add the shared library to our target
2469            shlib_module = target.AddModule(local_shlib_path, None, None, None)
2470            if lldb.remote_platform:
2471                # We must set the remote install location if we want the shared library
2472                # to get uploaded to the remote target
2473                remote_shlib_path = lldbutil.append_to_process_working_directory(os.path.basename(local_shlib_path))
2474                shlib_module.SetRemoteInstallFileSpec(lldb.SBFileSpec(remote_shlib_path, False))
2475
2476        return environment
2477
2478    # utility methods that tests can use to access the current objects
2479    def target(self):
2480        if not self.dbg:
2481            raise Exception('Invalid debugger instance')
2482        return self.dbg.GetSelectedTarget()
2483
2484    def process(self):
2485        if not self.dbg:
2486            raise Exception('Invalid debugger instance')
2487        return self.dbg.GetSelectedTarget().GetProcess()
2488
2489    def thread(self):
2490        if not self.dbg:
2491            raise Exception('Invalid debugger instance')
2492        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
2493
2494    def frame(self):
2495        if not self.dbg:
2496            raise Exception('Invalid debugger instance')
2497        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
2498
2499    def get_process_working_directory(self):
2500        '''Get the working directory that should be used when launching processes for local or remote processes.'''
2501        if lldb.remote_platform:
2502            # Remote tests set the platform working directory up in TestBase.setUp()
2503            return lldb.remote_platform.GetWorkingDirectory()
2504        else:
2505            # local tests change directory into each test subdirectory
2506            return os.getcwd()
2507
2508    def tearDown(self):
2509        #import traceback
2510        #traceback.print_stack()
2511
2512        # Ensure all the references to SB objects have gone away so that we can
2513        # be sure that all test-specific resources have been freed before we
2514        # attempt to delete the targets.
2515        gc.collect()
2516
2517        # Delete the target(s) from the debugger as a general cleanup step.
2518        # This includes terminating the process for each target, if any.
2519        # We'd like to reuse the debugger for our next test without incurring
2520        # the initialization overhead.
2521        targets = []
2522        for target in self.dbg:
2523            if target:
2524                targets.append(target)
2525                process = target.GetProcess()
2526                if process:
2527                    rc = self.invoke(process, "Kill")
2528                    self.assertTrue(rc.Success(), PROCESS_KILLED)
2529        for target in targets:
2530            self.dbg.DeleteTarget(target)
2531
2532        # Run global post-flight code, if defined via the config file.
2533        if lldb.post_flight:
2534            lldb.post_flight(self)
2535
2536        # Do this last, to make sure it's in reverse order from how we setup.
2537        Base.tearDown(self)
2538
2539        # This must be the last statement, otherwise teardown hooks or other
2540        # lines might depend on this still being active.
2541        del self.dbg
2542
2543    def switch_to_thread_with_stop_reason(self, stop_reason):
2544        """
2545        Run the 'thread list' command, and select the thread with stop reason as
2546        'stop_reason'.  If no such thread exists, no select action is done.
2547        """
2548        from .lldbutil import stop_reason_to_str
2549        self.runCmd('thread list')
2550        output = self.res.GetOutput()
2551        thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" %
2552                                         stop_reason_to_str(stop_reason))
2553        for line in output.splitlines():
2554            matched = thread_line_pattern.match(line)
2555            if matched:
2556                self.runCmd('thread select %s' % matched.group(1))
2557
2558    def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False):
2559        """
2560        Ask the command interpreter to handle the command and then check its
2561        return status.
2562        """
2563        # Fail fast if 'cmd' is not meaningful.
2564        if not cmd or len(cmd) == 0:
2565            raise Exception("Bad 'cmd' parameter encountered")
2566
2567        trace = (True if traceAlways else trace)
2568
2569        # This is an opportunity to insert the 'platform target-install' command if we are told so
2570        # via the settig of lldb.lldbtest_remote_sandbox.
2571        if cmd.startswith("target create "):
2572            cmd = cmd.replace("target create ", "file ")
2573        if cmd.startswith("file ") and lldb.lldbtest_remote_sandbox:
2574            with recording(self, trace) as sbuf:
2575                the_rest = cmd.split("file ")[1]
2576                # Split the rest of the command line.
2577                atoms = the_rest.split()
2578                #
2579                # NOTE: This assumes that the options, if any, follow the file command,
2580                # instead of follow the specified target.
2581                #
2582                target = atoms[-1]
2583                # Now let's get the absolute pathname of our target.
2584                abs_target = os.path.abspath(target)
2585                print("Found a file command, target (with absolute pathname)=%s" % abs_target, file=sbuf)
2586                fpath, fname = os.path.split(abs_target)
2587                parent_dir = os.path.split(fpath)[0]
2588                platform_target_install_command = 'platform target-install %s %s' % (fpath, lldb.lldbtest_remote_sandbox)
2589                print("Insert this command to be run first: %s" % platform_target_install_command, file=sbuf)
2590                self.ci.HandleCommand(platform_target_install_command, self.res)
2591                # And this is the file command we want to execute, instead.
2592                #
2593                # Warning: SIDE EFFECT AHEAD!!!
2594                # Populate the remote executable pathname into the lldb namespace,
2595                # so that test cases can grab this thing out of the namespace.
2596                #
2597                lldb.lldbtest_remote_sandboxed_executable = abs_target.replace(parent_dir, lldb.lldbtest_remote_sandbox)
2598                cmd = "file -P %s %s %s" % (lldb.lldbtest_remote_sandboxed_executable, the_rest.replace(target, ''), abs_target)
2599                print("And this is the replaced file command: %s" % cmd, file=sbuf)
2600
2601        running = (cmd.startswith("run") or cmd.startswith("process launch"))
2602
2603        for i in range(self.maxLaunchCount if running else 1):
2604            self.ci.HandleCommand(cmd, self.res, inHistory)
2605
2606            with recording(self, trace) as sbuf:
2607                print("runCmd:", cmd, file=sbuf)
2608                if not check:
2609                    print("check of return status not required", file=sbuf)
2610                if self.res.Succeeded():
2611                    print("output:", self.res.GetOutput(), file=sbuf)
2612                else:
2613                    print("runCmd failed!", file=sbuf)
2614                    print(self.res.GetError(), file=sbuf)
2615
2616            if self.res.Succeeded():
2617                break
2618            elif running:
2619                # For process launch, wait some time before possible next try.
2620                time.sleep(self.timeWaitNextLaunch)
2621                with recording(self, trace) as sbuf:
2622                    print("Command '" + cmd + "' failed!", file=sbuf)
2623
2624        if check:
2625            self.assertTrue(self.res.Succeeded(),
2626                            msg if msg else CMD_MSG(cmd))
2627
2628    def match (self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True):
2629        """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2630
2631        Otherwise, all the arguments have the same meanings as for the expect function"""
2632
2633        trace = (True if traceAlways else trace)
2634
2635        if exe:
2636            # First run the command.  If we are expecting error, set check=False.
2637            # Pass the assert message along since it provides more semantic info.
2638            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
2639
2640            # Then compare the output against expected strings.
2641            output = self.res.GetError() if error else self.res.GetOutput()
2642
2643            # If error is True, the API client expects the command to fail!
2644            if error:
2645                self.assertFalse(self.res.Succeeded(),
2646                                 "Command '" + str + "' is expected to fail!")
2647        else:
2648            # No execution required, just compare str against the golden input.
2649            output = str
2650            with recording(self, trace) as sbuf:
2651                print("looking at:", output, file=sbuf)
2652
2653        # The heading says either "Expecting" or "Not expecting".
2654        heading = "Expecting" if matching else "Not expecting"
2655
2656        for pattern in patterns:
2657            # Match Objects always have a boolean value of True.
2658            match_object = re.search(pattern, output)
2659            matched = bool(match_object)
2660            with recording(self, trace) as sbuf:
2661                print("%s pattern: %s" % (heading, pattern), file=sbuf)
2662                print("Matched" if matched else "Not matched", file=sbuf)
2663            if matched:
2664                break
2665
2666        self.assertTrue(matched if matching else not matched,
2667                        msg if msg else EXP_MSG(str, exe))
2668
2669        return match_object
2670
2671    def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True, inHistory=False):
2672        """
2673        Similar to runCmd; with additional expect style output matching ability.
2674
2675        Ask the command interpreter to handle the command and then check its
2676        return status.  The 'msg' parameter specifies an informational assert
2677        message.  We expect the output from running the command to start with
2678        'startstr', matches the substrings contained in 'substrs', and regexp
2679        matches the patterns contained in 'patterns'.
2680
2681        If the keyword argument error is set to True, it signifies that the API
2682        client is expecting the command to fail.  In this case, the error stream
2683        from running the command is retrieved and compared against the golden
2684        input, instead.
2685
2686        If the keyword argument matching is set to False, it signifies that the API
2687        client is expecting the output of the command not to match the golden
2688        input.
2689
2690        Finally, the required argument 'str' represents the lldb command to be
2691        sent to the command interpreter.  In case the keyword argument 'exe' is
2692        set to False, the 'str' is treated as a string to be matched/not-matched
2693        against the golden input.
2694        """
2695        trace = (True if traceAlways else trace)
2696
2697        if exe:
2698            # First run the command.  If we are expecting error, set check=False.
2699            # Pass the assert message along since it provides more semantic info.
2700            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error, inHistory=inHistory)
2701
2702            # Then compare the output against expected strings.
2703            output = self.res.GetError() if error else self.res.GetOutput()
2704
2705            # If error is True, the API client expects the command to fail!
2706            if error:
2707                self.assertFalse(self.res.Succeeded(),
2708                                 "Command '" + str + "' is expected to fail!")
2709        else:
2710            # No execution required, just compare str against the golden input.
2711            if isinstance(str,lldb.SBCommandReturnObject):
2712                output = str.GetOutput()
2713            else:
2714                output = str
2715            with recording(self, trace) as sbuf:
2716                print("looking at:", output, file=sbuf)
2717
2718        # The heading says either "Expecting" or "Not expecting".
2719        heading = "Expecting" if matching else "Not expecting"
2720
2721        # Start from the startstr, if specified.
2722        # If there's no startstr, set the initial state appropriately.
2723        matched = output.startswith(startstr) if startstr else (True if matching else False)
2724
2725        if startstr:
2726            with recording(self, trace) as sbuf:
2727                print("%s start string: %s" % (heading, startstr), file=sbuf)
2728                print("Matched" if matched else "Not matched", file=sbuf)
2729
2730        # Look for endstr, if specified.
2731        keepgoing = matched if matching else not matched
2732        if endstr:
2733            matched = output.endswith(endstr)
2734            with recording(self, trace) as sbuf:
2735                print("%s end string: %s" % (heading, endstr), file=sbuf)
2736                print("Matched" if matched else "Not matched", file=sbuf)
2737
2738        # Look for sub strings, if specified.
2739        keepgoing = matched if matching else not matched
2740        if substrs and keepgoing:
2741            for str in substrs:
2742                matched = output.find(str) != -1
2743                with recording(self, trace) as sbuf:
2744                    print("%s sub string: %s" % (heading, str), file=sbuf)
2745                    print("Matched" if matched else "Not matched", file=sbuf)
2746                keepgoing = matched if matching else not matched
2747                if not keepgoing:
2748                    break
2749
2750        # Search for regular expression patterns, if specified.
2751        keepgoing = matched if matching else not matched
2752        if patterns and keepgoing:
2753            for pattern in patterns:
2754                # Match Objects always have a boolean value of True.
2755                matched = bool(re.search(pattern, output))
2756                with recording(self, trace) as sbuf:
2757                    print("%s pattern: %s" % (heading, pattern), file=sbuf)
2758                    print("Matched" if matched else "Not matched", file=sbuf)
2759                keepgoing = matched if matching else not matched
2760                if not keepgoing:
2761                    break
2762
2763        self.assertTrue(matched if matching else not matched,
2764                        msg if msg else EXP_MSG(str, exe))
2765
2766    def invoke(self, obj, name, trace=False):
2767        """Use reflection to call a method dynamically with no argument."""
2768        trace = (True if traceAlways else trace)
2769
2770        method = getattr(obj, name)
2771        import inspect
2772        self.assertTrue(inspect.ismethod(method),
2773                        name + "is a method name of object: " + str(obj))
2774        result = method()
2775        with recording(self, trace) as sbuf:
2776            print(str(method) + ":",  result, file=sbuf)
2777        return result
2778
2779    def build(self, architecture=None, compiler=None, dictionary=None, clean=True):
2780        """Platform specific way to build the default binaries."""
2781        if lldb.skip_build_and_cleanup:
2782            return
2783        module = builder_module()
2784        if target_is_android():
2785            dictionary = append_android_envs(dictionary)
2786        if self.debug_info is None:
2787            return self.buildDefault(architecture, compiler, dictionary, clean)
2788        elif self.debug_info == "dsym":
2789            return self.buildDsym(architecture, compiler, dictionary, clean)
2790        elif self.debug_info == "dwarf":
2791            return self.buildDwarf(architecture, compiler, dictionary, clean)
2792        elif self.debug_info == "dwo":
2793            return self.buildDwo(architecture, compiler, dictionary, clean)
2794        else:
2795            self.fail("Can't build for debug info: %s" % self.debug_info)
2796
2797    # =================================================
2798    # Misc. helper methods for debugging test execution
2799    # =================================================
2800
2801    def DebugSBValue(self, val):
2802        """Debug print a SBValue object, if traceAlways is True."""
2803        from .lldbutil import value_type_to_str
2804
2805        if not traceAlways:
2806            return
2807
2808        err = sys.stderr
2809        err.write(val.GetName() + ":\n")
2810        err.write('\t' + "TypeName         -> " + val.GetTypeName()            + '\n')
2811        err.write('\t' + "ByteSize         -> " + str(val.GetByteSize())       + '\n')
2812        err.write('\t' + "NumChildren      -> " + str(val.GetNumChildren())    + '\n')
2813        err.write('\t' + "Value            -> " + str(val.GetValue())          + '\n')
2814        err.write('\t' + "ValueAsUnsigned  -> " + str(val.GetValueAsUnsigned())+ '\n')
2815        err.write('\t' + "ValueType        -> " + value_type_to_str(val.GetValueType()) + '\n')
2816        err.write('\t' + "Summary          -> " + str(val.GetSummary())        + '\n')
2817        err.write('\t' + "IsPointerType    -> " + str(val.TypeIsPointerType()) + '\n')
2818        err.write('\t' + "Location         -> " + val.GetLocation()            + '\n')
2819
2820    def DebugSBType(self, type):
2821        """Debug print a SBType object, if traceAlways is True."""
2822        if not traceAlways:
2823            return
2824
2825        err = sys.stderr
2826        err.write(type.GetName() + ":\n")
2827        err.write('\t' + "ByteSize        -> " + str(type.GetByteSize())     + '\n')
2828        err.write('\t' + "IsPointerType   -> " + str(type.IsPointerType())   + '\n')
2829        err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n')
2830
2831    def DebugPExpect(self, child):
2832        """Debug the spwaned pexpect object."""
2833        if not traceAlways:
2834            return
2835
2836        print(child)
2837
2838    @classmethod
2839    def RemoveTempFile(cls, file):
2840        if os.path.exists(file):
2841            os.remove(file)
2842