2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.testFramework
;
18 import com
.intellij
.codeInsight
.CodeInsightSettings
;
19 import com
.intellij
.openapi
.Disposable
;
20 import com
.intellij
.openapi
.application
.ApplicationManager
;
21 import com
.intellij
.openapi
.command
.CommandProcessor
;
22 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
23 import com
.intellij
.openapi
.project
.Project
;
24 import com
.intellij
.openapi
.util
.Disposer
;
25 import com
.intellij
.openapi
.util
.JDOMExternalizable
;
26 import com
.intellij
.openapi
.util
.JDOMUtil
;
27 import com
.intellij
.openapi
.util
.Key
;
28 import com
.intellij
.openapi
.util
.io
.FileUtil
;
29 import com
.intellij
.openapi
.util
.text
.StringUtil
;
30 import com
.intellij
.psi
.PsiDocumentManager
;
31 import com
.intellij
.psi
.codeStyle
.CodeStyleSettings
;
32 import com
.intellij
.psi
.codeStyle
.CodeStyleSettingsManager
;
33 import com
.intellij
.psi
.impl
.source
.PostprocessReformattingAspect
;
34 import com
.intellij
.util
.Consumer
;
35 import com
.intellij
.util
.Function
;
36 import com
.intellij
.util
.containers
.ContainerUtil
;
37 import com
.intellij
.refactoring
.rename
.inplace
.VariableInplaceRenamer
;
38 import com
.intellij
.testFramework
.exceptionCases
.AbstractExceptionCase
;
39 import gnu
.trove
.THashSet
;
40 import junit
.framework
.Assert
;
41 import junit
.framework
.AssertionFailedError
;
42 import junit
.framework
.TestCase
;
43 import org
.jdom
.Element
;
44 import org
.jetbrains
.annotations
.NonNls
;
45 import org
.jetbrains
.annotations
.Nullable
;
47 import java
.io
.FileReader
;
48 import java
.io
.IOException
;
49 import java
.lang
.reflect
.Field
;
50 import java
.lang
.reflect
.Method
;
51 import java
.lang
.reflect
.Modifier
;
57 public abstract class UsefulTestCase
extends TestCase
{
58 protected final Disposable myTestRootDisposable
= new Disposable() {
59 public void dispose() {
62 private static final String DEFAULT_SETTINGS_EXTERNALIZED
;
63 private static CodeStyleSettings myOldCodeStyleSettings
;
65 protected static final Key
<String
> CREATION_PLACE
= Key
.create("CREATION_PLACE");
69 CodeInsightSettings defaultSettings
= new CodeInsightSettings();
70 Element oldS
= new Element("temp");
71 defaultSettings
.writeExternal(oldS
);
72 DEFAULT_SETTINGS_EXTERNALIZED
= JDOMUtil
.writeElement(oldS
, "\n");
75 throw new RuntimeException(e
);
79 protected void tearDown() throws Exception
{
80 Disposer
.dispose(myTestRootDisposable
);
81 cleanupSwingDataStructures();
85 private static void cleanupSwingDataStructures() throws Exception
{
86 Class
<?
> aClass
= Class
.forName("javax.swing.KeyboardManager");
88 Method get
= aClass
.getMethod("getCurrentManager");
89 get
.setAccessible(true);
90 Object manager
= get
.invoke(null);
92 Field mapF
= aClass
.getDeclaredField("componentKeyStrokeMap");
93 mapF
.setAccessible(true);
94 Object map
= mapF
.get(manager
);
98 Field mapF
= aClass
.getDeclaredField("containerMap");
99 mapF
.setAccessible(true);
100 Object map
= mapF
.get(manager
);
104 //Constructor<?> ctr = aClass.getDeclaredConstructor();
105 //ctr.setAccessible(true);
106 //Object newManager = ctr.newInstance();
107 //Method setter = aClass.getDeclaredMethod("setCurrentManager", aClass);
108 //setter.setAccessible(true);
109 //setter.invoke(null, newManager);
112 protected void checkForSettingsDamage() throws Exception
{
113 if (isPerformanceTest() || ApplicationManager
.getApplication() == null) {
116 final CodeInsightSettings settings
= CodeInsightSettings
.getInstance();
117 Element newS
= new Element("temp");
118 settings
.writeExternal(newS
);
119 Assert
.assertEquals("Code insight settings damaged", DEFAULT_SETTINGS_EXTERNALIZED
, JDOMUtil
.writeElement(newS
, "\n"));
122 CodeStyleSettings codeStyleSettings
= getCurrentCodeStyleSettings();
123 codeStyleSettings
.getIndentOptions(StdFileTypes
.JAVA
);
125 checkSettingsEqual(myOldCodeStyleSettings
, codeStyleSettings
, "Code style settings damaged");
128 codeStyleSettings
.clearCodeStyleSettings();
130 myOldCodeStyleSettings
= null;
132 VariableInplaceRenamer
.checkCleared();
135 protected void storeSettings() {
136 if (!isPerformanceTest() && ApplicationManager
.getApplication() != null) {
137 myOldCodeStyleSettings
= getCurrentCodeStyleSettings().clone();
138 myOldCodeStyleSettings
.getIndentOptions(StdFileTypes
.JAVA
);
142 protected CodeStyleSettings
getCurrentCodeStyleSettings() {
143 return CodeStyleSettingsManager
.getInstance().getCurrentSettings();
146 protected Disposable
getTestRootDisposable() {
147 return myTestRootDisposable
;
151 public static String
toString(Collection
<?
> collection
) {
152 if (collection
.isEmpty()) {
156 final StringBuilder builder
= new StringBuilder();
157 for (final Object o
: collection
) {
158 if (o
instanceof THashSet
) {
159 builder
.append(new TreeSet
<Object
>((Collection
<Object
>)o
));
164 builder
.append("\n");
166 return builder
.toString();
169 public static <T
> void assertOrderedEquals(T
[] actual
, T
... expected
) {
170 assertOrderedEquals(Arrays
.asList(actual
), expected
);
173 public static <T
> void assertOrderedEquals(Collection
<T
> actual
, T
... expected
) {
174 assertOrderedEquals(null, actual
, expected
);
177 public static <T
> void assertOrderedEquals(final String errorMsg
, Collection
<T
> actual
, T
... expected
) {
178 Assert
.assertNotNull(actual
);
179 Assert
.assertNotNull(expected
);
180 assertOrderedEquals(errorMsg
, actual
, Arrays
.asList(expected
));
183 public static <T
> void assertOrderedEquals(final Collection
<?
extends T
> actual
, final Collection
<?
extends T
> expected
) {
184 assertOrderedEquals(null, actual
, expected
);
187 public static <T
> void assertOrderedEquals(final String erroMsg
, final Collection
<?
extends T
> actual
, final Collection
<?
extends T
> expected
) {
188 if (!new ArrayList
<T
>(actual
).equals(new ArrayList
<T
>(expected
))) {
189 Assert
.assertEquals(erroMsg
, toString(expected
), toString(actual
));
194 public static <T
> void assertOrderedCollection(T
[] collection
, Consumer
<T
>... checkers
) {
195 Assert
.assertNotNull(collection
);
196 assertOrderedCollection(Arrays
.asList(collection
), checkers
);
199 public static <T
> void assertSameElements(T
[] collection
, T
... expected
) {
200 assertSameElements(Arrays
.asList(collection
), expected
);
203 public static <T
> void assertSameElements(Collection
<?
extends T
> collection
, T
... expected
) {
204 assertSameElements(collection
, Arrays
.asList(expected
));
206 public static <T
> void assertSameElements(Collection
<?
extends T
> collection
, Collection
<T
> expected
) {
207 if (collection
.size() != expected
.size() || !new HashSet
<T
>(expected
).equals(new HashSet
<T
>(collection
))) {
208 Assert
.assertEquals(toString(expected
, "\n"), toString(collection
, "\n"));
209 Assert
.assertEquals(new HashSet
<T
>(expected
), new HashSet
<T
>(collection
));
213 public static String
toString(Object
[] collection
, String separator
) {
214 return toString(Arrays
.asList(collection
), separator
);
217 public static String
toString(Collection
<?
> collection
, String separator
) {
218 List
<String
> list
= ContainerUtil
.map2List(collection
, new Function
<Object
,String
>() {
219 public String
fun(final Object o
) {
220 return String
.valueOf(o
);
223 Collections
.sort(list
);
224 StringBuilder builder
= new StringBuilder();
225 boolean flag
= false;
226 for (final String o
: list
) {
228 builder
.append(separator
);
233 return builder
.toString();
236 public static <T
> void assertOrderedCollection(Collection
<?
extends T
> collection
, Consumer
<T
>... checkers
) {
237 Assert
.assertNotNull(collection
);
238 if (collection
.size() != checkers
.length
) {
239 Assert
.fail(toString(collection
));
242 for (final T actual
: collection
) {
244 checkers
[i
].consume(actual
);
246 catch (AssertionFailedError e
) {
247 System
.out
.println(i
+ ": " + actual
);
254 public static <T
> void assertUnorderedCollection(T
[] collection
, Consumer
<T
>... checkers
) {
255 assertUnorderedCollection(Arrays
.asList(collection
), checkers
);
258 public static <T
> void assertUnorderedCollection(Collection
<?
extends T
> collection
, Consumer
<T
>... checkers
) {
259 Assert
.assertNotNull(collection
);
260 if (collection
.size() != checkers
.length
) {
261 Assert
.fail(toString(collection
));
263 Set
<Consumer
<T
>> checkerSet
= new HashSet
<Consumer
<T
>>(Arrays
.asList(checkers
));
265 Throwable lastError
= null;
266 for (final T actual
: collection
) {
268 for (final Consumer
<T
> condition
: checkerSet
) {
269 Throwable error
= accepts(condition
, actual
);
271 checkerSet
.remove(condition
);
280 lastError
.printStackTrace();
281 Assert
.fail("Incorrect element(" + i
+ "): " + actual
);
287 private static <T
> Throwable
accepts(final Consumer
<T
> condition
, final T actual
) {
289 condition
.consume(actual
);
292 catch (Throwable e
) {
297 public static <T
> T
assertInstanceOf(Object o
, Class
<T
> aClass
) {
298 Assert
.assertNotNull(o
);
299 Assert
.assertTrue(o
.getClass().getName(), aClass
.isInstance(o
));
303 public static <T
> T
assertOneElement(Collection
<T
> collection
) {
304 Assert
.assertNotNull(collection
);
305 Assert
.assertEquals(toString(collection
), 1, collection
.size());
306 return collection
.iterator().next();
309 public static <T
> T
assertOneElement(T
[] ts
) {
310 Assert
.assertNotNull(ts
);
311 Assert
.assertEquals(1, ts
.length
);
315 public static void printThreadDump() {
316 final Map
<Thread
,StackTraceElement
[]> traces
= Thread
.getAllStackTraces();
317 for (final Map
.Entry
<Thread
, StackTraceElement
[]> entry
: traces
.entrySet()) {
318 System
.out
.println("\n" + entry
.getKey().getName() + "\n");
319 final StackTraceElement
[] value
= entry
.getValue();
320 for (final StackTraceElement stackTraceElement
: value
) {
321 System
.out
.println(" at "+stackTraceElement
);
326 public static void assertEmpty(final Object
[] array
) {
327 assertOrderedEquals(array
);
330 public static void assertEmpty(final Collection
<?
> collection
) {
331 assertEmpty(null, collection
);
334 public static void assertEmpty(final String s
) {
335 assertTrue(s
, StringUtil
.isEmpty(s
));
338 public static void assertEmpty(final String errorMsg
, final Collection
<?
> collection
) {
339 assertOrderedEquals(errorMsg
, collection
);
342 protected <T
extends Disposable
> T
disposeOnTearDown(final T disposable
) {
343 Disposer
.register(myTestRootDisposable
, disposable
);
347 public static void assertSameLines(String expected
, String actual
) {
348 String expectedText
= StringUtil
.convertLineSeparators(expected
.trim());
349 String actualText
= StringUtil
.convertLineSeparators(actual
.trim());
350 Assert
.assertEquals(expectedText
, actualText
);
353 protected String
getTestName(boolean lowercaseFirstLetter
) {
354 String name
= getName();
355 name
= StringUtil
.trimStart(name
, "test");
356 if (StringUtil
.isEmpty(name
)) {
359 if (lowercaseFirstLetter
&& !isAllUppercaseName(name
)) {
360 name
= Character
.toLowerCase(name
.charAt(0)) + name
.substring(1);
365 public static boolean isAllUppercaseName(String name
) {
366 int uppercaseChars
= 0;
367 for(int i
=0; i
<name
.length(); i
++) {
368 if (Character
.isLowerCase(name
.charAt(i
))) {
371 if (Character
.isUpperCase(name
.charAt(i
))) {
375 return uppercaseChars
>= 3;
378 protected String
getTestDirectoryName() {
379 final String testName
= getTestName(true);
380 return testName
.replaceAll("_.*", "");
383 protected static void assertSameLinesWithFile(final String filePath
, final String actualText
) {
386 final FileReader reader
= new FileReader(filePath
);
387 fileText
= FileUtil
.loadTextAndClose(reader
);
389 catch (IOException e
) {
390 throw new RuntimeException(e
);
392 assertSameLines(fileText
, actualText
);
395 public static void clearFields(final Object test
) throws IllegalAccessException
{
396 Class aClass
= test
.getClass();
397 while (aClass
!= null) {
398 clearDeclaredFields(test
, aClass
);
399 aClass
= aClass
.getSuperclass();
403 public static void clearDeclaredFields(Object test
, Class aClass
) throws IllegalAccessException
{
404 if (aClass
== null) return;
405 for (final Field field
: aClass
.getDeclaredFields()) {
406 @NonNls final String name
= field
.getDeclaringClass().getName();
407 if (!name
.startsWith("junit.framework.") && !name
.startsWith("com.intellij.testFramework.")) {
408 final int modifiers
= field
.getModifiers();
409 if ((modifiers
& Modifier
.FINAL
) == 0 && (modifiers
& Modifier
.STATIC
) == 0 && !field
.getType().isPrimitive()) {
410 field
.setAccessible(true);
411 field
.set(test
, null);
417 protected static void checkSettingsEqual(JDOMExternalizable expected
, JDOMExternalizable settings
, String message
) throws Exception
{
418 if (expected
== null) {
421 if (settings
== null) {
424 Element oldS
= new Element("temp");
425 expected
.writeExternal(oldS
);
426 Element newS
= new Element("temp");
427 settings
.writeExternal(newS
);
429 String newString
= JDOMUtil
.writeElement(newS
, "\n");
430 String oldString
= JDOMUtil
.writeElement(oldS
, "\n");
431 Assert
.assertEquals(message
, oldString
, newString
);
434 public boolean isPerformanceTest() {
435 String name
= getName();
436 return name
!= null && name
.contains("Performance") || getClass().getName().contains("Performance");
439 public static void doPostponedFormatting(final Project project
) {
441 CommandProcessor
.getInstance().runUndoTransparentAction(new Runnable() {
443 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
445 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
446 PostprocessReformattingAspect
.getInstance(project
).doPostponedFormatting();
452 catch (Throwable e
) {
457 protected static void checkAllTimersAreDisposed() throws Exception
{
458 Class
<?
> aClass
= Class
.forName("javax.swing.TimerQueue");
460 Method inst
= aClass
.getDeclaredMethod("sharedInstance");
461 inst
.setAccessible(true);
462 Object queue
= inst
.invoke(null);
463 Field field
= aClass
.getDeclaredField("firstTimer");
464 field
.setAccessible(true);
465 Object firstTimer
= field
.get(queue
);
466 if (firstTimer
!= null) {
468 fail("Not disposed Timer: "+firstTimer
.toString()+"; queue:"+queue
);
471 field
.set(queue
, null);
477 * Checks that code block throw corresponding exception.
478 * @param exceptionCase Block annotated with some exception type
481 protected void assertException(final AbstractExceptionCase exceptionCase
) throws Throwable
{
482 assertException(exceptionCase
, null);
486 * Checks that code block throw corresponding exception with expected error msg.
487 * If expected error message is null it will not be checked.
488 * @param exceptionCase Block annotated with some exception type
489 * @param expectedErrorMsg expected error messge
492 protected void assertException(final AbstractExceptionCase exceptionCase
,
493 @Nullable final String expectedErrorMsg
) throws Throwable
{
494 assertExceptionOccurred(true, exceptionCase
, expectedErrorMsg
);
498 * Checks that code block doesn't throw corresponding exception.
499 * @param exceptionCase Block annotated with some exception type
502 protected void assertNoException(final AbstractExceptionCase exceptionCase
) throws Throwable
{
503 assertExceptionOccurred(false, exceptionCase
, null);
506 protected void assertNoThrowable(final Runnable closure
) {
507 String throwableName
= null;
510 } catch (Throwable thr
) {
511 throwableName
= thr
.getClass().getName();
513 assertNull(throwableName
);
516 private void assertExceptionOccurred(boolean shouldOccur
,
517 AbstractExceptionCase exceptionCase
,
518 String expectedErrorMsg
) throws Throwable
{
519 boolean wasThrown
= false;
521 exceptionCase
.tryClosure();
522 } catch (Throwable e
) {
525 final String errorMessage
= exceptionCase
.getAssertionErrorMessage();
526 assertEquals(errorMessage
, exceptionCase
.getExpectedExceptionClass(), e
.getClass());
527 if (expectedErrorMsg
!= null) {
528 assertEquals("Compare error messages", expectedErrorMsg
, e
.getMessage());
530 } else if (exceptionCase
.getExpectedExceptionClass().equals(e
.getClass())) {
533 System
.out
.println("");
534 e
.printStackTrace(System
.out
);
536 fail("Exception isn't expected here. Exception message: " + e
.getMessage());
541 if (shouldOccur
&& !wasThrown
) {
542 fail(exceptionCase
.getAssertionErrorMessage());