Skip to content

Commit 40f0058

Browse files
committed
Allow to configure the number of bytes to keep from stdout/stderr for passed/failed test.
1 parent ba51b56 commit 40f0058

File tree

10 files changed

+433
-46
lines changed

10 files changed

+433
-46
lines changed

src/main/java/hudson/tasks/junit/CaseResult.java

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,18 @@ private static float parseTime(Element testCase) {
106106
return 0.0f;
107107
}
108108

109+
/**
110+
* @deprecated in favor of {@link #CaseResult(SuiteResult, Element, String, PluginConfig)}.
111+
*/
112+
@Deprecated
109113
CaseResult(SuiteResult parent, Element testCase, String testClassName, boolean keepLongStdio) {
114+
this(parent, testCase, testClassName, PluginConfig.defaults(keepLongStdio));
115+
}
116+
117+
/**
118+
* @since 1.6
119+
*/
120+
CaseResult(SuiteResult parent, Element testCase, String testClassName, PluginConfig config) {
110121
// schema for JUnit report XML format is not available in Ant,
111122
// so I don't know for sure what means what.
112123
// reports in http://www.nabble.com/difference-in-junit-publisher-and-ant-junitreport-tf4308604.html#a12265700
@@ -139,41 +150,58 @@ private static float parseTime(Element testCase) {
139150
skippedMessage = getSkippedMessage(testCase);
140151
@SuppressWarnings("LeakingThisInConstructor")
141152
Collection<CaseResult> _this = Collections.singleton(this);
142-
stdout = possiblyTrimStdio(_this, keepLongStdio, testCase.elementText("system-out"));
143-
stderr = possiblyTrimStdio(_this, keepLongStdio, testCase.elementText("system-err"));
153+
stdout = possiblyTrimStdio(_this, config, testCase.elementText("system-out"));
154+
stderr = possiblyTrimStdio(_this, config, testCase.elementText("system-err"));
144155
}
145156

146-
static String possiblyTrimStdio(Collection<CaseResult> results, boolean keepLongStdio, String stdio) { // HUDSON-6516
157+
static String possiblyTrimStdio(Collection<CaseResult> results, PluginConfig config, String stdio) { // HUDSON-6516
147158
if (stdio == null) {
148159
return null;
149160
}
150-
if (keepLongStdio) {
161+
if (config.isKeepLongStdio()) {
151162
return stdio;
152163
}
153164
int len = stdio.length();
154-
int halfMaxSize = halfMaxSize(results);
155-
int middle = len - halfMaxSize * 2;
165+
166+
int maxSize = config.getMaxSize(hasFailed(results));
167+
if (maxSize < 0) {
168+
return stdio;
169+
}
170+
if (maxSize == 0) {
171+
return null;
172+
}
173+
174+
int middle = len - maxSize;
156175
if (middle <= 0) {
157176
return stdio;
158177
}
178+
179+
int halfMaxSize = maxSize / 2;
159180
return stdio.subSequence(0, halfMaxSize) + "\n...[truncated " + middle + " chars]...\n" + stdio.subSequence(len - halfMaxSize, len);
160181
}
161182

162183
/**
163-
* Flavor of {@link #possiblyTrimStdio(Collection, boolean, String)} that doesn't try to read the whole thing into memory.
184+
* Flavor of {@link #possiblyTrimStdio(Collection, PluginConfig, String)} that doesn't try to read the whole thing into memory.
164185
*/
165-
static String possiblyTrimStdio(Collection<CaseResult> results, boolean keepLongStdio, File stdio) throws IOException {
186+
static String possiblyTrimStdio(Collection<CaseResult> results, PluginConfig config, File stdio) throws IOException {
166187
long len = stdio.length();
167-
if (keepLongStdio && len < 1024 * 1024) {
188+
if (config.isKeepLongStdio() && len < 1024 * 1024) {
168189
return FileUtils.readFileToString(stdio);
169190
}
170-
int halfMaxSize = halfMaxSize(results);
191+
int maxSize = config.getMaxSize(hasFailed(results));
192+
if (maxSize < 0) {
193+
return FileUtils.readFileToString(stdio);
194+
}
195+
if (maxSize == 0) {
196+
return null;
197+
}
171198

172-
long middle = len - halfMaxSize * 2;
199+
long middle = len - maxSize;
173200
if (middle <= 0) {
174201
return FileUtils.readFileToString(stdio);
175202
}
176203

204+
int halfMaxSize = maxSize / 2;
177205
TextFile tx = new TextFile(stdio);
178206
String head = tx.head(halfMaxSize);
179207
String tail = tx.fastTail(halfMaxSize);
@@ -190,15 +218,13 @@ static String possiblyTrimStdio(Collection<CaseResult> results, boolean keepLong
190218
return head + "\n...[truncated " + middle + " bytes]...\n" + tail;
191219
}
192220

193-
private static final int HALF_MAX_SIZE = 500;
194-
private static final int HALF_MAX_FAILING_SIZE = 50000;
195-
private static int halfMaxSize(Collection<CaseResult> results) {
221+
private static boolean hasFailed(Collection<CaseResult> results) {
196222
for (CaseResult result : results) {
197223
if (result.errorStackTrace != null) {
198-
return HALF_MAX_FAILING_SIZE;
224+
return true;
199225
}
200226
}
201-
return HALF_MAX_SIZE;
227+
return false;
202228
}
203229

204230

src/main/java/hudson/tasks/junit/JUnitParser.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@
3939

4040
/**
4141
* Parse some JUnit xml files and generate a TestResult containing all the
42-
* results parsed.
42+
* results parsed.
4343
*/
4444
@Extension
4545
public class JUnitParser extends TestResultParser {
4646

47-
private final boolean keepLongStdio;
47+
private final PluginConfig config;
4848

4949
/** TODO TestResultParser.all does not seem to ever be called so why must this be an Extension? */
5050
@Deprecated
@@ -56,8 +56,17 @@ public JUnitParser() {
5656
* @param keepLongStdio if true, retain a suite's complete stdout/stderr even if this is huge and the suite passed
5757
* @since 1.358
5858
*/
59+
@Deprecated
5960
public JUnitParser(boolean keepLongStdio) {
60-
this.keepLongStdio = keepLongStdio;
61+
this.config = PluginConfig.defaults(keepLongStdio);
62+
}
63+
64+
/**
65+
* @param config configuration of the plugin.
66+
* @since 1.6
67+
*/
68+
public JUnitParser(PluginConfig config) {
69+
this.config = config;
6170
}
6271

6372
@Override
@@ -86,21 +95,21 @@ public TestResult parseResult(String testResultLocations,
8695

8796
// [BUG 3123310] TODO - Test Result Refactor: review and fix TestDataPublisher/TestAction subsystem]
8897
// also get code that deals with testDataPublishers from JUnitResultArchiver.perform
89-
90-
return workspace.act(new ParseResultCallable(testResultLocations, buildTime, timeOnMaster, keepLongStdio));
98+
99+
return workspace.act(new ParseResultCallable(testResultLocations, buildTime, timeOnMaster, config));
91100
}
92101

93102
private static final class ParseResultCallable extends MasterToSlaveFileCallable<TestResult> {
94103
private final long buildTime;
95104
private final String testResults;
96105
private final long nowMaster;
97-
private final boolean keepLongStdio;
106+
private final PluginConfig config;
98107

99-
private ParseResultCallable(String testResults, long buildTime, long nowMaster, boolean keepLongStdio) {
108+
private ParseResultCallable(String testResults, long buildTime, long nowMaster, PluginConfig config) {
100109
this.buildTime = buildTime;
101110
this.testResults = testResults;
102111
this.nowMaster = nowMaster;
103-
this.keepLongStdio = keepLongStdio;
112+
this.config = config;
104113
}
105114

106115
public TestResult invoke(File ws, VirtualChannel channel) throws IOException {
@@ -116,9 +125,9 @@ public TestResult invoke(File ws, VirtualChannel channel) throws IOException {
116125
throw new AbortException(Messages.JUnitResultArchiver_NoTestReportFound());
117126
}
118127

119-
TestResult result = new TestResult(buildTime + (nowSlave - nowMaster), ds, keepLongStdio);
128+
TestResult result = new TestResult(buildTime + (nowSlave - nowMaster), ds, config);
120129
result.tally();
121-
return result;
130+
return result;
122131
}
123132
}
124133

src/main/java/hudson/tasks/junit/JUnitResultArchiver.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ public class JUnitResultArchiver extends Recorder implements SimpleBuildStep {
7474
*/
7575
private boolean keepLongStdio;
7676

77+
private int maxSucceededSize;
78+
79+
private int maxFailedSize;
80+
7781
/**
7882
* {@link TestDataPublisher}s configured for this archiver, to process the recorded data.
7983
* For compatibility reasons, can be null.
@@ -117,7 +121,7 @@ public JUnitResultArchiver(
117121
private TestResult parse(String expandedTestResults, Run<?,?> run, @Nonnull FilePath workspace, Launcher launcher, TaskListener listener)
118122
throws IOException, InterruptedException
119123
{
120-
return new JUnitParser(isKeepLongStdio()).parseResult(expandedTestResults, run, workspace, launcher, listener);
124+
return new JUnitParser(new PluginConfig(isKeepLongStdio(), getMaxSucceededSize(), getMaxFailedSize())).parseResult(expandedTestResults, run, workspace, launcher, listener);
121125
}
122126

123127
@Deprecated
@@ -230,8 +234,26 @@ public boolean isKeepLongStdio() {
230234
this.keepLongStdio = keepLongStdio;
231235
}
232236

237+
/** @since 1.6 */
238+
@DataBoundSetter public final void setMaxSucceededSize(int size) {
239+
this.maxSucceededSize = size;
240+
}
241+
242+
/** @since 1.6 */
243+
@DataBoundSetter public final void setMaxFailedSize(int size) {
244+
this.maxFailedSize = size;
245+
}
246+
233247
private static final long serialVersionUID = 1L;
234248

249+
public int getMaxSucceededSize() {
250+
return maxSucceededSize;
251+
}
252+
253+
public int getMaxFailedSize() {
254+
return maxFailedSize;
255+
}
256+
235257
@Extension
236258
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
237259
public String getDisplayName() {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package hudson.tasks.junit;
2+
3+
import java.io.Serializable;
4+
5+
/**
6+
* An object storing the plugin configuration.
7+
*/
8+
public class PluginConfig implements Serializable {
9+
10+
private final static int DEFAULT_MAX_SUCCEEDED_SIZE = 1000;
11+
12+
private final static int DEFAULT_MAX_FAILED_SIZE = 100000;
13+
14+
private final boolean keepLongStdio;
15+
16+
private final int maxSucceededSize;
17+
18+
private final int maxFailedSize;
19+
20+
public PluginConfig(boolean keepLongStdio, int maxSucceededSize, int maxFailedSize) {
21+
this.keepLongStdio = keepLongStdio;
22+
this.maxFailedSize = maxFailedSize;
23+
this.maxSucceededSize = maxSucceededSize;
24+
}
25+
26+
/**
27+
* If true, retain a suite's complete stdout/stderr even if this is huge and the
28+
* suite passed.
29+
* @return
30+
*/
31+
public boolean isKeepLongStdio() {
32+
return keepLongStdio;
33+
}
34+
35+
/**
36+
* @return maximum number of bytes to keep for a succeeded test, or -1 if infinite.
37+
*/
38+
public int getMaxSucceededSize() {
39+
return maxSucceededSize;
40+
}
41+
42+
/**
43+
* @return maximum number of bytes to keep for a failed test, or -1 if infinite.
44+
*/
45+
public int getMaxFailedSize() {
46+
return maxFailedSize;
47+
}
48+
49+
/**
50+
* Get a new {@link PluginConfig} initialized with defaults values.
51+
*/
52+
public static PluginConfig defaults() {
53+
return new PluginConfig(false, DEFAULT_MAX_SUCCEEDED_SIZE, DEFAULT_MAX_FAILED_SIZE);
54+
}
55+
56+
/**
57+
* Get a new {@link PluginConfig} with given <code>keepLongStdio</code>, and
58+
* defaults values for other configuration parameters.
59+
*/
60+
public static PluginConfig defaults(boolean keepLongStdio) {
61+
return new PluginConfig(keepLongStdio, DEFAULT_MAX_SUCCEEDED_SIZE, DEFAULT_MAX_FAILED_SIZE);
62+
}
63+
64+
/**
65+
* Get the maximum size of data to keep for a test, according to configuration.
66+
* @param failed if test has failed.
67+
* @return maximum number of bytes to keep.
68+
*/
69+
public int getMaxSize(boolean failed) {
70+
if (keepLongStdio) {
71+
return -1;
72+
}
73+
74+
if (failed) {
75+
if (maxFailedSize < 0)
76+
return -1;
77+
return (int) maxFailedSize;
78+
}
79+
else {
80+
if (maxSucceededSize < 0)
81+
return -1;
82+
return (int) maxSucceededSize;
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)