1"""
2Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3See https://llvm.org/LICENSE.txt for license information.
4SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5"""
6
7from __future__ import print_function
8from __future__ import absolute_import
9
10# System modules
11import importlib
12import socket
13import sys
14
15# Third-party modules
16
17# LLDB modules
18
19
20# Ignore method count on DTOs.
21# pylint: disable=too-few-public-methods
22class FormatterConfig(object):
23    """Provides formatter configuration info to create_results_formatter()."""
24
25    def __init__(self):
26        self.filename = None
27        self.formatter_name = None
28        self.formatter_options = None
29
30
31# Ignore method count on DTOs.
32# pylint: disable=too-few-public-methods
33class CreatedFormatter(object):
34    """Provides transfer object for returns from create_results_formatter()."""
35
36    def __init__(self, formatter, cleanup_func):
37        self.formatter = formatter
38        self.cleanup_func = cleanup_func
39
40
41def create_results_formatter(config):
42    """Sets up a test results formatter.
43
44    @param config an instance of FormatterConfig
45    that indicates how to setup the ResultsFormatter.
46
47    @return an instance of CreatedFormatter.
48    """
49
50    default_formatter_name = None
51    results_file_object = None
52    cleanup_func = None
53
54    if config.filename:
55        # Open the results file for writing.
56        if config.filename == 'stdout':
57            results_file_object = sys.stdout
58            cleanup_func = None
59        elif config.filename == 'stderr':
60            results_file_object = sys.stderr
61            cleanup_func = None
62        else:
63            results_file_object = open(config.filename, "w")
64            cleanup_func = results_file_object.close
65        default_formatter_name = (
66            "lldbsuite.test_event.formatter.xunit.XunitFormatter")
67
68    # If we have a results formatter name specified and we didn't specify
69    # a results file, we should use stdout.
70    if config.formatter_name is not None and results_file_object is None:
71        # Use stdout.
72        results_file_object = sys.stdout
73        cleanup_func = None
74
75    if results_file_object:
76        # We care about the formatter.  Choose user-specified or, if
77        # none specified, use the default for the output type.
78        if config.formatter_name:
79            formatter_name = config.formatter_name
80        else:
81            formatter_name = default_formatter_name
82
83        # Create an instance of the class.
84        # First figure out the package/module.
85        components = formatter_name.split(".")
86        module = importlib.import_module(".".join(components[:-1]))
87
88        # Create the class name we need to load.
89        cls = getattr(module, components[-1])
90
91        # Handle formatter options for the results formatter class.
92        formatter_arg_parser = cls.arg_parser()
93        if config.formatter_options and len(config.formatter_options) > 0:
94            command_line_options = config.formatter_options
95        else:
96            command_line_options = []
97
98        formatter_options = formatter_arg_parser.parse_args(
99            command_line_options)
100
101        # Create the TestResultsFormatter given the processed options.
102        results_formatter_object = cls(
103            results_file_object,
104            formatter_options)
105
106        def shutdown_formatter():
107            """Shuts down the formatter when it is no longer needed."""
108            # Tell the formatter to write out anything it may have
109            # been saving until the very end (e.g. xUnit results
110            # can't complete its output until this point).
111            results_formatter_object.send_terminate_as_needed()
112
113            # And now close out the output file-like object.
114            if cleanup_func is not None:
115                cleanup_func()
116
117        return CreatedFormatter(
118            results_formatter_object,
119            shutdown_formatter)
120    else:
121        return None
122