Skip to content

Commit cd5367f

Browse files
committed
[JENKINS-28871] CppTest 9.5 report file seems not valid for xUnit when no tests was executed
Improve CppTest XSL to better handle 7.x and 9.x reports. Cover also the case no test was run.
1 parent 6aed82b commit cd5367f

File tree

16 files changed

+695
-626
lines changed

16 files changed

+695
-626
lines changed

src/main/java/org/jenkinsci/plugins/xunit/types/CppTestUnit.java renamed to src/main/java/org/jenkinsci/plugins/xunit/types/CppTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import org.jenkinsci.lib.dtkit.model.OutputMetric;
2929
import org.jenkinsci.plugins.xunit.types.model.JUnitModel;
3030

31-
public class CppTestUnit extends InputMetricXSL {
31+
public class CppTest extends InputMetricXSL {
3232

3333
@Override
3434
public InputType getToolType() {

src/main/java/org/jenkinsci/plugins/xunit/types/CppTestJunitHudsonTestType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public CppTestJunitHudsonTestType(String pattern, boolean skipNoTestFiles, boole
4848
public static class DescriptorImpl extends TestTypeDescriptor<CppTestJunitHudsonTestType> {
4949

5050
public DescriptorImpl() {
51-
super(CppTestJunitHudsonTestType.class, CppTestUnit.class);
51+
super(CppTestJunitHudsonTestType.class, CppTest.class);
5252
}
5353

5454
}
Lines changed: 140 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,170 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
/*******************************************************************************
4-
* Copyright (c) 2011 Thales Corporate Services SAS *
5-
* Author : Gregory Boissinot, Aravindan Mahendran *
6-
* *
7-
* Permission is hereby granted, free of charge, to any person obtaining a copy *
8-
* of this software and associated documentation files (the "Software"), to deal*
9-
* in the Software without restriction, including without limitation the rights *
10-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
11-
* copies of the Software, and to permit persons to whom the Software is *
12-
* furnished to do so, subject to the following conditions: *
13-
* *
14-
* The above copyright notice and this permission notice shall be included in *
15-
* all copies or substantial portions of the Software. *
16-
* *
17-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
18-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
19-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
20-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
21-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
22-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
23-
* THE SOFTWARE. *
24-
*******************************************************************************/
3+
The MIT License (MIT)
4+
5+
Copyright (c) 2011, Gregory Boissinot, Aravindan Mahendran
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
THE SOFTWARE.
2524
-->
26-
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
25+
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xunit="http://www.xunit.org">
26+
<xsl:output method="xml" indent="yes" encoding="UTF-8" cdata-section-elements="system-out system-err failure"/>
27+
<xsl:decimal-format decimal-separator="." grouping-separator=","/>
2728

28-
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
29+
<xsl:function name="xunit:junit-time" as="xs:string">
30+
<xsl:param name="value" as="xs:double?" />
31+
32+
<xsl:variable name="time" as="xs:double">
33+
<xsl:value-of select="translate(string($value),',','.')" />
34+
</xsl:variable>
35+
<xsl:value-of select="format-number($time, '0.000')" />
36+
</xsl:function>
37+
38+
<xsl:function name="xunit:millis-from-time" as="xs:double">
39+
<xsl:param name="value" as="xs:string?" />
40+
41+
<xsl:variable name="formattedTime" select="xunit:if-empty(replace(translate($value,',','.'), '^(\d:.+)', '0$1'), '00:00:00')" />
42+
<xsl:variable name="time" select="xs:time($formattedTime)" />
43+
<xsl:value-of select="hours-from-time($time)*3600 + minutes-from-time($time)*60 + seconds-from-time($time)" />
44+
</xsl:function>
45+
46+
<xsl:function name="xunit:if-empty" as="xs:string">
47+
<xsl:param name="value" as="xs:string?" />
48+
<xsl:param name="default" as="xs:anyAtomicType?" />
49+
<xsl:value-of select="if (string($value) != '') then string($value) else $default" />
50+
</xsl:function>
51+
52+
<xsl:function name="xunit:is-empty" as="xs:boolean">
53+
<xsl:param name="value" as="xs:string?" />
54+
<xsl:value-of select="string($value) != ''" />
55+
</xsl:function>
2956

3057
<xsl:template match="/">
31-
<testsuite name="{ResultsSession/Exec/Summary/Projects/Project/@name}" time="0"
32-
tests="{Summary/Projects/Project/@testCases}"
33-
failures="{ResultsSession/Exec/Summary/Projects/Project/@fail}">
34-
<xsl:apply-templates select="ResultsSession/Exec"></xsl:apply-templates>
35-
<xsl:apply-templates select="ResultsSession/ExecutedTestsDetails"></xsl:apply-templates>
36-
</testsuite>
58+
<xsl:variable name="testCount" select="ResultsSession/Exec/Summary/Projects/Project/@testCases" />
59+
<xsl:variable name="failureCount" select="ResultsSession/Exec/Summary/Projects/Project/@fail" />
60+
<xsl:variable name="suiteName" select="ResultsSession/Exec/Summary/Projects/Project/@name" />
61+
<xsl:variable name="totalTime" select="xunit:junit-time(xunit:millis-from-time(ResultsSession/Exec/@time))" />
62+
63+
<xsl:choose>
64+
<xsl:when test="ResultsSession/Exec/TestingProcessProblems">
65+
<!-- No tests was run -->
66+
<testsuite name="{ResultsSession/TestConfig/@name}"
67+
time="{$totalTime}"
68+
tests="0"
69+
failures="0">
70+
<xsl:element name="system-err">
71+
<xsl:value-of select="ResultsSession/Exec/TestingProcessProblems/CppAnalysisProblem/ErrorList/Error/@val"/>
72+
</xsl:element>
73+
</testsuite>
74+
</xsl:when>
75+
<xsl:when test="ResultsSession/ExecutedTestsDetails">
76+
<!-- CppTest 9.x -->
77+
<testsuites name="{$suiteName}"
78+
time="{$totalTime}"
79+
tests="{$testCount}"
80+
failures="{$failureCount}">
81+
<xsl:apply-templates select="ResultsSession/ExecutedTestsDetails/Total/Project/TestSuite">
82+
<xsl:with-param name="suiteName" select="$suiteName" />
83+
</xsl:apply-templates>
84+
</testsuites>
85+
</xsl:when>
86+
<xsl:otherwise>
87+
<!-- CppTest 7.x -->
88+
<testsuite name="{$suiteName}"
89+
time="{$totalTime}"
90+
tests="{$testCount}"
91+
failures="{$failureCount}">
92+
<xsl:call-template name="TestCase_7x">
93+
<xsl:with-param name="violations" select="ResultsSession/Exec/ExecViols"/>
94+
</xsl:call-template>
95+
</testsuite>
96+
</xsl:otherwise>
97+
</xsl:choose>
3798
</xsl:template>
3899

39-
<xsl:template match="Exec">
40-
<xsl:apply-templates select="*"/>
41-
</xsl:template>
100+
<xsl:template name="TestCase_7x">
101+
<xsl:param name="violations" />
42102

43-
<xsl:template match="Goals">
44-
<properties>
45-
<xsl:apply-templates select="Goal"/>
46-
</properties>
103+
<xsl:for-each select="$violations/ExecViol">
104+
<xsl:variable name="suiteName" select="substring-before(@testName, '::')" />
105+
<xsl:variable name="testName" select="substring-after(@testName, '::')" />
106+
107+
<testcase classname="{$suiteName}" name="{$testName}" time="{xunit:junit-time(0)}">
108+
<xsl:apply-templates select="Thr" />
109+
</testcase>
110+
</xsl:for-each>
47111
</xsl:template>
48112

49-
<xsl:template match="Goal">
50-
<property name="{@name}" value="{@type}"/>
113+
<xsl:template match="TestSuite">
114+
<xsl:param name="suiteName" as="xs:string?" />
115+
116+
<xsl:variable name="suiteName" select="concat($suiteName, '.', @name)" />
117+
<xsl:choose>
118+
<xsl:when test="count(TestSuite) > 0">
119+
<xsl:apply-templates select="TestSuite">
120+
<xsl:with-param name="suiteName" select="$suiteName" />
121+
</xsl:apply-templates>
122+
</xsl:when>
123+
<xsl:otherwise>
124+
<testsuite name="{$suiteName}"
125+
time="{xunit:junit-time(0)}"
126+
tests="{@pass + @fail}"
127+
failures="{@fail}">
128+
<xsl:apply-templates select="Test">
129+
<xsl:with-param name="fullSuiteName" select="$suiteName" />
130+
<xsl:with-param name="suiteName" select="@name" />
131+
</xsl:apply-templates>
132+
</testsuite>
133+
</xsl:otherwise>
134+
</xsl:choose>
51135
</xsl:template>
52136

53-
<xsl:template match="ExecViols">
54-
<xsl:apply-templates select="ExecViol"/>
137+
<xsl:template match="Test">
138+
<xsl:param name="suiteName" as="xs:string?" />
139+
<xsl:param name="fullSuiteName" as="xs:string?" />
140+
141+
<xsl:variable name="testName" select="if (starts-with(@name, $suiteName)) then substring(@name, string-length($suiteName) + 3) else @name" />
142+
<xsl:variable name="testId" select="@id" />
143+
<testcase name="{$testName}"
144+
classname="{xunit:if-empty($fullSuiteName, $suiteName)}"
145+
time="{xunit:junit-time(xunit:millis-from-time(@time))}">
146+
<xsl:if test="@pass != 1">
147+
<xsl:apply-templates select="//Exec/ExecViols/ExecViol[@testId = $testId]" />
148+
</xsl:if>
149+
</testcase>
55150
</xsl:template>
56151

57152
<xsl:template match="ExecViol">
58-
<xsl:if test="@cat!=6">
59-
<testcase classname="{@locFile}" name="{@testName}" time="0">
60-
<xsl:apply-templates select="Thr"/>
61-
</testcase>
62-
</xsl:if>
153+
<xsl:apply-templates select="Thr"/>
63154
</xsl:template>
64155

65156
<xsl:template match="Thr">
66157
<xsl:apply-templates select="ThrPart"/>
67158
</xsl:template>
68159

69160
<xsl:template match="ThrPart">
70-
<failure type="{@clName}" message="{@detMsg}"/>
71-
<system-err>
72-
<xsl:text>Trace </xsl:text>
161+
<failure type="{@clName}" message="{@detMsg}">
73162
<xsl:apply-templates select="Trace"/>
74-
</system-err>
163+
</failure>
75164
</xsl:template>
76165

77166
<xsl:template match="Trace">
78-
<xsl:text>Line :</xsl:text>
79-
<xsl:value-of select="@ln"/>
80-
<xsl:text> File :</xsl:text>
81-
<xsl:value-of select="@fileName"/>
82-
</xsl:template>
83-
84-
<xsl:template match="ExecutedTestsDetails">
85-
<xsl:apply-templates select="Total"/>
86-
</xsl:template>
87-
88-
<xsl:template match="Total">
89-
<xsl:apply-templates select="Project"/>
90-
</xsl:template>
91-
92-
<xsl:template match="Project">
93-
<xsl:apply-templates select="TestSuite"/>
94-
</xsl:template>
95-
96-
<xsl:template match="TestSuite">
97-
<xsl:apply-templates select="*"/>
98-
</xsl:template>
99-
100-
<xsl:template match="Test">
101-
<xsl:variable name="fullTestName"><xsl:value-of select="/ResultsSession/Exec/Summary/Projects/Project/@name"/>JUnitTestSuite
102-
</xsl:variable>
103-
<xsl:if test="@pass=1">
104-
<testcase name="{@name}" classname="{$fullTestName}" time="0"/>
105-
</xsl:if>
167+
at <xsl:value-of select="@fileName"/>:<xsl:value-of select="@ln"/>
106168
</xsl:template>
107169

108170
</xsl:stylesheet>

src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,8 @@ THE SOFTWARE.
104104
</xs:sequence>
105105
<xs:attribute name="name" type="xs:string" use="required"/>
106106
<xs:attribute name="time" type="xs:string" use="optional"/>
107-
<xs:attribute name="timestamp" type="xs:string" use="optional"/>
108107
<xs:attribute name="classname" type="xs:string" use="optional"/>
109-
<xs:attribute name="status" type="xs:string" use="optional"/>
110-
<xs:attribute name="class" type="xs:string" use="optional"/>
111-
<xs:attribute name="file" type="xs:string" use="optional"/>
112-
<xs:attribute name="log" type="xs:string" use="optional"/>
113108
<xs:attribute name="group" type="xs:string" use="optional"/>
114-
<xs:attribute name="url" type="xs:string" use="optional"/>
115109
</xs:complexType>
116110
</xs:element>
117111

@@ -129,15 +123,12 @@ THE SOFTWARE.
129123
<xs:attribute name="failures" type="xs:string" use="optional"/>
130124
<xs:attribute name="errors" type="xs:string" use="optional"/>
131125
<xs:attribute name="time" type="xs:string" use="optional"/>
132-
<xs:attribute name="disabled" type="xs:string" use="optional"/>
133126
<xs:attribute name="skipped" type="xs:string" use="optional"/>
134-
<xs:attribute name="skips" type="xs:string" use="optional"/>
135127
<xs:attribute name="timestamp" type="xs:string" use="optional"/>
136128
<xs:attribute name="hostname" type="xs:string" use="optional"/>
137129
<xs:attribute name="id" type="xs:string" use="optional"/>
138130
<xs:attribute name="package" type="xs:string" use="optional"/>
139131
<xs:attribute name="file" type="xs:string" use="optional"/>
140-
<xs:attribute name="skip" type="xs:string" use="optional"/>
141132
<xs:attribute name="log" type="xs:string" use="optional"/>
142133
<xs:attribute name="url" type="xs:string" use="optional"/>
143134
</xs:complexType>
@@ -152,7 +143,6 @@ THE SOFTWARE.
152143
<xs:attribute name="time" type="xs:string" use="optional"/>
153144
<xs:attribute name="tests" type="xs:string" use="optional"/>
154145
<xs:attribute name="failures" type="xs:string" use="optional"/>
155-
<xs:attribute name="disabled" type="xs:string" use="optional"/>
156146
<xs:attribute name="errors" type="xs:string" use="optional"/>
157147
</xs:complexType>
158148
</xs:element>

src/test/java/org/jenkinsci/plugins/xunit/types/AbstractTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ protected void convertAndValidate(Class<? extends InputMetric> metricClass, Stri
101101

102102
inputMetric.convert(inputXMLFile, outputXMLFile);
103103
XMLUnit.setIgnoreWhitespace(true);
104-
Diff myDiff = new Diff(readXmlAsString(outputXMLFile), readXmlAsString(new File(this.getClass().getResource(expectedResultPath).toURI())));
104+
Diff myDiff = new Diff(readXmlAsString(new File(this.getClass().getResource(expectedResultPath).toURI())), readXmlAsString(outputXMLFile));
105105
Assert.assertTrue("XSL transformation did not work " + myDiff, myDiff.similar());
106106

107107
//The generated output file must be valid
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2017, Gregory Boissinot, Falco Nikolas
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package org.jenkinsci.plugins.xunit.types;
25+
26+
import java.util.Arrays;
27+
import java.util.Collection;
28+
29+
import org.junit.Test;
30+
import org.junit.runner.RunWith;
31+
import org.junit.runners.Parameterized;
32+
import org.junit.runners.Parameterized.Parameters;
33+
34+
@RunWith(Parameterized.class)
35+
public class CppTestTest extends AbstractTest {
36+
37+
@Parameters(name = "testcase{1}: {0}")
38+
public static Collection<Object[]> data() {
39+
return Arrays.asList(new Object[][] { { "testcase1", 1 }, //
40+
{ "mix execution of pass and fail tests", 2 }, //
41+
{ "testcase3", 3 } //
42+
});
43+
}
44+
45+
public CppTestTest(String testName, int testNumber) {
46+
super(CppTest.class, resolveInput("cpptest", testNumber), resolveOutput("cpptest", testNumber));
47+
}
48+
49+
@Override
50+
@Test
51+
public void verifyXSLT() throws Exception {
52+
super.verifyXSLT();
53+
}
54+
55+
}

0 commit comments

Comments
 (0)