Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2015-05-06 22:22:45 +02:00
22 changed files with 431 additions and 407 deletions
@@ -28,7 +28,6 @@ import com.intellij.openapi.extensions.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.*;
import com.intellij.util.containers.MultiMap;
@@ -614,7 +613,7 @@ public class PluginManagerCore {
String fileURL = StringUtil.replace(file.toURI().toASCIIString(), "!", "%21");
URL jarURL = new URL("jar:" + fileURL + "!/META-INF/" + fileName);
ZipFile zipFile = ZipFileCache.acquire(file.getPath());
ZipFile zipFile = new ZipFile(file);
try {
ZipEntry entry = zipFile.getEntry("META-INF/" + fileName);
if (entry != null) {
@@ -625,7 +624,7 @@ public class PluginManagerCore {
}
}
finally {
ZipFileCache.release(zipFile);
zipFile.close();
}
}
catch (XmlSerializationException e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package com.intellij.openapi.vfs.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import gnu.trove.THashMap;
@@ -43,7 +42,7 @@ public class ZipHandler extends ArchiveHandler {
Map<String, EntryInfo> map = new THashMap<String, EntryInfo>();
map.put("", createRootEntry());
ZipFile zip = getZipFile();
ZipFile zip = new ZipFile(getFileToUse());
try {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
@@ -51,7 +50,7 @@ public class ZipHandler extends ArchiveHandler {
}
}
finally {
ZipFileCache.release(zip);
zip.close();
}
return map;
@@ -62,11 +61,6 @@ public class ZipHandler extends ArchiveHandler {
return getFile();
}
@NotNull
private ZipFile getZipFile() throws IOException {
return ZipFileCache.acquire(getFileToUse().getPath());
}
@NotNull
private EntryInfo getOrCreate(ZipEntry entry, Map<String, EntryInfo> map, ZipFile zip) {
boolean isDirectory = entry.isDirectory();
@@ -117,7 +111,7 @@ public class ZipHandler extends ArchiveHandler {
@NotNull
@Override
public byte[] contentsToByteArray(@NotNull String relativePath) throws IOException {
ZipFile zip = getZipFile();
ZipFile zip = new ZipFile(getFileToUse());
try {
ZipEntry entry = zip.getEntry(relativePath);
if (entry != null) {
@@ -133,7 +127,7 @@ public class ZipHandler extends ArchiveHandler {
}
}
finally {
ZipFileCache.release(zip);
zip.close();
}
return ArrayUtil.EMPTY_BYTE_ARRAY;
@@ -17,6 +17,7 @@ package com.intellij.execution.console;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -76,7 +77,8 @@ public class ConsoleExecuteAction extends DumbAwareAction {
if (enabled) {
Lookup lookup = LookupManager.getActiveLookup(editor);
// we should check getCurrentItem() also - fast typing could produce outdated lookup, such lookup reports isCompletion() true
enabled = lookup == null || !lookup.isCompletion() || lookup.getCurrentItem() == null;
enabled = lookup == null || !lookup.isCompletion() || lookup.getCurrentItem() == null ||
(lookup instanceof LookupImpl && ((LookupImpl)lookup).getFocusDegree() == LookupImpl.FocusDegree.UNFOCUSED);
}
e.getPresentation().setEnabled(enabled);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ public abstract class RefreshQueue {
refresh(async, recursive, finishRunnable, getDefaultModalityState(), files);
}
public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull Collection<VirtualFile> files) {
public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull Collection<? extends VirtualFile> files) {
refresh(async, recursive, finishRunnable, getDefaultModalityState(), files);
}
@@ -62,7 +62,7 @@ public abstract class RefreshQueue {
boolean recursive,
@Nullable Runnable finishRunnable,
@NotNull ModalityState state,
@NotNull Collection<VirtualFile> files) {
@NotNull Collection<? extends VirtualFile> files) {
RefreshSession session = createSession(async, recursive, finishRunnable, state);
session.addAllFiles(files);
session.launch();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ public abstract class RefreshSession {
public abstract void addFile(@NotNull VirtualFile file);
public abstract void addAllFiles(@NotNull Collection<VirtualFile> files);
public abstract void addAllFiles(@NotNull Collection<? extends VirtualFile> files);
public void addAllFiles(@NotNull VirtualFile... files) {
addAllFiles(Arrays.asList(files));
@@ -37,15 +37,17 @@ public class IntelliJCheckBoxUI extends DarculaCheckBoxUI {
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g.setStroke(new BasicStroke(JBUI.scale(1) *2.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
g.setPaint(getShadowColor(enabled, true));
final int x1 = JBUI.scale(5);
final int y1 = JBUI.scale(9);
final int x2 = JBUI.scale(7);
final int y2 = JBUI.scale(11);
g.drawLine(x1, y1, x2, y2);
g.drawLine(x2, y2, w-JBUI.scale(2) - 1, JBUI.scale(5));
if (enabled) {
g.setPaint(getShadowColor(true, true));
g.drawLine(x1, y1, x2, y2);
g.drawLine(x2, y2, w - JBUI.scale(2) - 1, JBUI.scale(5));
}
g.setPaint(getCheckSignColor(enabled, true));
g.drawLine(x1, y1 - 2, x2, y2 - 2);
g.drawLine(x2, y2 - 2, w-JBUI.scale(2) - 1, JBUI.scale(5) - 2);
g.drawLine(x2, y2 - 2, w - JBUI.scale(2) - 1, JBUI.scale(5) - 2);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,7 +77,7 @@ public class RefreshSessionImpl extends RefreshSession {
}
@Override
public void addAllFiles(@NotNull Collection<VirtualFile> files) {
public void addAllFiles(@NotNull Collection<? extends VirtualFile> files) {
for (VirtualFile file : files) {
if (file == null) {
LOG.error("null passed among " + files);
@@ -21,7 +21,6 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VFileProperty;
@@ -297,7 +296,7 @@ public class VfsImplUtil {
}
private static class InvalidationState {
private Map<String, VirtualFile> rootsToRefresh;
private Set<NewVirtualFile> myRootsToRefresh;
@Nullable
public static InvalidationState invalidate(@Nullable InvalidationState state, final String path) {
@@ -323,19 +322,18 @@ public class VfsImplUtil {
private void registerPathToRefresh(String path, ArchiveFileSystem vfs) {
NewVirtualFile root = ManagingFS.getInstance().findRoot(vfs.composeRootPath(path), vfs);
if (root != null) {
if (rootsToRefresh == null) rootsToRefresh = ContainerUtil.newHashMap();
rootsToRefresh.put(path, root);
if (myRootsToRefresh == null) myRootsToRefresh = ContainerUtil.newHashSet();
myRootsToRefresh.add(root);
}
}
public void scheduleRefresh() {
if (rootsToRefresh != null) {
for (VirtualFile root : rootsToRefresh.values()) {
((NewVirtualFile)root).markDirtyRecursively();
if (myRootsToRefresh != null) {
for (NewVirtualFile root : myRootsToRefresh) {
root.markDirtyRecursively();
}
ZipFileCache.reset(rootsToRefresh.keySet());
boolean async = !ApplicationManager.getApplication().isUnitTestMode();
RefreshQueue.getInstance().refresh(async, true, null, rootsToRefresh.values());
RefreshQueue.getInstance().refresh(async, true, null, myRootsToRefresh);
}
}
}
@@ -259,6 +259,11 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte
if (forceUpdate || !Comparing.equal(myKey, selected)) {
handleSelectionChange(selected, true);
}
// Temporary workaround
if (e.getClickCount() == 2) {
hideHint();
}
}
protected void handleSelectionChange(KeyType selected) {
@@ -50,6 +50,8 @@ public abstract class GeneralTestEventsProcessor implements Disposable {
// tree construction events
public void onRootPresentationAdded(String rootName, String comment) {}
public void onSuiteTreeNodeAdded(String testName, String locationHint) { }
public void onSuiteTreeStarted(String suiteName, String locationHint) { }
@@ -114,6 +114,17 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
});
}
@Override
public void onRootPresentationAdded(final String rootName, final String comment) {
addToInvokeLater(new Runnable() {
@Override
public void run() {
myTestsRootNode.setPresentation(rootName);
myTestsRootNode.setComment(comment);
}
});
}
@Override
public void onSuiteTreeNodeAdded(final String testName, final String locationHint) {
myTreeBuildBeforeStart = true;
@@ -214,6 +214,14 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
}
private void fireRootPresentationAdded(String rootName, @Nullable String comment) {
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
processor.onRootPresentationAdded(rootName, comment);
}
}
private void fireOnSuiteTreeStarted(String suiteName, String locationHint) {
final GeneralTestEventsProcessor processor = myProcessor;
@@ -308,6 +316,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
@NonNls private static final String SUITE_TREE_STARTED = "suiteTreeStarted";
@NonNls private static final String SUITE_TREE_ENDED = "suiteTreeEnded";
@NonNls private static final String SUITE_TREE_NODE = "suiteTreeNode";
@NonNls private static final String ROOT_PRESENTATION = "rootName";
@NonNls private static final String ATTR_KEY_STATUS = "status";
@NonNls private static final String ATTR_VALUE_STATUS_ERROR = "ERROR";
@NonNls private static final String ATTR_VALUE_STATUS_WARNING = "WARNING";
@@ -489,6 +499,10 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
else if (SUITE_TREE_NODE.equals(name)) {
fireOnSuiteTreeNodeAdded(msg.getAttributes().get("name"), msg.getAttributes().get(ATTR_KEY_LOCATION_URL));
}
else if (ROOT_PRESENTATION.equals(name)) {
final Map<String, String> attributes = msg.getAttributes();
fireRootPresentationAdded(attributes.get("name"), attributes.get("comment"));
}
else {
GeneralToSMTRunnerEventsConvertor.logProblem(LOG, "Unexpected service message:" + name, myTestFrameworkName);
}
@@ -740,6 +740,9 @@ public class SMTestProxy extends AbstractTestProxy {
public static class SMRootTestProxy extends SMTestProxy {
private boolean myTestsReporterAttached; // false by default
private String myPresentation;
private String myComment;
public SMRootTestProxy() {
super("[root]", true, null);
}
@@ -752,6 +755,22 @@ public class SMTestProxy extends AbstractTestProxy {
return myTestsReporterAttached;
}
public String getPresentation() {
return myPresentation;
}
public void setPresentation(String presentation) {
myPresentation = presentation;
}
public void setComment(String comment) {
myComment = comment;
}
public String getComment() {
return myComment;
}
@Override
protected AbstractState determineSuiteStateOnFinished() {
if (isLeaf() && !isTestsReporterAttached()) {
@@ -145,7 +145,10 @@ public class TestsPresentationUtil {
final TestStateInfo.Magnitude magnitude = testProxy.getMagnitudeInfo();
final String text;
if (magnitude == TestStateInfo.Magnitude.RUNNING_INDEX) {
final String presentableName = testProxy.getPresentation();
if (presentableName != null) {
text = presentableName;
} else if (magnitude == TestStateInfo.Magnitude.RUNNING_INDEX) {
text = SMTestsRunnerBundle.message("sm.test.runner.ui.tests.tree.presentation.labels.running.tests");
} else if (magnitude == TestStateInfo.Magnitude.TERMINATED_INDEX) {
text = SMTestsRunnerBundle.message("sm.test.runner.ui.tests.tree.presentation.labels.was.terminated");
@@ -153,6 +156,10 @@ public class TestsPresentationUtil {
text = SMTestsRunnerBundle.message("sm.test.runner.ui.tests.tree.presentation.labels.test.results");
}
renderer.append(text, SimpleTextAttributes.REGULAR_ATTRIBUTES);
final String comment = testProxy.getComment();
if (comment != null) {
renderer.append(" (" + comment + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
}
}
public static void formatRootNodeWithoutChildren(final SMTestProxy.SMRootTestProxy testProxy,
@@ -15,259 +15,26 @@
*/
package com.intellij.openapi.util.io;
import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipFile;
/**
* <p>Utility class which tries to keep frequently requested .zip files open
* to avoid time loss on closing/reopening ZipFile instances.</p>
*
* <p>Clients obtain a file by calling {@link #acquire(String)}
* and indicate the loss of interest to it via {@link #release(ZipFile)}.
* Released files are closed after some period of time (about 30 seconds),
* unless requested again within the period.</p>
*
* <p>Since ZipFiles are read-only objects allowing concurrent access,
* a same instance may be returned to a different threads requesting a same path.
* A file may be closed only after being released by all applicants.</p>
*
* <p>The class does not expect .zip files on a disk to be changed,
* so it may return an outdated instance of ZipFile (reading from it
* may return inaccurate data or even cause an exceptions to happen).
* It's a clients' responsibility to keep a track of .zip files
* and call the {@link #reset(Collection)} method for a paths
* which are possibly changed. Reset paths are removed from the cache
* and are closed immediately after being released.</p>
*/
/** @deprecated use {@link ZipFile#ZipFile(String)} and {@link ZipFile#close()} instead (to be removed in IDEA 17) */
@SuppressWarnings("unused")
public class ZipFileCache {
private static final int PERIOD = 10000; // disposer schedule, ms
private static final int TIMEOUT = 30000; // released file close delay, ms
private static class CacheRecord {
private final String path;
private final ZipFile file;
private int count = 1;
private long released = 0;
private CacheRecord(@NotNull String path, @NotNull ZipFile file) throws IOException {
this.path = path;
this.file = file;
}
}
private static final Object ourLock = new Object();
private static final Map<String, CacheRecord> ourPathCache = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
private static final Map<ZipFile, CacheRecord> ourFileCache = ContainerUtil.newHashMap();
private static final Map<ZipFile, Integer> ourQueue = ContainerUtil.newHashMap();
private static final ScheduledThreadPoolExecutor ourExecutor;
static {
ourExecutor = ConcurrencyUtil.newSingleScheduledThreadExecutor("ZipFileCache Dispose", Thread.MIN_PRIORITY);
ourExecutor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
List<ZipFile> toClose = getFilesToClose(0, System.currentTimeMillis() - TIMEOUT);
if (toClose != null) {
close(toClose);
}
}
}, PERIOD, PERIOD, TimeUnit.MILLISECONDS);
}
@NotNull
public static ZipFile acquire(@NotNull String path) throws IOException {
path = toCanonicalPath(path);
synchronized (ourLock) {
CacheRecord record = ourPathCache.get(path);
if (record != null) {
record.count++;
return record.file;
}
}
CacheRecord record;
ZipFile file = tryOpen(path);
synchronized (ourLock) {
record = ourPathCache.get(path);
if (record == null) {
record = new CacheRecord(path, file);
ourPathCache.put(path, record);
ourFileCache.put(file, record);
return file;
}
else {
record.count++;
}
}
close(file);
return record.file;
}
private static String toCanonicalPath(@NotNull String path) {
path = FileUtil.toSystemDependentName(path);
File file = new File(path);
try {
return file.getCanonicalPath();
}
catch (IOException e) {
return file.getAbsolutePath();
}
}
private static ZipFile tryOpen(String path) throws IOException {
debug("opening %s", path);
try {
return new ZipFile(path);
}
catch (IOException e) {
String reason = e.getMessage();
if ("too many open files".equalsIgnoreCase(reason) && tryCloseFiles() > 0) {
return new ZipFile(path);
}
else {
throw e;
}
}
}
private static int tryCloseFiles() {
List<ZipFile> toClose = getFilesToClose(5, 0);
if (toClose == null) return 0;
close(toClose);
logger().warn("too many open files, closed: " + toClose.size());
return toClose.size();
}
@Nullable
private static List<ZipFile> getFilesToClose(int limit, long timeout) {
List<ZipFile> toClose = null;
synchronized (ourLock) {
Iterator<CacheRecord> i = ourPathCache.values().iterator();
while (i.hasNext() && (limit == 0 || toClose == null || toClose.size() < limit)) {
CacheRecord record = i.next();
if (record.count <= 0 && (timeout == 0 || record.released <= timeout)) {
i.remove();
ourFileCache.remove(record.file);
if (toClose == null) toClose = ContainerUtil.newArrayList();
toClose.add(record.file);
}
}
}
return toClose;
return new ZipFile(path);
}
public static void release(@NotNull ZipFile file) {
synchronized (ourLock) {
CacheRecord record = ourFileCache.get(file);
if (record != null) {
record.count--;
record.released = System.currentTimeMillis();
logger().assertTrue(record.count >= 0, record.path);
return;
}
Integer count = ourQueue.get(file);
if (count != null) {
count--;
if (count == 0) {
ourQueue.remove(file);
close(file);
}
else {
ourQueue.put(file, count);
}
return;
}
}
logger().warn(new IllegalArgumentException("stray file: " + file.getName()));
close(file);
try { file.close(); }
catch (IOException ignored) { }
}
public static void reset(@NotNull Collection<String> paths) {
debug("resetting %s", paths);
public static void reset(Collection<String> paths) { }
List<ZipFile> toClose = ContainerUtil.newSmartList();
paths = ContainerUtil.map(paths, new Function<String, String>() {
@Override
public String fun(String path) {
return toCanonicalPath(path);
}
});
synchronized (ourLock) {
for (String path : paths) {
CacheRecord record = ourPathCache.remove(path);
if (record != null) {
ourFileCache.remove(record.file);
if (record.count > 0) {
ourQueue.put(record.file, record.count);
}
else {
toClose.add(record.file);
}
}
}
}
close(toClose);
}
private static void close(@NotNull List<ZipFile> files) {
for (ZipFile file : files) {
close(file);
}
}
private static void close(@NotNull ZipFile file) {
debug("closing %s", file.getName());
try {
file.close();
}
catch (IOException e) {
logger().info(file.getName(), e);
}
}
private static Logger logger() {
return Logger.getInstance(ZipFileCache.class);
}
private static void debug(@NotNull String format, Object... args) {
LogUtil.debug(logger(), format, args);
}
/**
* ZipFileCache maintains a background thread. In server environments, this thread may run indefinitely and prevent the class loader from
* being gc-ed. Thus it's necessary to invoke this method to stop that thread and let the classes be garbage-collected.
*/
@SuppressWarnings("unused")
public static void stopBackgroundThread() {
if (ourExecutor != null) {
ourExecutor.shutdown();
}
}
public static void stopBackgroundThread() { }
}
@@ -16,15 +16,15 @@
package com.intellij.util.lang;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.misc.Resource;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
@@ -32,15 +32,14 @@ import java.util.zip.ZipFile;
class JarLoader extends Loader {
private final URL myURL;
private final boolean myCanLockJar;
private SoftReference<JarMemoryLoader> myMemoryLoader;
JarLoader(URL url, boolean canLockJar, int index, boolean preloadJarContents) throws IOException {
// todo drop unused parameter
JarLoader(URL url, @SuppressWarnings("unused") boolean canLockJar, int index, boolean preloadJarContents) throws IOException {
super(new URL(URLUtil.JAR_PROTOCOL, "", -1, url + "!/"), index);
myURL = url;
myCanLockJar = canLockJar;
ZipFile zipFile = acquireZipFile();
ZipFile zipFile = new ZipFile(getFileUrl());
try {
if (preloadJarContents) {
JarMemoryLoader loader = JarMemoryLoader.load(zipFile, getBaseURL());
@@ -50,29 +49,23 @@ class JarLoader extends Loader {
}
}
finally {
releaseZipFile(zipFile);
}
}
private ZipFile acquireZipFile() throws IOException {
String path = FileUtil.unquote(myURL.getFile());
//noinspection IOResourceOpenedButNotSafelyClosed
return myCanLockJar ? ZipFileCache.acquire(path) : new ZipFile(path);
}
private void releaseZipFile(ZipFile zipFile) throws IOException {
if (myCanLockJar) {
ZipFileCache.release(zipFile);
}
else {
zipFile.close();
}
}
private File getFileUrl() throws IOException {
try {
return new File(myURL.toURI());
}
catch (URISyntaxException e) {
throw new IOException(e);
}
}
@NotNull
@Override
public ClasspathCache.LoaderData buildData() throws IOException {
ZipFile zipFile = acquireZipFile();
ZipFile zipFile = new ZipFile(getFileUrl());
try {
ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData();
Enumeration<? extends ZipEntry> entries = zipFile.entries();
@@ -85,7 +78,7 @@ class JarLoader extends Loader {
return loaderData;
}
finally {
releaseZipFile(zipFile);
zipFile.close();
}
}
@@ -99,7 +92,7 @@ class JarLoader extends Loader {
}
try {
ZipFile zipFile = acquireZipFile();
ZipFile zipFile = new ZipFile(getFileUrl());
try {
ZipEntry entry = zipFile.getEntry(name);
if (entry != null) {
@@ -107,7 +100,7 @@ class JarLoader extends Loader {
}
}
finally {
releaseZipFile(zipFile);
zipFile.close();
}
}
catch (Exception e) {
+3
View File
@@ -55,6 +55,9 @@
<stacktrace.fold substring="at org.junit.Assert.assert"/>
<stacktrace.fold substring="at com.intellij.junit3."/>
<stacktrace.fold substring="at com.intellij.junit4."/>
<stacktrace.fold substring="at junit.framework.TestSuite.run"/>
<stacktrace.fold substring="at junit.framework.TestCase.run"/>
<stacktrace.fold substring="at junit.framework.TestResult"/>
</extensions>
@@ -25,6 +25,9 @@ import org.junit.runner.Result;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class JUnitTreeByDescriptionHierarchyTest {
@Test
@@ -35,32 +38,96 @@ public class JUnitTreeByDescriptionHierarchyTest {
@Test
public void test2Parameterized() throws Exception {
final Description root = Description.createSuiteDescription("root");
final ArrayList<Description> tests = new ArrayList<Description>();
for (String className : new String[]{"a.TestA", "a.TestB"}) {
final Description aTestClass = Description.createSuiteDescription(className);
root.addChild(aTestClass);
for (String paramName : new String[]{"[0]", "[1]"}) {
final Description param1 = Description.createSuiteDescription(paramName);
aTestClass.addChild(param1);
param1.addChild(Description.createTestDescription(className, "testName" + paramName));
}
attachParameterizedTests(className, aTestClass, tests);
}
doTest(root, "##teamcity[suiteTreeStarted name='TestA' locationHint='java:suite://a.TestA']\n" +
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://a.TestA.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://a.TestA.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://a.TestA.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://a.TestA.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n" +
"##teamcity[suiteTreeEnded name='TestA']\n" +
"##teamcity[suiteTreeStarted name='TestB' locationHint='java:suite://a.TestB']\n" +
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://a.TestB.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://a.TestB.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://a.TestB.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://a.TestB.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n" +
"##teamcity[suiteTreeEnded name='TestB']\n");
doTest(root, tests,
"##teamcity[suiteTreeStarted name='TestA' locationHint='java:suite://a.TestA']\n" +
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://a.TestA.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://a.TestA.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://a.TestA.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://a.TestA.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n" +
"##teamcity[suiteTreeEnded name='TestA']\n" +
"##teamcity[suiteTreeStarted name='TestB' locationHint='java:suite://a.TestB']\n" +
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://a.TestB.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://a.TestB.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://a.TestB.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://a.TestB.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n" +
"##teamcity[suiteTreeEnded name='TestB']\n",
"##teamcity[enteredTheMatrix]\n" +
"\n" +
"##teamcity[rootName name = 'root']\n" +
"\n" +
"##teamcity[testSuiteFinished name='root']\n" +
"##teamcity[testSuiteStarted name ='TestA']\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
"##teamcity[testStarted name='testName|[0|]' locationHint='java:test://a.TestA.testName|[0|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[0|]']\n" +
"##teamcity[testSuiteFinished name='|[0|]']\n" +
"##teamcity[testSuiteStarted name ='|[1|]']\n" +
"##teamcity[testStarted name='testName|[1|]' locationHint='java:test://a.TestA.testName|[1|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[1|]']\n" +
"##teamcity[testSuiteFinished name='|[1|]']\n" +
"##teamcity[testSuiteFinished name='TestA']\n" +
"##teamcity[testSuiteStarted name ='TestB']\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
"##teamcity[testStarted name='testName|[0|]' locationHint='java:test://a.TestB.testName|[0|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[0|]']\n" +
"##teamcity[testSuiteFinished name='|[0|]']\n" +
"##teamcity[testSuiteStarted name ='|[1|]']\n" +
"##teamcity[testStarted name='testName|[1|]' locationHint='java:test://a.TestB.testName|[1|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[1|]']\n" +
"##teamcity[testSuiteFinished name='|[1|]']\n" +
"\n" +
"##teamcity[testSuiteFinished name='TestB']\n" +
"\n");
}
@Test
public void testSingleParameterizedClass() throws Exception {
final String className = "a.TestA";
final Description aTestClassDescription = Description.createSuiteDescription(className);
final ArrayList<Description> tests = new ArrayList<Description>();
attachParameterizedTests(className, aTestClassDescription, tests);
doTest(aTestClassDescription, tests,
//tree
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://a.TestA.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://a.TestA.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://a.TestA.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://a.TestA.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n",
//start
"##teamcity[enteredTheMatrix]\n" +
"\n" +
"##teamcity[rootName name = 'TestA' comment = 'a']\n" +
"\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
"##teamcity[testStarted name='testName|[0|]' locationHint='java:test://a.TestA.testName|[0|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[0|]']\n" +
"##teamcity[testSuiteFinished name='|[0|]']\n" +
"##teamcity[testSuiteStarted name ='|[1|]']\n" +
"##teamcity[testStarted name='testName|[1|]' locationHint='java:test://a.TestA.testName|[1|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[1|]']\n" +
"##teamcity[testSuiteFinished name='|[1|]']\n" +
"\n" +
"##teamcity[testSuiteFinished name='TestA']\n" +
"\n");
}
@Test
@@ -68,17 +135,76 @@ public class JUnitTreeByDescriptionHierarchyTest {
final Description root = Description.createSuiteDescription("root");
final String className = "ATest";
final String methodName = "test1";
final List<Description> tests = new ArrayList<Description>();
for( String suiteName : new String[] {"ASuite1", "ASuite2"}) {
final Description aSuite = Description.createSuiteDescription(suiteName);
root.addChild(aSuite);
final Description aTest = Description.createSuiteDescription(className);
aSuite.addChild(aTest);
aTest.addChild(Description.createTestDescription(className, methodName));
final Description testDescription = Description.createTestDescription(className, methodName);
tests.add(testDescription);
aTest.addChild(testDescription);
}
doTest(root, "##teamcity[suiteTreeStarted name='ATest' locationHint='java:suite://ATest']\n" +
"##teamcity[suiteTreeNode name='test1' locationHint='java:test://ATest.test1']\n" +
"##teamcity[suiteTreeEnded name='ATest']\n");
doTest(root, tests,
//expected tree
"##teamcity[suiteTreeStarted name='ASuite1' locationHint='java:suite://ASuite1']\n" +
"##teamcity[suiteTreeStarted name='ATest' locationHint='java:suite://ATest']\n" +
"##teamcity[suiteTreeNode name='test1' locationHint='java:test://ATest.test1']\n" +
"##teamcity[suiteTreeEnded name='ATest']\n" +
"##teamcity[suiteTreeEnded name='ASuite1']\n" +
"##teamcity[suiteTreeStarted name='ASuite2' locationHint='java:suite://ASuite2']\n" +
"##teamcity[suiteTreeStarted name='ATest' locationHint='java:suite://ATest']\n" +
"##teamcity[suiteTreeNode name='test1' locationHint='java:test://ATest.test1']\n" +
"##teamcity[suiteTreeEnded name='ATest']\n" +
"##teamcity[suiteTreeEnded name='ASuite2']\n",
//started
"##teamcity[enteredTheMatrix]\n" +
"\n" +
"##teamcity[rootName name = 'root']\n" +
"\n" +
"##teamcity[testSuiteFinished name='root']\n" +
"##teamcity[testSuiteStarted name ='ASuite1']\n" +
"##teamcity[testSuiteStarted name ='ATest']\n" +
"##teamcity[testStarted name='test1' locationHint='java:test://ATest.test1']\n" +
"\n" +
"##teamcity[testFinished name='test1']\n" +
"##teamcity[testSuiteFinished name='ATest']\n" +
"##teamcity[testSuiteFinished name='ASuite1']\n" +
"##teamcity[testSuiteStarted name ='ASuite2']\n" +
"##teamcity[testSuiteStarted name ='ATest']\n" +
"##teamcity[testStarted name='test1' locationHint='java:test://ATest.test1']\n" +
"\n" +
"##teamcity[testFinished name='test1']\n" +
"##teamcity[testSuiteFinished name='ATest']\n" +
"\n" +
"##teamcity[testSuiteFinished name='ASuite2']\n" +
"\n");
}
private static void doTest(Description root, List<Description> tests, String expectedTree, String expectedStart) throws Exception {
final StringBuffer buf = new StringBuffer();
final SMTestSender sender = new SMTestSender(new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
buf.append(new String(new byte[]{(byte)b}));
}
}));
sender.sendTree(root);
Assert.assertEquals("output: " + buf, expectedTree, StringUtil.convertLineSeparators(buf.toString()));
buf.setLength(0);
sender.testRunStarted(root);
for (Description test : tests) {
sender.testStarted(test);
sender.testFinished(test);
}
sender.testRunFinished(new Result());
Assert.assertEquals("output: " + buf, expectedStart, StringUtil.convertLineSeparators(buf.toString()));
}
@Test
@@ -92,27 +218,70 @@ public class JUnitTreeByDescriptionHierarchyTest {
final Description root = Description.createSuiteDescription("root");
final Description aTestClass = Description.createSuiteDescription("ATest");
root.addChild(aTestClass);
for (String paramName : new String[]{"[0]", "[1]"}) {
final Description param1 = Description.createSuiteDescription(paramName);
aTestClass.addChild(param1);
param1.addChild(Description.createTestDescription("ATest", "testName" + paramName));
}
final ArrayList<Description> tests = new ArrayList<Description>();
attachParameterizedTests("ATest", aTestClass, tests);
final Description suiteDescription = Description.createSuiteDescription("suite");
root.addChild(suiteDescription);
final Description aTestClassWithJUnit3Test = Description.createSuiteDescription("ATest");
suiteDescription.addChild(aTestClassWithJUnit3Test);
aTestClassWithJUnit3Test.addChild(Description.createTestDescription("ATest", "test"));
doTest(root, "##teamcity[suiteTreeStarted name='ATest' locationHint='java:suite://ATest']\n" +
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://ATest.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://ATest.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://ATest.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://ATest.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n" +
"##teamcity[suiteTreeNode name='test' locationHint='java:test://ATest.test']\n" +
"##teamcity[suiteTreeEnded name='ATest']\n");
final Description testDescription = Description.createTestDescription("ATest", "test");
aTestClassWithJUnit3Test.addChild(testDescription);
tests.add(testDescription);
doTest(root, tests,
"##teamcity[suiteTreeStarted name='ATest' locationHint='java:suite://ATest']\n" +
"##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://ATest.|[0|]']\n" +
"##teamcity[suiteTreeNode name='testName|[0|]' locationHint='java:test://ATest.testName|[0|]']\n" +
"##teamcity[suiteTreeEnded name='|[0|]']\n" +
"##teamcity[suiteTreeStarted name='|[1|]' locationHint='java:suite://ATest.|[1|]']\n" +
"##teamcity[suiteTreeNode name='testName|[1|]' locationHint='java:test://ATest.testName|[1|]']\n" +
"##teamcity[suiteTreeEnded name='|[1|]']\n" +
"##teamcity[suiteTreeEnded name='ATest']\n" +
"##teamcity[suiteTreeStarted name='suite' locationHint='java:suite://suite']\n" +
"##teamcity[suiteTreeStarted name='ATest' locationHint='java:suite://ATest']\n" +
"##teamcity[suiteTreeNode name='test' locationHint='java:test://ATest.test']\n" +
"##teamcity[suiteTreeEnded name='ATest']\n" +
"##teamcity[suiteTreeEnded name='suite']\n",
//start
"##teamcity[enteredTheMatrix]\n" +
"\n" +
"##teamcity[rootName name = 'root']\n" +
"\n" +
"##teamcity[testSuiteFinished name='root']\n" +
"##teamcity[testSuiteStarted name ='ATest']\n" +
"##teamcity[testSuiteStarted name ='|[0|]']\n" +
"##teamcity[testStarted name='testName|[0|]' locationHint='java:test://ATest.testName|[0|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[0|]']\n" +
"##teamcity[testSuiteFinished name='|[0|]']\n" +
"##teamcity[testSuiteStarted name ='|[1|]']\n" +
"##teamcity[testStarted name='testName|[1|]' locationHint='java:test://ATest.testName|[1|]']\n" +
"\n" +
"##teamcity[testFinished name='testName|[1|]']\n" +
"##teamcity[testSuiteFinished name='|[1|]']\n" +
"##teamcity[testSuiteFinished name='ATest']\n" +
"##teamcity[testSuiteStarted name ='suite']\n" +
"##teamcity[testSuiteStarted name ='ATest']\n" +
"##teamcity[testStarted name='test' locationHint='java:test://ATest.test']\n" +
"\n" +
"##teamcity[testFinished name='test']\n" +
"##teamcity[testSuiteFinished name='ATest']\n" +
"\n" +
"##teamcity[testSuiteFinished name='suite']\n" +
"\n");
}
private static void attachParameterizedTests(String className, Description aTestClass, List<Description> tests) {
for (String paramName : new String[]{"[0]", "[1]"}) {
final Description param1 = Description.createSuiteDescription(paramName);
aTestClass.addChild(param1);
final Description testDescription = Description.createTestDescription(className, "testName" + paramName);
tests.add(testDescription);
param1.addChild(testDescription);
}
}
private static void doTest(Description description, String expected) {
final StringBuffer buf = new StringBuffer();
new SMTestSender(new PrintStream(new OutputStream() {
@@ -130,31 +299,18 @@ public class JUnitTreeByDescriptionHierarchyTest {
final Description description = Description.createSuiteDescription("TestA");
final Description emptyDescription = Description.createTestDescription(SMTestSender.EMPTY_SUITE_NAME, SMTestSender.EMPTY_SUITE_WARNING);
description.addChild(emptyDescription);
doTest(description, Collections.singletonList(emptyDescription),
"##teamcity[suiteTreeNode name='warning' locationHint='java:test://TestA.warning']\n",
final StringBuffer buf = new StringBuffer();
final PrintStream printStream = new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
buf.append(new String(new byte[]{(byte)b}));
}
});
final SMTestSender sender = new SMTestSender(printStream);
sender.sendTree(description);
sender.testRunStarted(description);
sender.testStarted(emptyDescription);
sender.testFinished(emptyDescription);
sender.testRunFinished(new Result());
Assert.assertEquals("output: " + buf, "##teamcity[suiteTreeNode name='warning' locationHint='java:test://junit.framework.TestSuite$1.warning']\n" +
"##teamcity[enteredTheMatrix]\n" +
"\n" +
"##teamcity[testStarted name='warning' locationHint='java:test://junit.framework.TestSuite$1.warning']\n" +
"\n" +
"##teamcity[testFinished name='warning']\n" +
"##teamcity[testSuiteFinished name='TestA']\n" +
"\n", StringUtil.convertLineSeparators(buf.toString()));
"##teamcity[enteredTheMatrix]\n" +
"\n" +
"##teamcity[rootName name = 'TestA']\n" +
"\n" +
"##teamcity[testStarted name='warning' locationHint='java:test://junit.framework.TestSuite$1.warning']\n" +
"\n" +
"##teamcity[testFinished name='warning']\n" +
"##teamcity[testSuiteFinished name='TestA']\n" +
"\n");
}
}
@@ -52,7 +52,7 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner {
description = getFilteredDescription(request, description);
}
TreeSender.sendTree(this, description, sendTree);
if (myTestsListener instanceof SMTestSender) {
if (myTestsListener instanceof SMTestSender && sendTree) {
((SMTestSender)myTestsListener).sendTree(description);
}
}
@@ -41,10 +41,14 @@ public class SMTestSender extends RunListener {
public static final String EMPTY_SUITE_NAME = "junit.framework.TestSuite$1";
public static final String EMPTY_SUITE_WARNING = "warning";
private String myCurrentSuiteName;
private String myCurrentClassName;
private String myParamName;
private PrintStream myPrintStream = System.out;
private final Map myParents = new HashMap();
private final Map mySuites = new HashMap();
public SMTestSender() {}
@@ -58,6 +62,20 @@ public class SMTestSender extends RunListener {
public void testRunStarted(Description description) throws Exception {
myPrintStream.println("##teamcity[enteredTheMatrix]\n");
if (myCurrentClassName != null && !myCurrentClassName.startsWith("[")) {
int lastPointIdx = myCurrentClassName.lastIndexOf('.');
String name = myCurrentClassName;
String comment = null;
if (lastPointIdx >= 0) {
name = myCurrentClassName.substring(lastPointIdx + 1);
comment = myCurrentClassName.substring(0, lastPointIdx);
}
myPrintStream.println("##teamcity[rootName name = \'" + escapeName(name) +
(comment != null ? ("\' comment = \'" + escapeName(comment)) : "") +
"\']\n");
myCurrentClassName = getShortName(myCurrentClassName);
}
}
public void testRunFinished(Result result) throws Exception {
@@ -67,6 +85,9 @@ public class SMTestSender extends RunListener {
if (myCurrentClassName != null) {
myPrintStream.println("##teamcity[testSuiteFinished name=\'" + escapeName(myCurrentClassName) + "\']\n");
}
if (myCurrentSuiteName != null) {
myPrintStream.println("##teamcity[testSuiteFinished name=\'" + escapeName(getShortName(myCurrentSuiteName)) + "\']\n");
}
}
public void testStarted(Description description) throws Exception {
@@ -77,10 +98,35 @@ public class SMTestSender extends RunListener {
myPrintStream.println("##teamcity[testSuiteFinished name=\'" + escapeName(myParamName) + "\']");
myParamName = null;
}
final List suites = (List)myParents.get(description);
if (suites != null && !suites.isEmpty()) {
String currentSuite = (String)suites.get(0);
List descriptors = (List)mySuites.get(currentSuite);
if (descriptors.isEmpty()) {
currentSuite = (String)suites.get(1);
descriptors = (List)mySuites.get(currentSuite);
}
if (!currentSuite.equals(myCurrentSuiteName)) {
finishCurrentSuite();
myCurrentSuiteName = currentSuite;
myPrintStream.println("##teamcity[testSuiteStarted name =\'" + escapeName(getShortName(myCurrentSuiteName)) + "\']");
}
descriptors.remove(description);
}
else if (myCurrentSuiteName != null){
finishCurrentSuite();
myCurrentSuiteName = null;
}
String className = getShortName(classFQN);
if (!myEmptyTests.isEmpty() && isWarning(methodName, classFQN)) {
className = (String)myEmptyTests.remove(0);
}
if (!className.equals(myCurrentClassName)) {
if (myCurrentClassName != null) {
myPrintStream.println("##teamcity[testSuiteFinished name=\'" + escapeName(myCurrentClassName) + "\']");
@@ -99,6 +145,16 @@ public class SMTestSender extends RunListener {
getTestMethodLocation(methodName, classFQN) + "]");
}
private void finishCurrentSuite() {
if (myCurrentClassName != null) {
myPrintStream.println("##teamcity[testSuiteFinished name=\'" + escapeName(myCurrentClassName) + "\']");
myCurrentClassName = null;
}
if (myCurrentSuiteName != null) {
myPrintStream.println("##teamcity[testSuiteFinished name=\'" + escapeName(getShortName(myCurrentSuiteName)) + "\']");
}
}
public void testFinished(Description description) throws Exception {
myPrintStream.println("\n##teamcity[testFinished name=\'" + escapeName(JUnit4ReflectionUtil.getMethodName(description)) + "\']");
}
@@ -194,31 +250,49 @@ public class SMTestSender extends RunListener {
private final List myEmptyTests = new ArrayList();
private void sendTree(Description description, Map groups, Description parent) {
final String className = JUnit4ReflectionUtil.getClassName(description);
private void sendTree(Description description, Description parent, Description suiteParent) {
String className = JUnit4ReflectionUtil.getClassName(description);
if (description.getChildren().isEmpty()) {
final String methodName = JUnit4ReflectionUtil.getMethodName((Description)description);
if (methodName != null) {
myPrintStream.println("##teamcity[suiteTreeNode name=\'" + escapeName(methodName) + "\' " + getTestMethodLocation(methodName, className) + "]");
if (isWarning(methodName, className)) {
myEmptyTests.add(getShortName(JUnit4ReflectionUtil.getClassName(parent)));
className = JUnit4ReflectionUtil.getClassName(parent);
myEmptyTests.add(getShortName(className));
}
myPrintStream.println("##teamcity[suiteTreeNode name=\'" + escapeName(methodName) + "\' " + getTestMethodLocation(methodName, className) + "]");
}
if (suiteParent != null ) {
final String parentFQName = JUnit4ReflectionUtil.getClassName(suiteParent);
if (!myCurrentClassName.equals(parentFQName)) {
List parents = (List)myParents.get(description);
if (parents == null) {
parents = new ArrayList();
myParents.put(description, parents);
}
if (!parents.contains(parentFQName)) {
parents.add(parentFQName);
}
List descriptors = (List)mySuites.get(parentFQName);
if (descriptors == null) {
descriptors = new ArrayList();
mySuites.put(parentFQName, descriptors);
}
descriptors.add(description);
}
}
return;
}
List tests = (List)groups.get(description);
if (isParameter(description)) {
tests = description.getChildren();
}
if (tests == null) {
return;
}
List tests = description.getChildren();
boolean pass = false;
for (Iterator iterator = tests.iterator(); iterator.hasNext(); ) {
final Object next = iterator.next();
final List childTests = ((Description)next).getChildren();
final Description nextDescription = (Description)next;
if (((myCurrentClassName == null || !myCurrentClassName.equals(getShortName(className))) && childTests.isEmpty() && JUnit4ReflectionUtil.getMethodName(nextDescription) != null || isParameter(nextDescription)) && !pass) {
final List childTests = nextDescription.getChildren();
if ((myCurrentClassName == null || !myCurrentClassName.equals(className)) && !pass) {
pass = true;
String locationHint = className;
if (isParameter((Description)description)) {
@@ -231,14 +305,12 @@ public class SMTestSender extends RunListener {
}
}
}
myPrintStream.println("##teamcity[suiteTreeStarted name=\'" + escapeName(getShortName(className)) +
"\' locationHint=\'java:suite://" + escapeName(locationHint) + "\']");
myPrintStream.println("##teamcity[suiteTreeStarted name=\'" + escapeName(getShortName(className)) + "\' locationHint=\'java:suite://" + escapeName(locationHint) + "\']");
}
sendTree(nextDescription, groups, description);
sendTree(nextDescription, description, isParameter(description) ? null : childTests.isEmpty() && parent != null ? parent : description);
}
if (pass) {
myPrintStream.println("##teamcity[suiteTreeEnded name=\'" + escapeName(getShortName(JUnit4ReflectionUtil.getClassName((Description)description))) + "\']");
groups.remove(description);
}
}
@@ -250,34 +322,14 @@ public class SMTestSender extends RunListener {
return "locationHint=\'java:test://" + escapeName(className + "." + methodName) + "\'";
}
private static void groupTests(Object description, Map found) {
if (!isParameter((Description)description)) {
ArrayList childTests = ((Description)description).getChildren();
List children = (List)found.get(description);
if (children == null) {
children = new ArrayList();
found.put(description, children);
} else {
childTests = new ArrayList(childTests);
childTests.removeAll(children);
}
children.addAll(childTests);
for (Iterator iterator = childTests.iterator(); iterator.hasNext(); ) {
groupTests(iterator.next(), found);
}
}
}
private static boolean isParameter(Description description) {
String displayName = description.getDisplayName();
return displayName.startsWith("[") && displayName.endsWith("]");
}
public void sendTree(Description description) {
myCurrentClassName = getShortName(JUnit4ReflectionUtil.getClassName((Description)description));
final HashMap group = new HashMap();
groupTests(description, group);
sendTree(description, group, null);
myCurrentClassName = JUnit4ReflectionUtil.getClassName((Description)description);
sendTree(description, null, null);
}
private static String getShortName(String fqName) {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 970 B