1#!/usr/bin/env python 2# Large parts of this file are modified from 3# deps/v8/tools/testrunner/local/junit_output.py, which no longer exists in 4# latest V8. 5# 6# Copyright 2013 the V8 project authors. All rights reserved. 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions are 9# met: 10# 11# * Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# * Redistributions in binary form must reproduce the above 14# copyright notice, this list of conditions and the following 15# disclaimer in the documentation and/or other materials provided 16# with the distribution. 17# * Neither the name of Google Inc. nor the names of its 18# contributors may be used to endorse or promote products derived 19# from this software without specific prior written permission. 20# 21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 33import json 34import utils 35import signal 36import sys 37import xml.etree.ElementTree as xml 38 39def IsExitCodeCrashing(exit_code): 40 if utils.IsWindows(): 41 return 0x80000000 & exit_code and not (0x3FFFFF00 & exit_code) 42 return exit_code < 0 and exit_code != -signal.SIGABRT 43 44 45class JUnitTestOutput: 46 def __init__(self, test_suite_name): 47 self.root = xml.Element("testsuite") 48 self.root.attrib["name"] = test_suite_name 49 50 def HasRunTest(self, test_name, test_cmd, test_duration, test_failure): 51 test_case_element = xml.Element("testcase") 52 test_case_element.attrib["name"] = test_name 53 test_case_element.attrib["cmd"] = test_cmd 54 test_case_element.attrib["time"] = str(round(test_duration, 3)) 55 if test_failure is not None: 56 failure_element = xml.Element("failure") 57 failure_element.text = test_failure 58 test_case_element.append(failure_element) 59 self.root.append(test_case_element) 60 61 def FinishAndWrite(self, f): 62 xml.ElementTree(self.root).write(f, "UTF-8") 63 64 65def Main(): 66 test_results = json.load(sys.stdin) 67 68 # V8's JSON test runner only logs failing and flaky tests under "results". We 69 # assume the caller has put a large number for --slow-tests-cutoff, to ensure 70 # that all the tests appear under "slowest_tests". 71 72 failing_tests = {result["name"]: result for result in test_results["results"]} 73 all_tests = {result["name"]: result for result in test_results["slowest_tests"]} 74 passing_tests = { 75 name: result for name, result in all_tests.items() if name not in failing_tests 76 } 77 78 # These check that --slow-tests-cutoff was passed correctly. 79 assert len(failing_tests) + len(passing_tests) == len(all_tests) 80 assert len(all_tests) == len(test_results["slowest_tests"]) 81 82 output = JUnitTestOutput("v8tests") 83 84 for name, failing_test in failing_tests.items(): 85 failing_output = [] 86 87 stdout = failing_test["stdout"].strip() 88 if len(stdout): 89 failing_output.append("stdout:") 90 failing_output.append(stdout) 91 92 stderr = failing_test["stderr"].strip() 93 if len(stderr): 94 failing_output.append("stderr:") 95 failing_output.append(stderr) 96 97 failing_output.append("Command: " + failing_test["command"]) 98 99 exit_code = failing_test["exit_code"] 100 if failing_test["result"] == "TIMEOUT": 101 failing_output.append("--- TIMEOUT ---") 102 elif IsExitCodeCrashing(exit_code): 103 failing_output.append("exit code: " + str(exit_code)) 104 failing_output.append("--- CRASHED ---") 105 106 output.HasRunTest( 107 test_name=name, 108 test_cmd=failing_test["command"], 109 test_duration=failing_test["duration"], 110 test_failure="\n".join(failing_output), 111 ) 112 113 for name, passing_test in passing_tests.items(): 114 output.HasRunTest( 115 test_name=name, 116 test_cmd=passing_test["command"], 117 test_duration=passing_test["duration"], 118 test_failure=None, 119 ) 120 121 output.FinishAndWrite(sys.stdout.buffer) 122 123if __name__ == '__main__': 124 Main() 125