From 2889fb291b55da370324e0de5c788fff84c63f85 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 6 May 2015 17:57:01 +0200 Subject: [PATCH 01/11] junit: stacktrace folding for JUnit 3 --- plugins/junit/src/META-INF/plugin.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml index 43d2dceeb5c4..0ca3bc1d7ed9 100644 --- a/plugins/junit/src/META-INF/plugin.xml +++ b/plugins/junit/src/META-INF/plugin.xml @@ -55,6 +55,9 @@ + + + From ff5640ab59d4c97d597c7bcf9b1e473977794656 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 6 May 2015 19:03:51 +0300 Subject: [PATCH 02/11] Step Into My Code (PY-15500) change icon --- .../jetbrains/python/debug/StepIntoMyCode.png | Bin 283 -> 415 bytes .../python/debug/StepIntoMyCode@2x.png | Bin 397 -> 970 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/python/resources/icons/com/jetbrains/python/debug/StepIntoMyCode.png b/python/resources/icons/com/jetbrains/python/debug/StepIntoMyCode.png index 6872566a1f0edfe549bc974fe332d411b0a5e5a2..a5cd4415d07b4e88e1d35a725cb5ebc04cda9a73 100644 GIT binary patch delta 389 zcmV;00eb$M0-pnrBYy#ANklTeGQuE&IAb8f)>Fb8l!7p!Ic$F zG^r>;3s`OjMWb6ant;+fSlRjltjn5(o8y!yX-QcCF20;0Kf1>L>f0YpK@V%1hJe$z&`XrXz?;AezBo)ZT`qA0^(R>vsN54wotQ{t!` zFY*1gD+M*l5PmL75H86Ottb$>6!qNkZyrVkL&;;}upD9e@70n7M(`{@R$#(;+8~2j z4hU8-;myDrB75s!NsuCfOar7KIbe zSrkotW17=tNU{My&ARrDOWruPto(0XF%!cOpzCA_dI6}}(7k`#8|RL-D2AA3cgmXO z_1wX0z~gCsU<}j@G-Nx(kjhza%nSN`t;(n0v8|r_AEpKwBY7JDQg9!L72t++uKVxM zwCq2~FsHWFFa!Q0V{`)$hIFp;@tC;tKL~qH-u>UDYXd<8;27v^S)k2#K$^X#?FVBd z1F(AmhCu-a@-xWUAe)g5z#E8NU0q~hWCQ+_gQ;f#B^Uq_o}j0|6hJBf0000Zvhp5)Cb2)fR_B&&F&_|q%*v>k3RVy^of~o&u#}NY*xFOIORHaBfAs+FXa*$2DJLA)SW&S+Qy|UG2h%jUdepm;#qd@h zBaaIh+{lrHhUPhiQ;ne4S@9kOWUq5xp~*A2vh@qtD@a5A2h9A8||5_GpVFgXIGH;xb1cDV) zvbbLosTQ^c+)-5++|2Q-H1RcBw3v}61ze_G>08ah8B*Zz%e=uS2?RT)xG4#VG!R@Q zT#f*{bU!ByKg#o~kMl4?aSYM!=&z`inm5cyyly%r5PwYPxKF(=B{m0TbS`S>rds>g zFd(t6MU@S1W`)ZSbNtFy4rVA0%7g0A5|B_oo#f}H5&~iLsQWoV+n$0as^H=}-J-QJ z1n6P9PATSDRM@~qMi_c_Ba+62dl{pyZ%wl= zaQ4nVJAXGBXHEVjy^b`ya8IK%k>!`}XJJO)1W0(U+t{DjSRHdA+V@ zMa8Sp@0b-O0%s#rV1A~GJJ3|12Yt-Emmn_87;vSEiR#VRW;(r zHQmdKeE|x>#9ze3A7kI&xUsZ%IIyn4jJ^x{qJP~>3VK%*<9Bhsb1|*=`P!m4>RYk5 z^0~OfYA5#STM-vMQHkEUY>T!~(*7Z=8jrn`n%g^K{p7D`n@^&XB)S&<9oJmK{&%42 zW`FFhRFB8R(?9LPF};uW&_4opa0bf}7~8g_`sTKHTHHb76irVPdG4mr8L@{m5VtRI z>PKEe)fgAQxE({o)E->HINaeR3D~D~cHh3hXQTWCBp}w@qQxioj7d6Z>ve&0Xz`aL z@WYEYoEm+>YR0!&!<}8`oZV*~^9kk-y)GM{&sP>D0_8TS6e|IINd6c2^aTF1|Bn9# XE_fs#{Z(pm00000NkvXXu0mjf7o^iG delta 371 zcmV-(0gV322aN-eBYy!@Nkl?@|n`E}J z(cJ-Nc|D%i6*GU>*3A2FQ9NmzNme@>-5db2+@^ZY50}pM|J{1G{C8+x_TRF2GEE(U z!U6hxJ;-v;DSQ5VPTlw4eZqE{I|79R40d*)&$odr_nNk!WPe8h<%=m!13=5zfR>W% z2=juzV#|^#|EZD-NOc6ra=W?(|Lq%>{HIzuK&&HRmb> Date: Wed, 6 May 2015 19:23:20 +0300 Subject: [PATCH 03/11] IDEA-125664 Diff view vanishes into background after pop-up message from plugin --- .../src/com/intellij/ui/AbstractExpandableItemsHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index b7b0638185bf..4ea30d0a2a4b 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -259,6 +259,11 @@ public abstract class AbstractExpandableItemsHandler Date: Wed, 6 May 2015 18:48:01 +0200 Subject: [PATCH 04/11] Cleanup (correct generics) --- .../src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java | 6 +++--- .../src/com/intellij/openapi/vfs/newvfs/RefreshSession.java | 4 ++-- .../com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java index b7a3736bbbf8..6948e19193fc 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java @@ -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 files) { + public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull Collection 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 files) { + @NotNull Collection files) { RefreshSession session = createSession(async, recursive, finishRunnable, state); session.addAllFiles(files); session.launch(); diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java index 78f0daaa7cc7..e0f4d599a98d 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java @@ -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 files); + public abstract void addAllFiles(@NotNull Collection files); public void addAllFiles(@NotNull VirtualFile... files) { addAllFiles(Arrays.asList(files)); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java index 220d86b09162..e760233798d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java @@ -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 files) { + public void addAllFiles(@NotNull Collection files) { for (VirtualFile file : files) { if (file == null) { LOG.error("null passed among " + files); From ef5cd4e5bc5ef62bfc830cee629dee7c48cdd317 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 6 May 2015 18:58:57 +0200 Subject: [PATCH 05/11] platform: .zip file cache deprecated (should fix EA-62551, EA-65208) --- .../ide/plugins/PluginManagerCore.java | 5 +- .../intellij/openapi/vfs/impl/ZipHandler.java | 16 +- .../openapi/vfs/newvfs/VfsImplUtil.java | 16 +- .../openapi/util/io/ZipFileCache.java | 247 +----------------- .../src/com/intellij/util/lang/JarLoader.java | 43 ++- 5 files changed, 39 insertions(+), 288 deletions(-) diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index fa3ad03df96b..41d7551234d9 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -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) { diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/ZipHandler.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/ZipHandler.java index fc4844ec2f18..6672674d9e14 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/ZipHandler.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/ZipHandler.java @@ -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 map = new THashMap(); map.put("", createRootEntry()); - ZipFile zip = getZipFile(); + ZipFile zip = new ZipFile(getFileToUse()); try { Enumeration 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 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java index 77825b188d01..059a8611cd6f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java @@ -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 rootsToRefresh; + private Set 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); } } } diff --git a/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java b/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java index 89aa9dddb0f3..4b1873e48297 100644 --- a/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java +++ b/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java @@ -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; -/** - *

