@NotNull public static char[] adaptiveLoadText(@NotNull Reader reader) throws IOException { char[] chars = new char[4096]; List<char[]> buffers = null; int count = 0; int total = 0; while (true) { int n = reader.read(chars, count, chars.length - count); if (n <= 0) break; count += n; if (total > 1024 * 1024 * 10) throw new FileTooBigException("File too big " + reader); total += n; if (count == chars.length) { if (buffers == null) { buffers = new ArrayList<char[]>(); } buffers.add(chars); int newLength = Math.min(1024 * 1024, chars.length * 2); chars = new char[newLength]; count = 0; } } char[] result = new char[total]; if (buffers != null) { for (char[] buffer : buffers) { System.arraycopy(buffer, 0, result, result.length - total, buffer.length); total -= buffer.length; } } System.arraycopy(chars, 0, result, result.length - total, total); return result; }
@NotNull public static byte[] adaptiveLoadBytes(@NotNull InputStream stream) throws IOException { byte[] bytes = new byte[4096]; List<byte[]> buffers = null; int count = 0; int total = 0; while (true) { int n = stream.read(bytes, count, bytes.length - count); if (n <= 0) break; count += n; if (total > 1024 * 1024 * 10) throw new FileTooBigException("File too big " + stream); total += n; if (count == bytes.length) { if (buffers == null) { buffers = new ArrayList<byte[]>(); } buffers.add(bytes); int newLength = Math.min(1024 * 1024, bytes.length * 2); bytes = new byte[newLength]; count = 0; } } byte[] result = new byte[total]; if (buffers != null) { for (byte[] buffer : buffers) { System.arraycopy(buffer, 0, result, result.length - total, buffer.length); total -= buffer.length; } } System.arraycopy(bytes, 0, result, result.length - total, total); return result; }
private void insertChildAt(@NotNull VirtualFileSystemEntry file, int negativeIndex) { @NotNull VirtualFileSystemEntry[] array = myChildren; VirtualFileSystemEntry[] appended = new VirtualFileSystemEntry[array.length + 1]; int i = -negativeIndex - 1; System.arraycopy(array, 0, appended, 0, i); appended[i] = file; System.arraycopy(array, i, appended, i + 1, array.length - i); myChildren = appended; }
public static void importConfigsTo(@NotNull String newConfigPath) { ConfigImportSettings settings = getConfigImportSettings(); File newConfigDir = new File(newConfigPath); File oldConfigDir = findOldConfigDir(newConfigDir, settings.getCustomPathsSelector()); do { ImportOldConfigsPanel dialog = new ImportOldConfigsPanel(oldConfigDir, settings); dialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL); AppUIUtil.updateWindowIcon(dialog); dialog.setVisible(true); if (dialog.isImportEnabled()) { File installationHome = dialog.getSelectedFile(); oldConfigDir = getOldConfigDir(installationHome, settings); if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) { continue; } assert oldConfigDir != null; doImport(newConfigDir, oldConfigDir, settings, installationHome); settings.importFinished(newConfigPath); System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString()); } break; } while (true); }
private static File getTempFile(@NotNull String originalFileName, @NotNull File parent) { int randomSuffix = (int) (System.currentTimeMillis() % 1000); for (int i = randomSuffix; ; i++) { @NonNls String name = "___" + originalFileName + i + ASYNC_DELETE_EXTENSION; File tempFile = new File(parent, name); if (!tempFile.exists()) return tempFile; } }
static { // Radar #5755208: Command line Java applications need a way to launch without a Dock icon. System.setProperty("apple.awt.UIElement", "true"); try { CodeInsightSettings defaultSettings = new CodeInsightSettings(); Element oldS = new Element("temp"); defaultSettings.writeExternal(oldS); DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS, "\n"); } catch (Exception e) { throw new RuntimeException(e); } }
// null means we were unable to get roots, so do not check access @Nullable @TestOnly private static Set<String> allowedRoots() { if (insideGettingRoots) return null; Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length == 0) return null; final Set<String> allowed = new THashSet<String>(); allowed.add(FileUtil.toSystemIndependentName(PathManager.getHomePath())); try { URL outUrl = Application.class.getResource("/"); String output = new File(outUrl.toURI()).getParentFile().getParentFile().getPath(); allowed.add(FileUtil.toSystemIndependentName(output)); } catch (URISyntaxException ignored) { } allowed.add(FileUtil.toSystemIndependentName(SystemProperties.getJavaHome())); allowed.add( FileUtil.toSystemIndependentName(new File(FileUtil.getTempDirectory()).getParent())); allowed.add(FileUtil.toSystemIndependentName(System.getProperty("java.io.tmpdir"))); allowed.add(FileUtil.toSystemIndependentName(SystemProperties.getUserHome())); for (Project project : openProjects) { if (!project.isInitialized()) { return null; // all is allowed } for (VirtualFile root : ProjectRootManager.getInstance(project).getContentRoots()) { allowed.add(root.getPath()); } for (VirtualFile root : getAllRoots(project)) { allowed.add(StringUtil.trimEnd(root.getPath(), JarFileSystem.JAR_SEPARATOR)); } String location = project.getBasePath(); assert location != null : project; allowed.add(FileUtil.toSystemIndependentName(location)); } allowed.addAll(ourAdditionalRoots); return allowed; }
/** @author max */ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl"); public static boolean CHECK = ApplicationManager.getApplication().isUnitTestMode(); static final VirtualDirectoryImpl NULL_VIRTUAL_FILE = new VirtualDirectoryImpl("*?;%NULL", null, LocalFileSystem.getInstance(), -42, 0) { public String toString() { return "NULL"; } }; private final NewVirtualFileSystem myFS; /** * The array is logically divided into the two parts: - left subarray for storing real child files * - right subarray for storing "adopted children" files. "Adopted children" are fake files which * are used for storing names which were accessed via findFileByName() or similar calls. We have * to store these unsuccessful find attempts to be able to correctly refresh in the future. See * usages of {@link #getSuspiciousNames()} in the {@link * com.intellij.openapi.vfs.newvfs.persistent.RefreshWorker} * * <p>Guarded by this, files in each subarray are sorted according to the compareNameTo() * comparator TODO: revise the whole adopted scheme */ private VirtualFileSystemEntry[] myChildren = EMPTY_ARRAY; public VirtualDirectoryImpl( @NonNls @NotNull final String name, @Nullable final VirtualDirectoryImpl parent, @NotNull final NewVirtualFileSystem fs, final int id, @PersistentFS.Attributes final int attributes) { super(name, parent, id, attributes); myFS = fs; } @Override @NotNull public NewVirtualFileSystem getFileSystem() { return myFS; } @Nullable private VirtualFileSystemEntry findChild( @NotNull String name, final boolean doRefresh, boolean ensureCanonicalName, @NotNull NewVirtualFileSystem delegate) { boolean ignoreCase = !delegate.isCaseSensitive(); Comparator comparator = getComparator(name, ignoreCase); VirtualFileSystemEntry result = doFindChild(name, ensureCanonicalName, delegate, comparator); if (result == NULL_VIRTUAL_FILE) { result = doRefresh ? createAndFindChildWithEventFire(name, delegate) : null; } else if (result != null) { if (doRefresh && delegate.isDirectory(result) != result.isDirectory()) { RefreshQueue.getInstance().refresh(false, false, null, result); result = findChild(name, false, ensureCanonicalName, delegate); } } if (result == null) { addToAdoptedChildren(name, !delegate.isCaseSensitive(), comparator); } return result; } private synchronized void addToAdoptedChildren( @NotNull final String name, final boolean ignoreCase, @NotNull Comparator comparator) { long r = findIndexInBoth(myChildren, comparator); int indexInReal = (int) (r >> 32); int indexInAdopted = (int) r; if (indexInAdopted >= 0) return; // already added if (!allChildrenLoaded()) { insertChildAt(new AdoptedChild(name), indexInAdopted); } if (indexInReal >= 0) { // there suddenly can be that we ask to add name to adopted whereas it already contains in the // real part // in this case we should remove it from there removeFromArray(indexInReal); } assertConsistency(myChildren, ignoreCase, name); } private static class AdoptedChild extends VirtualFileImpl { private AdoptedChild(String name) { super(name, NULL_VIRTUAL_FILE, -42, -1); } } @Nullable // null if there can't be a child with this name, NULL_VIRTUAL_FILE private synchronized VirtualFileSystemEntry doFindChildInArray(@NotNull Comparator comparator) { VirtualFileSystemEntry[] array = myChildren; long r = findIndexInBoth(array, comparator); int indexInReal = (int) (r >> 32); int indexInAdopted = (int) r; if (indexInAdopted >= 0) return NULL_VIRTUAL_FILE; if (indexInReal >= 0) { return array[indexInReal]; } return null; } @Nullable // null if there can't be a child with this name, NULL_VIRTUAL_FILE if cached as absent, // the file if found private VirtualFileSystemEntry doFindChild( @NotNull String name, boolean ensureCanonicalName, @NotNull NewVirtualFileSystem delegate, @NotNull Comparator comparator) { if (name.isEmpty()) { return null; } VirtualFileSystemEntry found = doFindChildInArray(comparator); if (found != null) return found; if (allChildrenLoaded()) { return NULL_VIRTUAL_FILE; } if (ensureCanonicalName) { VirtualFile fake = new FakeVirtualFile(this, name); name = delegate.getCanonicallyCasedName(fake); if (name.isEmpty()) return null; } synchronized (this) { // maybe another doFindChild() sneaked in the middle VirtualFileSystemEntry[] array = myChildren; long r = findIndexInBoth(array, comparator); int indexInReal = (int) (r >> 32); int indexInAdopted = (int) r; if (indexInAdopted >= 0) return NULL_VIRTUAL_FILE; // double check if (indexInReal >= 0) { return array[indexInReal]; } // do not extract getId outside the synchronized block since it will cause a concurrency // problem. int id = ourPersistence.getId(this, name, delegate); if (id <= 0) { return null; } String shorty = new String(name); VirtualFileSystemEntry child = createChild( shorty, id, delegate); // So we don't hold whole char[] buffer of a lengthy path VirtualFileSystemEntry[] after = myChildren; if (after != array) { // in tests when we call assertAccessInTests it can load a huge number of files which lead // to children modification // so fall back to slow path addChild(child); } else { insertChildAt(child, indexInReal); assertConsistency(myChildren, !delegate.isCaseSensitive(), name); } return child; } } @NotNull private static Comparator getComparator(@NotNull final String name, final boolean ignoreCase) { return new Comparator() { @Override public int compareMyKeyTo(@NotNull VirtualFileSystemEntry file) { return -file.compareNameTo(name, ignoreCase); } }; } private synchronized VirtualFileSystemEntry[] getArraySafely() { return myChildren; } @NotNull public VirtualFileSystemEntry createChild( @NotNull String name, int id, @NotNull NewVirtualFileSystem delegate) { VirtualFileSystemEntry child; final int attributes = ourPersistence.getFileAttributes(id); if (PersistentFS.isDirectory(attributes)) { child = new VirtualDirectoryImpl(name, this, delegate, id, attributes); } else { child = new VirtualFileImpl(name, this, id, attributes); //noinspection TestOnlyProblems assertAccessInTests(child, delegate); } if (delegate.markNewFilesAsDirty()) { child.markDirty(); } return child; } private static final boolean IS_UNDER_TEAMCITY = System.getProperty("bootstrap.testcases") != null; private static final boolean SHOULD_PERFORM_ACCESS_CHECK = System.getenv("NO_FS_ROOTS_ACCESS_CHECK") == null; private static final Collection<String> ourAdditionalRoots = new THashSet<String>(); @TestOnly public static void allowRootAccess(@NotNull String... roots) { for (String root : roots) { ourAdditionalRoots.add(FileUtil.toSystemIndependentName(root)); } } @TestOnly public static void disallowRootAccess(@NotNull String... roots) { for (String root : roots) { ourAdditionalRoots.remove(FileUtil.toSystemIndependentName(root)); } } @TestOnly private static void assertAccessInTests( @NotNull VirtualFileSystemEntry child, @NotNull NewVirtualFileSystem delegate) { final Application application = ApplicationManager.getApplication(); if (IS_UNDER_TEAMCITY && SHOULD_PERFORM_ACCESS_CHECK && application.isUnitTestMode() && application instanceof ApplicationImpl && ((ApplicationImpl) application).isComponentsCreated()) { if (delegate != LocalFileSystem.getInstance() && delegate != JarFileSystem.getInstance()) { return; } // root' children are loaded always if (child.getParent() == null || child.getParent().getParent() == null) return; Set<String> allowed = allowedRoots(); boolean isUnder = allowed == null; if (!isUnder) { String childPath = child.getPath(); if (delegate == JarFileSystem.getInstance()) { VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(child); assert local != null : child; childPath = local.getPath(); } for (String root : allowed) { if (FileUtil.startsWith(childPath, root)) { isUnder = true; break; } if (root.startsWith(JarFileSystem.PROTOCOL_PREFIX)) { String rootLocalPath = FileUtil.toSystemIndependentName(PathUtil.toPresentableUrl(root)); isUnder = FileUtil.startsWith(childPath, rootLocalPath); if (isUnder) break; } } } assert isUnder || allowed.isEmpty() : "File accessed outside allowed roots: " + child + ";\nAllowed roots: " + new ArrayList<String>(allowed); } } // null means we were unable to get roots, so do not check access @Nullable @TestOnly private static Set<String> allowedRoots() { if (insideGettingRoots) return null; Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length == 0) return null; final Set<String> allowed = new THashSet<String>(); allowed.add(FileUtil.toSystemIndependentName(PathManager.getHomePath())); try { URL outUrl = Application.class.getResource("/"); String output = new File(outUrl.toURI()).getParentFile().getParentFile().getPath(); allowed.add(FileUtil.toSystemIndependentName(output)); } catch (URISyntaxException ignored) { } allowed.add(FileUtil.toSystemIndependentName(SystemProperties.getJavaHome())); allowed.add( FileUtil.toSystemIndependentName(new File(FileUtil.getTempDirectory()).getParent())); allowed.add(FileUtil.toSystemIndependentName(System.getProperty("java.io.tmpdir"))); allowed.add(FileUtil.toSystemIndependentName(SystemProperties.getUserHome())); for (Project project : openProjects) { if (!project.isInitialized()) { return null; // all is allowed } for (VirtualFile root : ProjectRootManager.getInstance(project).getContentRoots()) { allowed.add(root.getPath()); } for (VirtualFile root : getAllRoots(project)) { allowed.add(StringUtil.trimEnd(root.getPath(), JarFileSystem.JAR_SEPARATOR)); } String location = project.getBasePath(); assert location != null : project; allowed.add(FileUtil.toSystemIndependentName(location)); } allowed.addAll(ourAdditionalRoots); return allowed; } private static boolean insideGettingRoots; @TestOnly private static VirtualFile[] getAllRoots(@NotNull Project project) { insideGettingRoots = true; final Set<VirtualFile> roots = new THashSet<VirtualFile>(); final OrderEnumerator enumerator = ProjectRootManager.getInstance(project).orderEntries(); ContainerUtil.addAll(roots, enumerator.getClassesRoots()); ContainerUtil.addAll(roots, enumerator.getSourceRoots()); insideGettingRoots = false; return VfsUtilCore.toVirtualFileArray(roots); } @Nullable private VirtualFileSystemEntry createAndFindChildWithEventFire( @NotNull String name, @NotNull NewVirtualFileSystem delegate) { final VirtualFile fake = new FakeVirtualFile(this, name); final FileAttributes attributes = delegate.getAttributes(fake); if (attributes == null) return null; final String realName = delegate.getCanonicallyCasedName(fake); final VFileCreateEvent event = new VFileCreateEvent(null, this, realName, attributes.isDirectory(), true); RefreshQueue.getInstance().processSingleEvent(event); return findChild(realName); } @Override @Nullable public NewVirtualFile refreshAndFindChild(@NotNull String name) { return findChild(name, true, true, getFileSystem()); } private static int findIndexInOneHalf( final VirtualFileSystemEntry[] array, int start, int end, final boolean isAdopted, @NotNull final Comparator comparator) { return binSearch( array, start, end, new Comparator() { @Override public int compareMyKeyTo(@NotNull VirtualFileSystemEntry file) { if (isAdopted && !isAdoptedChild(file)) return 1; if (!isAdopted && isAdoptedChild(file)) return -1; return comparator.compareMyKeyTo(file); } }); } // returns two int indices packed into one long. left index is for the real file array half, right // is for the adopted children name array private static long findIndexInBoth( @NotNull VirtualFileSystemEntry[] array, @NotNull Comparator comparator) { int high = array.length - 1; if (high == -1) { return pack(-1, -1); } int low = 0; boolean startInAdopted = isAdoptedChild(array[low]); boolean endInAdopted = isAdoptedChild(array[high]); if (startInAdopted == endInAdopted) { int index = findIndexInOneHalf(array, low, high + 1, startInAdopted, comparator); int otherIndex = startInAdopted ? -1 : -array.length - 1; return startInAdopted ? pack(otherIndex, index) : pack(index, otherIndex); } boolean adopted = false; int cmp = -1; int mid = -1; int foundIndex = -1; while (low <= high) { mid = low + high >>> 1; VirtualFileSystemEntry file = array[mid]; cmp = comparator.compareMyKeyTo(file); adopted = isAdoptedChild(file); if (cmp == 0) { foundIndex = mid; break; } if ((adopted || cmp <= 0) && (!adopted || cmp >= 0)) { int indexInAdopted = findIndexInOneHalf(array, mid + 1, high + 1, true, comparator); int indexInReal = findIndexInOneHalf(array, low, mid, false, comparator); return pack(indexInReal, indexInAdopted); } if (cmp > 0) { low = mid + 1; } else { high = mid - 1; } } // key not found. if (cmp != 0) foundIndex = -low - 1; int newStart = adopted ? low : mid + 1; int newEnd = adopted ? mid + 1 : high + 1; int theOtherHalfIndex = newStart < newEnd ? findIndexInOneHalf(array, newStart, newEnd, !adopted, comparator) : -newStart - 1; return adopted ? pack(theOtherHalfIndex, foundIndex) : pack(foundIndex, theOtherHalfIndex); } private static long pack(int indexInReal, int indexInAdopted) { return (long) indexInReal << 32 | (indexInAdopted & 0xffffffffL); } @Override @Nullable public synchronized NewVirtualFile findChildIfCached(@NotNull String name) { final boolean ignoreCase = !getFileSystem().isCaseSensitive(); Comparator comparator = getComparator(name, ignoreCase); VirtualFileSystemEntry found = doFindChildInArray(comparator); return found == NULL_VIRTUAL_FILE ? null : found; } @Override @NotNull public Iterable<VirtualFile> iterInDbChildren() { if (!ourPersistence.wereChildrenAccessed(this)) { return Collections.emptyList(); } if (!ourPersistence.areChildrenLoaded(this)) { final String[] names = ourPersistence.listPersisted(this); final NewVirtualFileSystem delegate = PersistentFS.replaceWithNativeFS(getFileSystem()); for (String name : names) { findChild(name, false, false, delegate); } } return getCachedChildren(); } @Override @NotNull public synchronized VirtualFile[] getChildren() { VirtualFileSystemEntry[] children = myChildren; NewVirtualFileSystem delegate = getFileSystem(); final boolean ignoreCase = !delegate.isCaseSensitive(); if (allChildrenLoaded()) { assertConsistency(children, ignoreCase); return children; } final FSRecords.NameId[] childrenIds = ourPersistence.listAll(this); VirtualFileSystemEntry[] result; if (childrenIds.length == 0) { result = EMPTY_ARRAY; } else { Arrays.sort( childrenIds, new java.util.Comparator<FSRecords.NameId>() { @Override public int compare(FSRecords.NameId o1, FSRecords.NameId o2) { String name1 = o1.name; String name2 = o2.name; int cmp = compareNames(name1, name2, ignoreCase); if (cmp == 0 && name1 != name2) { LOG.error( ourPersistence + " returned duplicate file names(" + name1 + "," + name2 + ")" + " ignoreCase: " + ignoreCase + " SystemInfo.isFileSystemCaseSensitive: " + SystemInfo.isFileSystemCaseSensitive + " SystemInfo.OS: " + SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION + " in the dir: " + VirtualDirectoryImpl.this + ";" + " children: " + Arrays.toString(childrenIds)); } return cmp; } }); result = new VirtualFileSystemEntry[childrenIds.length]; int delegateI = 0; int i = 0; int cachedEnd = getAdoptedChildrenStart(); // merge (sorted) children[0..cachedEnd) and childrenIds into the result array. // file that is already in children array must be copied into the result as is // for the file name that is new in childrenIds the file must be created and copied into // result while (delegateI < childrenIds.length) { FSRecords.NameId nameId = childrenIds[delegateI]; while (i < cachedEnd && children[i].compareNameTo(nameId.name, ignoreCase) < 0) i++; // skip files that are not in childrenIds VirtualFileSystemEntry resultFile; if (i < cachedEnd && children[i].compareNameTo(nameId.name, ignoreCase) == 0) { resultFile = children[i++]; } else { resultFile = createChild(nameId.name, nameId.id, delegate); } result[delegateI++] = resultFile; } assertConsistency(result, ignoreCase, children, cachedEnd, childrenIds); } if (getId() > 0) { myChildren = result; setChildrenLoaded(); } return result; } private void assertConsistency( @NotNull VirtualFileSystemEntry[] array, boolean ignoreCase, @NotNull Object... details) { if (!CHECK) return; boolean allChildrenLoaded = allChildrenLoaded(); for (int i = 0; i < array.length; i++) { VirtualFileSystemEntry file = array[i]; boolean isAdopted = isAdoptedChild(file); assert !isAdopted || !allChildrenLoaded; if (isAdopted && i != array.length - 1) { assert isAdoptedChild(array[i + 1]); } if (i != 0) { VirtualFileSystemEntry prev = array[i - 1]; String prevName = prev.getName(); int cmp = file.compareNameTo(prevName, ignoreCase); if (cmp == 0) { Function<VirtualFileSystemEntry, String> verboseToString = new Function<VirtualFileSystemEntry, String>() { @Override public String fun(VirtualFileSystemEntry entry) { return entry + " (name: '" + entry.getName() + "', " + entry.getClass() + ", parent:" + entry.getParent() + "; id:" + entry.getId() + "; FS:" + entry.getFileSystem() + "; delegate.attrs:" + entry.getFileSystem().getAttributes(entry) + "; caseSensitive:" + entry.getFileSystem().isCaseSensitive() + "; canonical:" + entry.getFileSystem().getCanonicallyCasedName(entry) + ") "; } }; String children = StringUtil.join(array, verboseToString, ","); throw new AssertionError( verboseToString.fun(prev) + " equals to " + verboseToString.fun(file) + "; children: " + children + "\nDetails: " + ContainerUtil.map( details, new Function<Object, Object>() { @Override public Object fun(Object o) { return o instanceof Object[] ? Arrays.toString((Object[]) o) : o; } })); } if (isAdopted == isAdoptedChild(prev)) { assert cmp > 0 : "Not sorted. " + Arrays.toString(details); } } } } @Override @Nullable public VirtualFileSystemEntry findChild(@NotNull final String name) { return findChild(name, false, true, getFileSystem()); } public VirtualFileSystemEntry findChildById(int id, boolean cachedOnly) { VirtualFile[] array = getArraySafely(); VirtualFileSystemEntry result = null; for (VirtualFile file : array) { VirtualFileSystemEntry withId = (VirtualFileSystemEntry) file; if (withId.getId() == id) { result = withId; break; } } if (result != null) return result; if (cachedOnly) return null; String name = ourPersistence.getName(id); return findChild(name, false, false, getFileSystem()); } @NotNull @Override public byte[] contentsToByteArray() throws IOException { throw new IOException("Cannot get content of directory: " + this); } public synchronized void addChild(@NotNull VirtualFileSystemEntry child) { VirtualFileSystemEntry[] array = myChildren; final String childName = child.getName(); final boolean ignoreCase = !getFileSystem().isCaseSensitive(); long r = findIndexInBoth(array, getComparator(childName, ignoreCase)); int indexInReal = (int) (r >> 32); int indexInAdopted = (int) r; if (indexInAdopted >= 0) { // remove Adopted first removeFromArray(indexInAdopted); } if (indexInReal < 0) { insertChildAt(child, indexInReal); } // else already stored assertConsistency(myChildren, ignoreCase, child); } private void insertChildAt(@NotNull VirtualFileSystemEntry file, int negativeIndex) { @NotNull VirtualFileSystemEntry[] array = myChildren; VirtualFileSystemEntry[] appended = new VirtualFileSystemEntry[array.length + 1]; int i = -negativeIndex - 1; System.arraycopy(array, 0, appended, 0, i); appended[i] = file; System.arraycopy(array, i, appended, i + 1, array.length - i); myChildren = appended; } public synchronized void removeChild(@NotNull VirtualFile file) { boolean ignoreCase = !getFileSystem().isCaseSensitive(); String name = file.getName(); addToAdoptedChildren(name, ignoreCase, getComparator(name, ignoreCase)); assertConsistency(myChildren, ignoreCase, file); } private void removeFromArray(int index) { myChildren = ArrayUtil.remove( myChildren, index, new ArrayFactory<VirtualFileSystemEntry>() { @NotNull @Override public VirtualFileSystemEntry[] create(int count) { return new VirtualFileSystemEntry[count]; } }); } public boolean allChildrenLoaded() { return getFlagInt(CHILDREN_CACHED); } private void setChildrenLoaded() { setFlagInt(CHILDREN_CACHED, true); } @NotNull public synchronized List<String> getSuspiciousNames() { List<VirtualFile> suspicious = new SubList<VirtualFile>(myChildren, getAdoptedChildrenStart(), myChildren.length); return ContainerUtil.map2List( suspicious, new Function<VirtualFile, String>() { @Override public String fun(VirtualFile file) { return file.getName(); } }); } private int getAdoptedChildrenStart() { int index = binSearch( myChildren, 0, myChildren.length, new Comparator() { @Override public int compareMyKeyTo(@NotNull VirtualFileSystemEntry v) { return isAdoptedChild(v) ? -1 : 1; } }); return -index - 1; } private static boolean isAdoptedChild(@NotNull VirtualFileSystemEntry v) { return v.getParent() == NULL_VIRTUAL_FILE; } private interface Comparator { int compareMyKeyTo(@NotNull VirtualFileSystemEntry file); } private static int binSearch( @NotNull VirtualFileSystemEntry[] array, int start, int end, @NotNull Comparator comparator) { int low = start; int high = end - 1; assert low >= 0 && low <= array.length; while (low <= high) { int mid = low + high >>> 1; int cmp = comparator.compareMyKeyTo(array[mid]); if (cmp > 0) { low = mid + 1; } else if (cmp < 0) { high = mid - 1; } else { return mid; // key found } } return -(low + 1); // key not found. } @Override public boolean isDirectory() { return true; } @Override @NotNull public synchronized List<VirtualFile> getCachedChildren() { return new SubList<VirtualFile>(myChildren, 0, getAdoptedChildrenStart()); } @Override public InputStream getInputStream() throws IOException { throw new IOException("getInputStream() must not be called against a directory: " + getUrl()); } @Override @NotNull public OutputStream getOutputStream( final Object requestor, final long newModificationStamp, final long newTimeStamp) throws IOException { throw new IOException("getOutputStream() must not be called against a directory: " + getUrl()); } @Override public void markDirtyRecursively() { markDirty(); markDirtyRecursivelyInternal(); } // optimisation: do not travel up unnecessary private void markDirtyRecursivelyInternal() { for (VirtualFileSystemEntry child : getArraySafely()) { if (isAdoptedChild(child)) break; child.markDirtyInternal(); if (child instanceof VirtualDirectoryImpl) { ((VirtualDirectoryImpl) child).markDirtyRecursivelyInternal(); } } } }
/** @author peter */ @SuppressWarnings("UseOfSystemOutOrSystemErr") public abstract class UsefulTestCase extends TestCase { public static final boolean IS_UNDER_TEAMCITY = System.getenv("TEAMCITY_VERSION") != null; public static final String IDEA_MARKER_CLASS = "com.intellij.openapi.components.impl.stores.IdeaProjectStoreImpl"; public static final String TEMP_DIR_MARKER = "unitTest_"; protected static boolean OVERWRITE_TESTDATA = false; private static final String DEFAULT_SETTINGS_EXTERNALIZED; private static final Random RNG = new SecureRandom(); private static final String ORIGINAL_TEMP_DIR = FileUtil.getTempDirectory(); protected final Disposable myTestRootDisposable = new Disposable() { @Override public void dispose() {} @Override public String toString() { String testName = getTestName(false); return UsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName); } }; protected static String ourPathToKeep = null; private CodeStyleSettings myOldCodeStyleSettings; private String myTempDir; protected static final Key<String> CREATION_PLACE = Key.create("CREATION_PLACE"); static { // Radar #5755208: Command line Java applications need a way to launch without a Dock icon. System.setProperty("apple.awt.UIElement", "true"); try { CodeInsightSettings defaultSettings = new CodeInsightSettings(); Element oldS = new Element("temp"); defaultSettings.writeExternal(oldS); DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS, "\n"); } catch (Exception e) { throw new RuntimeException(e); } } protected boolean shouldContainTempFiles() { return true; } @Override protected void setUp() throws Exception { super.setUp(); if (shouldContainTempFiles()) { String testName = getTestName(true); if (StringUtil.isEmptyOrSpaces(testName)) testName = ""; testName = new File(testName).getName(); // in case the test name contains file separators myTempDir = FileUtil.toSystemDependentName( ORIGINAL_TEMP_DIR + "/" + TEMP_DIR_MARKER + testName + "_" + RNG.nextInt(1000)); FileUtil.resetCanonicalTempPathCache(myTempDir); } //noinspection AssignmentToStaticFieldFromInstanceMethod DocumentImpl.CHECK_DOCUMENT_CONSISTENCY = !isPerformanceTest(); } @Override protected void tearDown() throws Exception { try { Disposer.dispose(myTestRootDisposable); cleanupSwingDataStructures(); cleanupDeleteOnExitHookList(); } finally { if (shouldContainTempFiles()) { FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR); if (ourPathToKeep != null && FileUtil.isAncestor(myTempDir, ourPathToKeep, false)) { File[] files = new File(myTempDir).listFiles(); if (files != null) { for (File file : files) { if (!FileUtil.pathsEqual(file.getPath(), ourPathToKeep)) { FileUtil.delete(file); } } } } else { FileUtil.delete(new File(myTempDir)); } } } UIUtil.removeLeakingAppleListeners(); super.tearDown(); } private static final Set<String> DELETE_ON_EXIT_HOOK_DOT_FILES; private static final Class DELETE_ON_EXIT_HOOK_CLASS; static { Class<?> aClass = null; Set<String> files = null; try { aClass = Class.forName("java.io.DeleteOnExitHook"); files = ReflectionUtil.getField(aClass, null, Set.class, "files"); } catch (Exception ignored) { } DELETE_ON_EXIT_HOOK_CLASS = aClass; DELETE_ON_EXIT_HOOK_DOT_FILES = files; } public static void cleanupDeleteOnExitHookList() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { // try to reduce file set retained by java.io.DeleteOnExitHook List<String> list; synchronized (DELETE_ON_EXIT_HOOK_CLASS) { if (DELETE_ON_EXIT_HOOK_DOT_FILES.isEmpty()) return; list = new ArrayList<String>(DELETE_ON_EXIT_HOOK_DOT_FILES); } for (int i = list.size() - 1; i >= 0; i--) { String path = list.get(i); if (FileSystemUtil.getAttributes(path) == null || new File(path).delete()) { synchronized (DELETE_ON_EXIT_HOOK_CLASS) { DELETE_ON_EXIT_HOOK_DOT_FILES.remove(path); } } } } private static void cleanupSwingDataStructures() throws Exception { Class<?> aClass = Class.forName("javax.swing.KeyboardManager"); Method get = aClass.getMethod("getCurrentManager"); get.setAccessible(true); Object manager = get.invoke(null); { Field mapF = aClass.getDeclaredField("componentKeyStrokeMap"); mapF.setAccessible(true); Object map = mapF.get(manager); ((Map) map).clear(); } { Field mapF = aClass.getDeclaredField("containerMap"); mapF.setAccessible(true); Object map = mapF.get(manager); ((Map) map).clear(); } } protected CompositeException checkForSettingsDamage() throws Exception { Application app = ApplicationManager.getApplication(); if (isPerformanceTest() || app == null || app instanceof MockApplication) { return new CompositeException(); } CodeStyleSettings oldCodeStyleSettings = myOldCodeStyleSettings; myOldCodeStyleSettings = null; return doCheckForSettingsDamage(oldCodeStyleSettings, getCurrentCodeStyleSettings()); } public static CompositeException doCheckForSettingsDamage( @NotNull CodeStyleSettings oldCodeStyleSettings, @NotNull CodeStyleSettings currentCodeStyleSettings) throws Exception { CompositeException result = new CompositeException(); final CodeInsightSettings settings = CodeInsightSettings.getInstance(); try { Element newS = new Element("temp"); settings.writeExternal(newS); Assert.assertEquals( "Code insight settings damaged", DEFAULT_SETTINGS_EXTERNALIZED, JDOMUtil.writeElement(newS, "\n")); } catch (AssertionError error) { CodeInsightSettings clean = new CodeInsightSettings(); Element temp = new Element("temp"); clean.writeExternal(temp); settings.loadState(temp); result.add(error); } currentCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA); try { checkSettingsEqual( oldCodeStyleSettings, currentCodeStyleSettings, "Code style settings damaged"); } catch (AssertionError e) { result.add(e); } finally { currentCodeStyleSettings.clearCodeStyleSettings(); } try { InplaceRefactoring.checkCleared(); } catch (AssertionError e) { result.add(e); } try { StartMarkAction.checkCleared(); } catch (AssertionError e) { result.add(e); } return result; } protected void storeSettings() { if (!isPerformanceTest() && ApplicationManager.getApplication() != null) { myOldCodeStyleSettings = getCurrentCodeStyleSettings().clone(); myOldCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA); } } protected CodeStyleSettings getCurrentCodeStyleSettings() { if (CodeStyleSchemes.getInstance().getCurrentScheme() == null) return new CodeStyleSettings(); return CodeStyleSettingsManager.getInstance().getCurrentSettings(); } public Disposable getTestRootDisposable() { return myTestRootDisposable; } @Override protected void runTest() throws Throwable { final Throwable[] throwables = new Throwable[1]; Runnable runnable = new Runnable() { @Override public void run() { try { UsefulTestCase.super.runTest(); } catch (InvocationTargetException e) { e.fillInStackTrace(); throwables[0] = e.getTargetException(); } catch (IllegalAccessException e) { e.fillInStackTrace(); throwables[0] = e; } catch (Throwable e) { throwables[0] = e; } } }; invokeTestRunnable(runnable); if (throwables[0] != null) { throw throwables[0]; } } protected boolean shouldRunTest() { return PlatformTestUtil.canRunTest(getClass()); } public static void edt(Runnable r) { UIUtil.invokeAndWaitIfNeeded(r); } protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception { UIUtil.invokeAndWaitIfNeeded(runnable); // runnable.run(); } protected void defaultRunBare() throws Throwable { super.runBare(); } @Override public void runBare() throws Throwable { if (!shouldRunTest()) return; if (runInDispatchThread()) { final Throwable[] exception = {null}; UIUtil.invokeAndWaitIfNeeded( new Runnable() { @Override public void run() { try { defaultRunBare(); } catch (Throwable tearingDown) { if (exception[0] == null) exception[0] = tearingDown; } } }); if (exception[0] != null) throw exception[0]; } else { defaultRunBare(); } } protected boolean runInDispatchThread() { return true; } @NonNls public static String toString(Iterable<?> collection) { if (!collection.iterator().hasNext()) { return "<empty>"; } final StringBuilder builder = new StringBuilder(); for (final Object o : collection) { if (o instanceof THashSet) { builder.append(new TreeSet<Object>((THashSet) o)); } else { builder.append(o); } builder.append("\n"); } return builder.toString(); } public static <T> void assertOrderedEquals(T[] actual, T... expected) { assertOrderedEquals(Arrays.asList(actual), expected); } public static <T> void assertOrderedEquals(Iterable<T> actual, T... expected) { assertOrderedEquals(null, actual, expected); } public static void assertOrderedEquals(@NotNull byte[] actual, @NotNull byte[] expected) { assertEquals(actual.length, expected.length); for (int i = 0; i < actual.length; i++) { byte a = actual[i]; byte e = expected[i]; assertEquals("not equals at index: " + i, e, a); } } public static <T> void assertOrderedEquals( final String errorMsg, @NotNull Iterable<T> actual, @NotNull T... expected) { Assert.assertNotNull(actual); Assert.assertNotNull(expected); assertOrderedEquals(errorMsg, actual, Arrays.asList(expected)); } public static <T> void assertOrderedEquals( final Iterable<? extends T> actual, final Collection<? extends T> expected) { assertOrderedEquals(null, actual, expected); } public static <T> void assertOrderedEquals( final String erroMsg, final Iterable<? extends T> actual, final Collection<? extends T> expected) { ArrayList<T> list = new ArrayList<T>(); for (T t : actual) { list.add(t); } if (!list.equals(new ArrayList<T>(expected))) { String expectedString = toString(expected); String actualString = toString(actual); Assert.assertEquals(erroMsg, expectedString, actualString); Assert.fail( "Warning! 'toString' does not reflect the difference.\nExpected: " + expectedString + "\nActual: " + actualString); } } public static <T> void assertOrderedCollection(T[] collection, @NotNull Consumer<T>... checkers) { Assert.assertNotNull(collection); assertOrderedCollection(Arrays.asList(collection), checkers); } public static <T> void assertSameElements(T[] collection, T... expected) { assertSameElements(Arrays.asList(collection), expected); } public static <T> void assertSameElements(Collection<? extends T> collection, T... expected) { assertSameElements(collection, Arrays.asList(expected)); } public static <T> void assertSameElements( Collection<? extends T> collection, Collection<T> expected) { assertSameElements(null, collection, expected); } public static <T> void assertSameElements( String message, Collection<? extends T> collection, Collection<T> expected) { assertNotNull(collection); assertNotNull(expected); if (collection.size() != expected.size() || !new HashSet<T>(expected).equals(new HashSet<T>(collection))) { Assert.assertEquals(message, toString(expected, "\n"), toString(collection, "\n")); Assert.assertEquals(message, new HashSet<T>(expected), new HashSet<T>(collection)); } } public <T> void assertContainsOrdered(Collection<? extends T> collection, T... expected) { assertContainsOrdered(collection, Arrays.asList(expected)); } public <T> void assertContainsOrdered( Collection<? extends T> collection, Collection<T> expected) { ArrayList<T> copy = new ArrayList<T>(collection); copy.retainAll(expected); assertOrderedEquals(toString(collection), copy, expected); } public <T> void assertContainsElements(Collection<? extends T> collection, T... expected) { assertContainsElements(collection, Arrays.asList(expected)); } public <T> void assertContainsElements( Collection<? extends T> collection, Collection<T> expected) { ArrayList<T> copy = new ArrayList<T>(collection); copy.retainAll(expected); assertSameElements(toString(collection), copy, expected); } public static String toString(Object[] collection, String separator) { return toString(Arrays.asList(collection), separator); } public <T> void assertDoesntContain(Collection<? extends T> collection, T... notExpected) { assertDoesntContain(collection, Arrays.asList(notExpected)); } public <T> void assertDoesntContain( Collection<? extends T> collection, Collection<T> notExpected) { ArrayList<T> expected = new ArrayList<T>(collection); expected.removeAll(notExpected); assertSameElements(collection, expected); } public static String toString(Collection<?> collection, String separator) { List<String> list = ContainerUtil.map2List( collection, new Function<Object, String>() { @Override public String fun(final Object o) { return String.valueOf(o); } }); Collections.sort(list); StringBuilder builder = new StringBuilder(); boolean flag = false; for (final String o : list) { if (flag) { builder.append(separator); } builder.append(o); flag = true; } return builder.toString(); } public static <T> void assertOrderedCollection( Collection<? extends T> collection, Consumer<T>... checkers) { Assert.assertNotNull(collection); if (collection.size() != checkers.length) { Assert.fail(toString(collection)); } int i = 0; for (final T actual : collection) { try { checkers[i].consume(actual); } catch (AssertionFailedError e) { System.out.println(i + ": " + actual); throw e; } i++; } } public static <T> void assertUnorderedCollection(T[] collection, Consumer<T>... checkers) { assertUnorderedCollection(Arrays.asList(collection), checkers); } public static <T> void assertUnorderedCollection( Collection<? extends T> collection, Consumer<T>... checkers) { Assert.assertNotNull(collection); if (collection.size() != checkers.length) { Assert.fail(toString(collection)); } Set<Consumer<T>> checkerSet = new HashSet<Consumer<T>>(Arrays.asList(checkers)); int i = 0; Throwable lastError = null; for (final T actual : collection) { boolean flag = true; for (final Consumer<T> condition : checkerSet) { Throwable error = accepts(condition, actual); if (error == null) { checkerSet.remove(condition); flag = false; break; } else { lastError = error; } } if (flag) { lastError.printStackTrace(); Assert.fail("Incorrect element(" + i + "): " + actual); } i++; } } private static <T> Throwable accepts(final Consumer<T> condition, final T actual) { try { condition.consume(actual); return null; } catch (Throwable e) { return e; } } public static <T> T assertInstanceOf(Object o, Class<T> aClass) { Assert.assertNotNull("Expected instance of: " + aClass.getName() + " actual: " + null, o); Assert.assertTrue( "Expected instance of: " + aClass.getName() + " actual: " + o.getClass().getName(), aClass.isInstance(o)); @SuppressWarnings("unchecked") T t = (T) o; return t; } public static <T> T assertOneElement(Collection<T> collection) { Assert.assertNotNull(collection); Assert.assertEquals(toString(collection), 1, collection.size()); return collection.iterator().next(); } public static <T> T assertOneElement(T[] ts) { Assert.assertNotNull(ts); Assert.assertEquals(Arrays.asList(ts).toString(), 1, ts.length); return ts[0]; } public static <T> void assertOneOf(T value, T... values) { boolean found = false; for (T v : values) { if (value == v || value != null && value.equals(v)) { found = true; } } Assert.assertTrue(value + " should be equal to one of " + Arrays.toString(values), found); } public static void printThreadDump() { PerformanceWatcher.dumpThreadsToConsole("Thread dump:"); } public static void assertEmpty(final Object[] array) { assertOrderedEquals(array); } public static void assertNotEmpty(final Collection<?> collection) { if (collection == null) return; assertTrue(!collection.isEmpty()); } public static void assertEmpty(final Collection<?> collection) { assertEmpty(collection.toString(), collection); } public static void assertNullOrEmpty(final Collection<?> collection) { if (collection == null) return; assertEmpty(null, collection); } public static void assertEmpty(final String s) { assertTrue(s, StringUtil.isEmpty(s)); } public static <T> void assertEmpty(final String errorMsg, final Collection<T> collection) { assertOrderedEquals(errorMsg, collection); } public static void assertSize(int expectedSize, final Object[] array) { assertEquals(toString(Arrays.asList(array)), expectedSize, array.length); } public static void assertSize(int expectedSize, final Collection<?> c) { assertEquals(toString(c), expectedSize, c.size()); } protected <T extends Disposable> T disposeOnTearDown(final T disposable) { Disposer.register(myTestRootDisposable, disposable); return disposable; } public static void assertSameLines(String expected, String actual) { String expectedText = StringUtil.convertLineSeparators(expected.trim()); String actualText = StringUtil.convertLineSeparators(actual.trim()); Assert.assertEquals(expectedText, actualText); } public static void assertExists(File file) { assertTrue("File should exist " + file, file.exists()); } public static void assertDoesntExist(File file) { assertFalse("File should not exist " + file, file.exists()); } protected String getTestName(boolean lowercaseFirstLetter) { String name = getName(); return getTestName(name, lowercaseFirstLetter); } public static String getTestName(String name, boolean lowercaseFirstLetter) { if (name == null) { return ""; } name = StringUtil.trimStart(name, "test"); if (StringUtil.isEmpty(name)) { return ""; } return lowercaseFirstLetter(name, lowercaseFirstLetter); } public static String lowercaseFirstLetter(String name, boolean lowercaseFirstLetter) { if (lowercaseFirstLetter && !isAllUppercaseName(name)) { name = Character.toLowerCase(name.charAt(0)) + name.substring(1); } return name; } public static boolean isAllUppercaseName(String name) { int uppercaseChars = 0; for (int i = 0; i < name.length(); i++) { if (Character.isLowerCase(name.charAt(i))) { return false; } if (Character.isUpperCase(name.charAt(i))) { uppercaseChars++; } } return uppercaseChars >= 3; } protected String getTestDirectoryName() { final String testName = getTestName(true); return testName.replaceAll("_.*", ""); } protected static void assertSameLinesWithFile(String filePath, String actualText) { String fileText; try { if (OVERWRITE_TESTDATA) { VfsTestUtil.overwriteTestData(filePath, actualText); System.out.println("File " + filePath + " created."); } fileText = FileUtil.loadFile(new File(filePath), CharsetToolkit.UTF8); } catch (FileNotFoundException e) { VfsTestUtil.overwriteTestData(filePath, actualText); throw new AssertionFailedError("No output text found. File " + filePath + " created."); } catch (IOException e) { throw new RuntimeException(e); } String expected = StringUtil.convertLineSeparators(fileText.trim()); String actual = StringUtil.convertLineSeparators(actualText.trim()); if (!Comparing.equal(expected, actual)) { throw new FileComparisonFailure(null, expected, actual, filePath); } } public static void clearFields(final Object test) throws IllegalAccessException { Class aClass = test.getClass(); while (aClass != null) { clearDeclaredFields(test, aClass); aClass = aClass.getSuperclass(); } } public static void clearDeclaredFields(Object test, Class aClass) throws IllegalAccessException { if (aClass == null) return; for (final Field field : aClass.getDeclaredFields()) { @NonNls final String name = field.getDeclaringClass().getName(); if (!name.startsWith("junit.framework.") && !name.startsWith("com.intellij.testFramework.")) { final int modifiers = field.getModifiers(); if ((modifiers & Modifier.FINAL) == 0 && (modifiers & Modifier.STATIC) == 0 && !field.getType().isPrimitive()) { field.setAccessible(true); field.set(test, null); } } } } @SuppressWarnings("deprecation") protected static void checkSettingsEqual( JDOMExternalizable expected, JDOMExternalizable settings, String message) throws Exception { if (expected == null || settings == null) return; Element oldS = new Element("temp"); expected.writeExternal(oldS); Element newS = new Element("temp"); settings.writeExternal(newS); String newString = JDOMUtil.writeElement(newS, "\n"); String oldString = JDOMUtil.writeElement(oldS, "\n"); Assert.assertEquals(message, oldString, newString); } public boolean isPerformanceTest() { String name = getName(); return name != null && name.contains("Performance") || getClass().getName().contains("Performance"); } public static void doPostponedFormatting(final Project project) { DocumentUtil.writeInRunUndoTransparentAction( new Runnable() { @Override public void run() { PsiDocumentManager.getInstance(project).commitAllDocuments(); PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); } }); } protected static void checkAllTimersAreDisposed() { try { Class<?> aClass = Class.forName("javax.swing.TimerQueue"); Method inst = aClass.getDeclaredMethod("sharedInstance"); inst.setAccessible(true); Object queue = inst.invoke(null); Field field = aClass.getDeclaredField("firstTimer"); field.setAccessible(true); Object firstTimer = field.get(queue); if (firstTimer != null) { try { fail("Not disposed Timer: " + firstTimer.toString() + "; queue:" + queue); } finally { field.set(queue, null); } } } catch (Throwable e) { // Ignore } } /** * Checks that code block throw corresponding exception. * * @param exceptionCase Block annotated with some exception type * @throws Throwable */ protected void assertException(final AbstractExceptionCase exceptionCase) throws Throwable { assertException(exceptionCase, null); } /** * Checks that code block throw corresponding exception with expected error msg. If expected error * message is null it will not be checked. * * @param exceptionCase Block annotated with some exception type * @param expectedErrorMsg expected error messge * @throws Throwable */ protected void assertException( final AbstractExceptionCase exceptionCase, @Nullable final String expectedErrorMsg) throws Throwable { assertExceptionOccurred(true, exceptionCase, expectedErrorMsg); } /** * Checks that code block doesn't throw corresponding exception. * * @param exceptionCase Block annotated with some exception type * @throws Throwable */ protected void assertNoException(final AbstractExceptionCase exceptionCase) throws Throwable { assertExceptionOccurred(false, exceptionCase, null); } protected void assertNoThrowable(final Runnable closure) { String throwableName = null; try { closure.run(); } catch (Throwable thr) { throwableName = thr.getClass().getName(); } assertNull(throwableName); } private static void assertExceptionOccurred( boolean shouldOccur, AbstractExceptionCase exceptionCase, String expectedErrorMsg) throws Throwable { boolean wasThrown = false; try { exceptionCase.tryClosure(); } catch (Throwable e) { if (shouldOccur) { wasThrown = true; final String errorMessage = exceptionCase.getAssertionErrorMessage(); assertEquals(errorMessage, exceptionCase.getExpectedExceptionClass(), e.getClass()); if (expectedErrorMsg != null) { assertEquals("Compare error messages", expectedErrorMsg, e.getMessage()); } } else if (exceptionCase.getExpectedExceptionClass().equals(e.getClass())) { wasThrown = true; System.out.println(""); e.printStackTrace(System.out); fail("Exception isn't expected here. Exception message: " + e.getMessage()); } else { throw e; } } finally { if (shouldOccur && !wasThrown) { fail(exceptionCase.getAssertionErrorMessage()); } } } protected boolean annotatedWith(@NotNull Class annotationClass) { Class<?> aClass = getClass(); String methodName = "test" + getTestName(false); boolean methodChecked = false; while (aClass != null && aClass != Object.class) { if (aClass.getAnnotation(annotationClass) != null) return true; if (!methodChecked) { try { Method method = aClass.getDeclaredMethod(methodName); if (method.getAnnotation(annotationClass) != null) return true; methodChecked = true; } catch (NoSuchMethodException ignored) { } } aClass = aClass.getSuperclass(); } return false; } protected String getHomePath() { return PathManager.getHomePath().replace(File.separatorChar, '/'); } protected static boolean isInHeadlessEnvironment() { return GraphicsEnvironment.isHeadless(); } public static void refreshRecursively(@NotNull VirtualFile file) { VfsUtilCore.visitChildrenRecursively( file, new VirtualFileVisitor() { @Override public boolean visitFile(@NotNull VirtualFile file) { file.getChildren(); return true; } }); file.refresh(false, true); } @NotNull public static Test filteredSuite(@RegExp String regexp, @NotNull Test test) { final Pattern pattern = Pattern.compile(regexp); final TestSuite testSuite = new TestSuite(); new Processor<Test>() { @Override public boolean process(Test test) { if (test instanceof TestSuite) { for (int i = 0, len = ((TestSuite) test).testCount(); i < len; i++) { process(((TestSuite) test).testAt(i)); } } else if (pattern.matcher(test.toString()).find()) { testSuite.addTest(test); } return false; } }.process(test); return testSuite; } }