提交 734e7e01 编写于 作者: J Jesse Glick

[FIXED JENKINS-15818] Display exceedingly slow for large test results.

上级 f8b6af8f
......@@ -61,6 +61,9 @@ Upcoming changes</a>
<li class=bug>
Build records were broken if timezone was changed while running.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-15816">issue 15816</a>)
<li class='major bug'>
Displaying massive test suite results could bring down Jenkins.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-15818">issue 15818</a>)
</ul>
</div><!--=TRUNK-END=-->
......
......@@ -54,6 +54,7 @@ public final class CaseResult extends TestResult implements Comparable<CaseResul
* This field retains the method name.
*/
private final String testName;
private transient String safeName;
private final boolean skipped;
private final String errorStackTrace;
private final String errorDetails;
......@@ -232,7 +233,10 @@ public final class CaseResult extends TestResult implements Comparable<CaseResul
/**
* Gets the version of {@link #getName()} that's URL-safe.
*/
public @Override String getSafeName() {
public @Override synchronized String getSafeName() {
if (safeName != null) {
return safeName;
}
StringBuilder buf = new StringBuilder(testName);
for( int i=0; i<buf.length(); i++ ) {
char ch = buf.charAt(i);
......@@ -240,7 +244,7 @@ public final class CaseResult extends TestResult implements Comparable<CaseResul
buf.setCharAt(i,'_');
}
Collection<CaseResult> siblings = (classResult ==null ? Collections.<CaseResult>emptyList(): classResult.getChildren());
return uniquifyName(siblings, buf.toString());
return safeName = uniquifyName(siblings, buf.toString());
}
/**
......
......@@ -42,6 +42,7 @@ import java.util.List;
*/
public final class ClassResult extends TabulatedResult implements Comparable<ClassResult> {
private final String className; // simple name
private transient String safeName;
private final List<CaseResult> cases = new ArrayList<CaseResult>();
......@@ -112,8 +113,11 @@ public final class ClassResult extends TabulatedResult implements Comparable<Cla
else return className.substring(idx+1);
}
public @Override String getSafeName() {
return uniquifyName(parent.getChildren(), safe(getName()));
public @Override synchronized String getSafeName() {
if (safeName != null) {
return safeName;
}
return safeName = uniquifyName(parent.getChildren(), safe(getName()));
}
public CaseResult getCaseResult(String name) {
......
......@@ -40,6 +40,7 @@ import java.util.*;
public final class PackageResult extends MetaTabulatedResult implements Comparable<PackageResult> {
private final String packageName;
private transient String safeName;
/**
* All {@link ClassResult}s keyed by their short name.
*/
......@@ -68,9 +69,12 @@ public final class PackageResult extends MetaTabulatedResult implements Comparab
}
@Override
public String getSafeName() {
public synchronized String getSafeName() {
if (safeName != null) {
return safeName;
}
Collection<PackageResult> siblings = (parent == null ? Collections.EMPTY_LIST : parent.getChildren());
return uniquifyName(
return safeName = uniquifyName(
siblings,
safe(getName()));
}
......
......@@ -42,8 +42,10 @@ import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -80,6 +82,7 @@ public final class SuiteResult implements Serializable {
* All test cases.
*/
private final List<CaseResult> cases = new ArrayList<CaseResult>();
private transient Map<String,CaseResult> casesByName;
private transient hudson.tasks.junit.TestResult parent;
SuiteResult(String name, String stdout, String stderr) {
......@@ -89,6 +92,16 @@ public final class SuiteResult implements Serializable {
this.file = null;
}
private synchronized Map<String,CaseResult> casesByName() {
if (casesByName == null) {
casesByName = new HashMap<String,CaseResult>();
for (CaseResult c : cases) {
casesByName.put(c.getName(), c);
}
}
return casesByName;
}
/**
* Passed to {@link ParserConfigurator}.
* @since 1.416
......@@ -217,6 +230,7 @@ public final class SuiteResult implements Serializable {
/*package*/ void addCase(CaseResult cr) {
cases.add(cr);
casesByName().put(cr.getName(), cr);
duration += cr.getDuration();
}
......@@ -294,11 +308,7 @@ public final class SuiteResult implements Serializable {
* Note that test name needs not be unique.
*/
public CaseResult getCase(String name) {
for (CaseResult c : cases) {
if(c.getName().equals(name))
return c;
}
return null;
return casesByName().get(name);
}
public Set<String> getClassNames() {
......
......@@ -32,8 +32,6 @@ import hudson.tasks.junit.TestAction;
import hudson.tasks.junit.TestResultAction;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.*;
import org.kohsuke.stapler.export.ExportedBean;
......@@ -41,8 +39,6 @@ import com.google.common.collect.MapMaker;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.logging.Logger;
......@@ -335,19 +331,25 @@ public abstract class TestObject extends hudson.tasks.junit.TestObject {
/**
* #2988: uniquifies a {@link #getSafeName} amongst children of the parent.
*/
protected final synchronized String uniquifyName(
Collection<? extends TestObject> siblings, String base) {
String uniquified = base;
int sequence = 1;
for (TestObject sibling : siblings) {
if (sibling != this && uniquified.equals(UNIQUIFIED_NAMES.get(sibling))) {
uniquified = base + '_' + ++sequence;
protected final String uniquifyName(Collection<? extends TestObject> siblings, String base) {
synchronized (UNIQUIFIED_NAMES) {
String uniquified = base;
Map<TestObject,Void> taken = UNIQUIFIED_NAMES.get(base);
if (taken == null) {
taken = new WeakHashMap<TestObject,Void>();
UNIQUIFIED_NAMES.put(base, taken);
} else {
Set<TestObject> similars = new HashSet<TestObject>(taken.keySet());
similars.retainAll(new HashSet<TestObject>(siblings));
if (!similars.isEmpty()) {
uniquified = base + '_' + (similars.size() + 1);
}
}
taken.put(this, null);
return uniquified;
}
UNIQUIFIED_NAMES.put(this, uniquified);
return uniquified;
}
private static final Map<TestObject, String> UNIQUIFIED_NAMES = new MapMaker().weakKeys().makeMap();
private static final Map<String,Map<TestObject,Void>> UNIQUIFIED_NAMES = new MapMaker().makeMap();
/**
* Replaces URL-unsafe characters.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册