Utility class which tries to keep frequently requested .zip files open - * to avoid time loss on closing/reopening ZipFile instances.

- * - *

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.

- * - *

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.

- * - *

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.

- */ +/** @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 ourPathCache = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); - private static final Map ourFileCache = ContainerUtil.newHashMap(); - private static final Map 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 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 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 getFilesToClose(int limit, long timeout) { - List toClose = null; - - synchronized (ourLock) { - Iterator 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 paths) { - debug("resetting %s", paths); + public static void reset(Collection paths) { } - List toClose = ContainerUtil.newSmartList(); - - paths = ContainerUtil.map(paths, new Function() { - @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 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() { } } diff --git a/platform/util/src/com/intellij/util/lang/JarLoader.java b/platform/util/src/com/intellij/util/lang/JarLoader.java index 4a040e53ef88..0c5499f4c2d5 100644 --- a/platform/util/src/com/intellij/util/lang/JarLoader.java +++ b/platform/util/src/com/intellij/util/lang/JarLoader.java @@ -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 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 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) { From 95d5d903761d527c06a7322c85d912220b294efd Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 6 May 2015 20:03:05 +0300 Subject: [PATCH 06/11] RUBY-16676: Enable execute in console action also if Lookup does not have focus --- .../com/intellij/execution/console/ConsoleExecuteAction.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java index f1cf7487bde4..5826e6de5159 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java @@ -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); From 3d6623a87a967f5f74b0b7f87b10f9aa0e309398 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 6 May 2015 19:12:35 +0200 Subject: [PATCH 07/11] IntelliJ LaF: make disabled checkbox look better --- .../ide/ui/laf/intellij/IntelliJCheckBoxUI.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/IntelliJCheckBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/IntelliJCheckBoxUI.java index d13551d1d2e4..4492a8bbb4ff 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/IntelliJCheckBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/IntelliJCheckBoxUI.java @@ -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); } } From 5bf9d7513ee38aa2adfe684b411baaac4982f047 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 6 May 2015 15:07:13 +0200 Subject: [PATCH 08/11] junit sm: test for parameterized single test --- .../JUnitTreeByDescriptionHierarchyTest.java | 37 +++++++++++++------ .../src/com/intellij/junit4/SMTestSender.java | 2 +- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java b/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java index dd6e52cf8f2a..36bc93bb3ba4 100644 --- a/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java +++ b/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java @@ -38,12 +38,7 @@ public class JUnitTreeByDescriptionHierarchyTest { 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); } doTest(root, "##teamcity[suiteTreeStarted name='TestA' locationHint='java:suite://a.TestA']\n" + "##teamcity[suiteTreeStarted name='|[0|]' locationHint='java:suite://a.TestA.|[0|]']\n" + @@ -63,6 +58,19 @@ public class JUnitTreeByDescriptionHierarchyTest { "##teamcity[suiteTreeEnded name='TestB']\n"); } + @Test + public void testSingleParameterizedClass() throws Exception { + final String className = "a.TestA"; + final Description aTestClassDescription = Description.createSuiteDescription(className); + attachParameterizedTests(className, aTestClassDescription); + doTest(aTestClassDescription, "##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"); + } + @Test public void test2SuitesWithTheSameTest() throws Exception { final Description root = Description.createSuiteDescription("root"); @@ -92,11 +100,7 @@ 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)); - } + attachParameterizedTests("ATest", aTestClass); final Description suiteDescription = Description.createSuiteDescription("suite"); root.addChild(suiteDescription); final Description aTestClassWithJUnit3Test = Description.createSuiteDescription("ATest"); @@ -113,6 +117,15 @@ public class JUnitTreeByDescriptionHierarchyTest { "##teamcity[suiteTreeEnded name='ATest']\n"); } + + private static void attachParameterizedTests(String className, Description aTestClass) { + for (String paramName : new String[]{"[0]", "[1]"}) { + final Description param1 = Description.createSuiteDescription(paramName); + aTestClass.addChild(param1); + param1.addChild(Description.createTestDescription(className, "testName" + paramName)); + } + } + private static void doTest(Description description, String expected) { final StringBuffer buf = new StringBuffer(); new SMTestSender(new PrintStream(new OutputStream() { @@ -151,6 +164,8 @@ public class JUnitTreeByDescriptionHierarchyTest { Assert.assertEquals("output: " + buf, "##teamcity[suiteTreeNode name='warning' locationHint='java:test://junit.framework.TestSuite$1.warning']\n" + "##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" + diff --git a/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java b/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java index f82a6077cc96..d311e7707af2 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java @@ -218,7 +218,7 @@ public class SMTestSender extends RunListener { 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) { + if (((myCurrentClassName == null || !myCurrentClassName.equals(getShortName(className))) && (childTests.isEmpty() && JUnit4ReflectionUtil.getMethodName(nextDescription) != null || isParameter(nextDescription))) && !pass) { pass = true; String locationHint = className; if (isParameter((Description)description)) { From 68e1faee11bfa021f807d427960bd40b79983868 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 6 May 2015 15:20:15 +0200 Subject: [PATCH 09/11] sm runner: ability to provide root presentation --- .../sm/runner/GeneralTestEventsProcessor.java | 2 ++ .../GeneralToSMTRunnerEventsConvertor.java | 11 +++++++++++ .../OutputToGeneralTestEventsConverter.java | 14 ++++++++++++++ .../testframework/sm/runner/SMTestProxy.java | 19 +++++++++++++++++++ .../sm/runner/ui/TestsPresentationUtil.java | 9 ++++++++- .../src/com/intellij/junit4/SMTestSender.java | 18 ++++++++++++++++-- 6 files changed, 70 insertions(+), 3 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java index 2562537a58f5..a53a5a9bcd5f 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java @@ -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) { } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java index 830ea477ff07..92743bafdf24 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java @@ -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; diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java index cf6d619cf5fd..02a6ec568fca 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java @@ -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 attributes = msg.getAttributes(); + fireRootPresentationAdded(attributes.get("name"), attributes.get("comment")); + } else { GeneralToSMTRunnerEventsConvertor.logProblem(LOG, "Unexpected service message:" + name, myTestFrameworkName); } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index bdf9d9050542..62abe559587b 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -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()) { diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java index d36250191b09..ed7789e236a9 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/TestsPresentationUtil.java @@ -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, diff --git a/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java b/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java index d311e7707af2..7b46def53a24 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java @@ -58,6 +58,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 { @@ -218,7 +232,7 @@ public class SMTestSender extends RunListener { 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) { + if (((myCurrentClassName == null || !myCurrentClassName.equals(className)) && (childTests.isEmpty() && JUnit4ReflectionUtil.getMethodName(nextDescription) != null || isParameter(nextDescription))) && !pass) { pass = true; String locationHint = className; if (isParameter((Description)description)) { @@ -274,7 +288,7 @@ public class SMTestSender extends RunListener { } public void sendTree(Description description) { - myCurrentClassName = getShortName(JUnit4ReflectionUtil.getClassName((Description)description)); + myCurrentClassName = JUnit4ReflectionUtil.getClassName((Description)description); final HashMap group = new HashMap(); groupTests(description, group); sendTree(description, group, null); From 2b2985c28f82bb54e04a91ce2199916a19e87d0c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 6 May 2015 19:44:16 +0200 Subject: [PATCH 10/11] sm junit: support suites hierarchy --- .../JUnitTreeByDescriptionHierarchyTest.java | 277 +++++++++++++----- .../src/com/intellij/junit4/SMTestSender.java | 114 ++++--- 2 files changed, 285 insertions(+), 106 deletions(-) diff --git a/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java b/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java index 36bc93bb3ba4..a71e2cfcf17c 100644 --- a/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java +++ b/plugins/junit/test/com/intellij/execution/junit/JUnitTreeByDescriptionHierarchyTest.java @@ -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,40 +38,96 @@ public class JUnitTreeByDescriptionHierarchyTest { @Test public void test2Parameterized() throws Exception { final Description root = Description.createSuiteDescription("root"); + final ArrayList tests = new ArrayList(); for (String className : new String[]{"a.TestA", "a.TestB"}) { final Description aTestClass = Description.createSuiteDescription(className); root.addChild(aTestClass); - attachParameterizedTests(className, aTestClass); + 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); - attachParameterizedTests(className, aTestClassDescription); - doTest(aTestClassDescription, "##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"); + final ArrayList tests = new ArrayList(); + 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 @@ -76,17 +135,76 @@ public class JUnitTreeByDescriptionHierarchyTest { final Description root = Description.createSuiteDescription("root"); final String className = "ATest"; final String methodName = "test1"; + final List tests = new ArrayList(); 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 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 @@ -100,29 +218,67 @@ public class JUnitTreeByDescriptionHierarchyTest { final Description root = Description.createSuiteDescription("root"); final Description aTestClass = Description.createSuiteDescription("ATest"); root.addChild(aTestClass); - attachParameterizedTests("ATest", aTestClass); + final ArrayList tests = new ArrayList(); + 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) { + private static void attachParameterizedTests(String className, Description aTestClass, List tests) { for (String paramName : new String[]{"[0]", "[1]"}) { final Description param1 = Description.createSuiteDescription(paramName); aTestClass.addChild(param1); - param1.addChild(Description.createTestDescription(className, "testName" + paramName)); + final Description testDescription = Description.createTestDescription(className, "testName" + paramName); + tests.add(testDescription); + param1.addChild(testDescription); } } @@ -143,33 +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[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", 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"); } } diff --git a/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java b/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java index 7b46def53a24..e5b831eaa3fd 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/SMTestSender.java @@ -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() {} @@ -81,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 { @@ -91,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) + "\']"); @@ -113,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)) + "\']"); } @@ -208,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(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)) { @@ -245,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); } } @@ -264,24 +322,6 @@ 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("]"); @@ -289,9 +329,7 @@ public class SMTestSender extends RunListener { public void sendTree(Description description) { myCurrentClassName = JUnit4ReflectionUtil.getClassName((Description)description); - final HashMap group = new HashMap(); - groupTests(description, group); - sendTree(description, group, null); + sendTree(description, null, null); } private static String getShortName(String fqName) { From dcc2dbc35cb5d6a08b3433d0c34d6bd3b9443f0a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 6 May 2015 20:07:25 +0200 Subject: [PATCH 11/11] sm runner: disable sending tree in fork mode, this way tests would be grouped by the test run in the same VM --- .../junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java index 19ad2bff1af6..fcdb82291eba 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java @@ -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); } }