1#
2# Copyright (C) 2018 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import logging
18import os
19
20from xml.etree import ElementTree
21
22from host_controller import common
23
24
25def ExtractResultZip(zip_file, output_dir, xml_only=True):
26    """Extracts XML result from a zip file.
27
28    Args:
29        zip_file: An object of zipfile.ZipFile.
30        output_dir: The directory where the zip is extracted.
31        xml_only: Whether to extract log-result.xml or test_result.xml only.
32
33    Returns:
34        The path to the XML in the output directory.
35        None if the zip does not contain the XML result.
36    """
37    try:
38        xml_name = next(x for x in zip_file.namelist() if
39                        x.endswith(common._TEST_RESULT_XML) or
40                        x.endswith(common._LOG_RESULT_XML))
41    except StopIteration:
42        return None
43
44    if not os.path.exists(output_dir):
45        os.makedirs(output_dir)
46    if xml_only:
47        return zip_file.extract(xml_name, path=output_dir)
48    else:
49        zip_file.extractall(path=output_dir)
50        return os.path.join(output_dir, xml_name)
51
52
53def LoadTestSummary(result_xml):
54    """Gets attributes of <Result>, <Build>, and <Summary>.
55
56    Args:
57        result_xml: A file object of the TradeFed report in XML format.
58
59    Returns:
60        3 dictionaries, the attributes of <Result>, <Build>, and <Summary>.
61    """
62    result_attrib = {}
63    build_attrib = {}
64    summary_attrib = {}
65    for event, elem in ElementTree.iterparse(result_xml, events=("start", )):
66        if all((result_attrib, build_attrib, summary_attrib)):
67            break
68        if elem.tag == common._RESULT_TAG:
69            result_attrib = dict(elem.attrib)
70        elif elem.tag == common._BUILD_TAG:
71            build_attrib = dict(elem.attrib)
72        elif elem.tag == common._SUMMARY_TAG:
73            summary_attrib = dict(elem.attrib)
74    return result_attrib, build_attrib, summary_attrib
75
76
77def IterateTestResults(result_xml):
78    """Yields test records in test_result.xml.
79
80    Args:
81        result_xml: A file object of the TradeFed report in XML format.
82
83    Yields:
84        A tuple of ElementTree.Element, (Module, TestCase, Test) for each
85        </Test>.
86    """
87    module_elem = None
88    testcase_elem = None
89    for event, elem in ElementTree.iterparse(
90            result_xml, events=("start", "end")):
91        if event == "start":
92            if elem.tag == common._MODULE_TAG:
93                module_elem = elem
94            elif elem.tag == common._TESTCASE_TAG:
95                testcase_elem = elem
96
97        if event == "end" and elem.tag == common._TEST_TAG:
98            yield module_elem, testcase_elem, elem
99
100
101def GetAbiBitness(abi):
102    """Gets bitness of an ABI.
103
104    Args:
105        abi: A string, the ABI name.
106
107    Returns:
108        32 or 64, the ABI bitness.
109    """
110    return 64 if "arm64" in abi or "x86_64" in abi else 32
111
112
113def GetTestName(module, testcase, test):
114    """Gets the bitness and the full test name.
115
116    Args:
117        module: The Element for <Module>.
118        testcase: The Element for <TestCase>.
119        test: The Element for <Test>.
120
121    Returns:
122        A tuple of (bitness, module_name, testcase_name, test_name).
123    """
124    abi = module.attrib.get(common._ABI_ATTR_KEY, "")
125    bitness = str(GetAbiBitness(abi))
126    module_name = module.attrib.get(common._NAME_ATTR_KEY, "")
127    testcase_name = testcase.attrib.get(common._NAME_ATTR_KEY, "")
128    test_name = test.attrib.get(common._NAME_ATTR_KEY, "")
129    return bitness, module_name, testcase_name, test_name
130