Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'JENKINS-5949'
  • Loading branch information
slide committed Dec 11, 2012
2 parents 541ca82 + bcbfd02 commit 4a441eb
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 17 deletions.
Expand Up @@ -12,6 +12,8 @@
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
* An EmailContent for failing tests. Only shows tests that have failed.
*
Expand All @@ -24,8 +26,9 @@ public class FailedTestsContent implements EmailContent {
private static final String SHOW_STACK_NAME = "showStack";
private static final boolean SHOW_STACK_DEFAULT = true;
public static final String MAX_TESTS_ARG_NAME = "maxTests";
static final String ONLY_REGRESSIONS_NAME = "onlyRegressions";
private static final String ONLY_REGRESSIONS_NAME = "onlyRegressions";
private static final boolean ONLY_REGRESSIONS_DEFAULT = false;
public static final String MAX_LENGTH_ARG_NAME = "maxLength";

public String getToken() {
return TOKEN;
Expand All @@ -45,7 +48,9 @@ public String getHelpText() {
+ "only regressions compared to the previous builds should be shown.<br>\n"
+ "Defaults to " + SHOW_STACK_DEFAULT + ".\n"
+ "<li><i>" + MAX_TESTS_ARG_NAME + "</i> - display at most this many failing tests.<br>\n"
+ "No limit is set by default.\n"
+ "No limit is set by default.</li>\n"
+ "<li><i>" + MAX_LENGTH_ARG_NAME + "</i> - display at most this much KB of failing test data.<br/>\n"
+ "No limit is set by default. Setting \"50\" for the argument value would mean 50KB of data would be the max</li>\n"
+ "</ul>\n";
}

Expand All @@ -71,13 +76,19 @@ public <P extends AbstractProject<P, B>, B extends AbstractBuild<P, B>> String g

boolean showStacks = Args.get(args, SHOW_STACK_NAME, SHOW_STACK_DEFAULT);
int maxTests = Args.get(args, MAX_TESTS_ARG_NAME, Integer.MAX_VALUE);
int maxLength = Args.get(args, MAX_LENGTH_ARG_NAME, Integer.MAX_VALUE);
boolean showOldFailures = !Args.get(args, ONLY_REGRESSIONS_NAME, ONLY_REGRESSIONS_DEFAULT);
if(maxLength < Integer.MAX_VALUE) {
maxLength *= 1024;
}

if (maxTests > 0) {
int printedTests = 0;
int printedLength = 0;
for (CaseResult failedTest : testResult.getFailedTests()) {
if (showOldFailures || failedTest.getAge() == 1) {
if (printedTests < maxTests) {
outputTest(buffer, failedTest, showStacks);
if (printedTests < maxTests && printedLength <= maxLength) {
printedLength += outputTest(buffer, failedTest, showStacks, maxLength-printedLength);
printedTests++;
}
}
Expand All @@ -87,27 +98,46 @@ public <P extends AbstractProject<P, B>, B extends AbstractBuild<P, B>> String g
buffer.append(failCount - printedTests);
buffer.append(" other failed tests.\n\n");
}
if (printedLength >= maxLength) {
buffer.append("\n\n... output truncated.\n\n");
}
}
}

return buffer.toString();
}

private void outputTest(StringBuffer buffer, CaseResult failedTest,
boolean showStack) {
buffer.append(failedTest.getStatus().toString());
buffer.append(": ");
buffer.append(failedTest.getClassName());
buffer.append(".");
buffer.append(failedTest.getDisplayName());
buffer.append("\n\n");
buffer.append("Error Message:\n");
buffer.append(failedTest.getErrorDetails());
private int outputTest(StringBuffer buffer, CaseResult failedTest,
boolean showStack, int lengthLeft) {
StringBuffer local = new StringBuffer();
int currLength = buffer.length();

local.append(failedTest.getStatus().toString());
local.append(": ");

local.append(failedTest.getClassName());
local.append(".");

local.append(failedTest.getDisplayName());
local.append("\n\n");

local.append("Error Message:\n");
local.append(failedTest.getErrorDetails());

if (showStack) {
buffer.append("\n\nStack Trace:\n");
buffer.append(failedTest.getErrorStackTrace());
local.append("\n\n");
local.append("Stack Trace:\n");
local.append(failedTest.getErrorStackTrace());
}

local.append("\n\n");

if(local.length() > lengthLeft) {
local.setLength(lengthLeft);
}
buffer.append("\n\n");

buffer.append(local.toString());
return local.length();
}

public boolean hasNestedContent() {
Expand Down
@@ -1,17 +1,29 @@
package hudson.plugins.emailext.plugins.content;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import hudson.model.AbstractBuild;
import hudson.tasks.junit.CaseResult;
import hudson.tasks.test.AbstractTestResultAction;

import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

@SuppressWarnings({"unchecked"})
@RunWith(PowerMockRunner.class)
@PrepareForTest( { CaseResult.class })
public class FailedTestsContentTest
{
private FailedTestsContent failedTestContent;
Expand Down Expand Up @@ -62,4 +74,33 @@ public void testGetContent_whenSomeTestsFailedShouldGiveMeaningfulMessage()
assertEquals( "123 tests failed.\n", content );
}

@Test
public void testGetContent_whenContentLargerThanMaxLengthShouldTruncate()
{
AbstractTestResultAction<?> testResults = mock( AbstractTestResultAction.class );
when( testResults.getFailCount() ).thenReturn( 5 );

List<CaseResult> failedTests = new ArrayList<CaseResult>();
for(int i = 0; i < 5; i++) {
CaseResult result = mock( CaseResult.class );
when( result.getStatus() ).thenReturn( CaseResult.Status.FAILED );
when( result.getClassName() ).thenReturn( "hudson.plugins.emailext.ExtendedEmailPublisherTest" );
when( result.getDisplayName() ).thenReturn( "Test" + i );
when( result.getErrorDetails() ).thenReturn( StringUtils.leftPad( "", 3 * 1024, 'z' ) );
when( result.getErrorStackTrace() ).thenReturn( StringUtils.leftPad( "", 200, 'e' ) );
failedTests.add(result);
}
when( testResults.getFailedTests() ).thenReturn( failedTests );
when( build.getTestResultAction() ).thenReturn( testResults );

Map<String, Integer> args = Collections.singletonMap(
FailedTestsContent.MAX_LENGTH_ARG_NAME, 10 );
String content = failedTestContent.getContent( build, null, null, args );
assertTrue( content.length() < (3 * 1024 * 5) );

Map<String, Boolean> args2 = Collections.singletonMap(
"showStack", true);
content = failedTestContent.getContent( build, null, null, args2 );
assertTrue( content.length() >= (3 * 1024 * 5) );
}
}

0 comments on commit 4a441eb

Please sign in to comment.