From 5c82be881d09ca8df67d334934554c4df3b7f199 Mon Sep 17 00:00:00 2001 From: Jonah Graham Date: Sat, 19 Dec 2020 14:29:24 -0500 Subject: [PATCH] Bug 569839: Provide a new JUnit5 base and utility classes Change-Id: I8682f4702cfa0cad7d0452ca48d1ab74eeb1dbdb --- .../cdt/codan/core/tests/CodanTestCase.java | 1 + .../.settings/.api_filters | 12 + .../META-INF/MANIFEST.MF | 1 + .../index/tests/TeamSharedIndexTest.java | 1 + .../pdom/tests/ChangeConfigurationTests.java | 1 + .../cdt/internal/pdom/tests/PDOMTestBase.java | 1 + .../core/testplugin/util/BaseTestCase.java | 186 ++---------- .../core/testplugin/util/BaseTestCase5.java | 284 ++++++++++++++++++ .../core/testplugin/util/LogMonitoring.java | 90 ++++++ .../cdt/core/testplugin/util/ModelJoiner.java | 69 +++++ .../cdt/ui/tests/UITestCaseWithProject.java | 1 + 11 files changed, 484 insertions(+), 163 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/.settings/.api_filters create mode 100644 core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase5.java create mode 100644 core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/LogMonitoring.java create mode 100644 core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/ModelJoiner.java diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java index e833eb9d6f2..d6989fe3746 100644 --- a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java @@ -27,6 +27,7 @@ import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.core.testplugin.util.ModelJoiner; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; diff --git a/core/org.eclipse.cdt.core.tests/.settings/.api_filters b/core/org.eclipse.cdt.core.tests/.settings/.api_filters new file mode 100644 index 00000000000..cc8fdc94773 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/.settings/.api_filters @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF index b63891271a3..3d3b4e2e0b7 100644 --- a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF @@ -48,3 +48,4 @@ Bundle-Vendor: %providerName Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: org.eclipse.cdt.core.tests Bundle-Localization: plugin +Import-Package: org.junit.jupiter.api;version="5.7.0" diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java index 1bcdecaf8b3..4c7486907f5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/TeamSharedIndexTest.java @@ -29,6 +29,7 @@ import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.core.testplugin.util.ModelJoiner; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.core.resources.IFile; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ChangeConfigurationTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ChangeConfigurationTests.java index 86d90490a8d..8f6b1dab75c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ChangeConfigurationTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ChangeConfigurationTests.java @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CTestPlugin; +import org.eclipse.cdt.core.testplugin.util.ModelJoiner; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java index 9bb0fe1f6d7..5d4f6a97937 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java @@ -38,6 +38,7 @@ import org.eclipse.cdt.core.parser.tests.VisibilityAsserts; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.core.testplugin.util.ModelJoiner; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.pdom.PDOM; diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java index 172d940df91..c6efc350e43 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java @@ -20,36 +20,21 @@ import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.HashSet; -import java.util.List; import java.util.Set; -import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.index.IIndex; -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.ElementChangedEvent; import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.model.IElementChangedListener; import org.eclipse.cdt.core.testplugin.ResourceHelper; import org.eclipse.cdt.core.testplugin.TestScannerProvider; -import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; import org.eclipse.cdt.internal.core.pdom.CModelListener; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResourceStatus; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.ILogListener; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.jobs.Job; import junit.framework.AssertionFailedError; import junit.framework.Test; @@ -58,29 +43,33 @@ import junit.framework.TestFailure; import junit.framework.TestResult; import junit.framework.TestSuite; +/** + * @deprecated Please migrate tests away from JUnit3 style to JUnit5 style by using {@link BaseTestCase5} + * as base class. + */ +@Deprecated public abstract class BaseTestCase extends TestCase { - private static final String DEFAULT_INDEXER_TIMEOUT_SEC = "10"; - private static final String INDEXER_TIMEOUT_PROPERTY = "indexer.timeout"; + private static final String DEFAULT_INDEXER_TIMEOUT_SEC = BaseTestCase5.DEFAULT_INDEXER_TIMEOUT_SEC; + private static final String INDEXER_TIMEOUT_PROPERTY = BaseTestCase5.INDEXER_TIMEOUT_PROPERTY; /** * Indexer timeout used by tests. To avoid this timeout expiring during debugging add * -Dindexer.timeout=some_large_number to VM arguments of the test launch configuration. */ - protected static final int INDEXER_TIMEOUT_SEC = Integer - .parseInt(System.getProperty(INDEXER_TIMEOUT_PROPERTY, DEFAULT_INDEXER_TIMEOUT_SEC)); - protected static final int INDEXER_TIMEOUT_MILLISEC = INDEXER_TIMEOUT_SEC * 1000; + protected static final int INDEXER_TIMEOUT_SEC = BaseTestCase5.INDEXER_TIMEOUT_SEC; + protected static final int INDEXER_TIMEOUT_MILLISEC = BaseTestCase5.INDEXER_TIMEOUT_MILLISEC; /** * The GCC version to emulate when running tests. * We emulate the latest version whose extensions we support. */ - protected static final int GCC_MAJOR_VERSION_FOR_TESTS = 10; - protected static final int GCC_MINOR_VERSION_FOR_TESTS = 1; + protected static final int GCC_MAJOR_VERSION_FOR_TESTS = BaseTestCase5.GCC_MAJOR_VERSION_FOR_TESTS; + protected static final int GCC_MINOR_VERSION_FOR_TESTS = BaseTestCase5.GCC_MINOR_VERSION_FOR_TESTS; /** * This provides the systems new line separator. Use this if you do String comparisons in tests * instead of hard coding '\n' or '\r\n' respectively. */ - protected static final String NL = System.getProperty("line.separator"); + protected static final String NL = BaseTestCase5.NL; private boolean fExpectFailure; private int fBugNumber; @@ -187,74 +176,13 @@ public abstract class BaseTestCase extends TestCase { @Override public void runBare() throws Throwable { - final List statusLog = Collections.synchronizedList(new ArrayList()); - ILogListener logListener = new ILogListener() { - @Override - public void logging(IStatus status, String plugin) { - if (!status.isOK() && status.getSeverity() != IStatus.INFO) { - switch (status.getCode()) { - case IResourceStatus.NOT_FOUND_LOCAL: - case IResourceStatus.NO_LOCATION_LOCAL: - case IResourceStatus.FAILED_READ_LOCAL: - case IResourceStatus.RESOURCE_NOT_LOCAL: - // Logged by the resources plugin. - return; - } - statusLog.add(status); - } - } - }; - final CCorePlugin corePlugin = CCorePlugin.getDefault(); - if (corePlugin != null) { // Iff we don't run as a JUnit Plugin Test. - corePlugin.getLog().addLogListener(logListener); - } - - Throwable testThrowable = null; + LogMonitoring monitoring = new LogMonitoring(); + monitoring.start(); try { - try { - super.runBare(); - } catch (Throwable e) { - testThrowable = e; - } - - if (statusLog.size() != fExpectedLoggedNonOK) { - StringBuilder msg = new StringBuilder("Expected number (").append(fExpectedLoggedNonOK).append(") of "); - msg.append("Non-OK status objects in log differs from actual (").append(statusLog.size()) - .append(").\n"); - Throwable cause = null; - if (!statusLog.isEmpty()) { - synchronized (statusLog) { - for (IStatus status : statusLog) { - IStatus[] ss = { status }; - ss = status instanceof MultiStatus ? ((MultiStatus) status).getChildren() : ss; - for (IStatus s : ss) { - msg.append('\t').append(s.getMessage()).append(' '); - - Throwable t = s.getException(); - cause = cause != null ? cause : t; - if (t != null) { - msg.append( - t.getMessage() != null ? t.getMessage() : t.getClass().getCanonicalName()); - } - - msg.append("\n"); - } - } - } - } - cause = cause != null ? cause : testThrowable; - AssertionFailedError afe = new AssertionFailedError(msg.toString()); - afe.initCause(cause); - throw afe; - } + super.runBare(); } finally { - if (corePlugin != null) { - corePlugin.getLog().removeLogListener(logListener); - } + monitoring.stop(fExpectedLoggedNonOK); } - - if (testThrowable != null) - throw testThrowable; } @Override @@ -302,97 +230,29 @@ public abstract class BaseTestCase extends TestCase { fExpectedLoggedNonOK = count; } - /** - * Some test steps need synchronizing against a CModel event. This class - * is a very basic means of doing that. - */ - static protected class ModelJoiner implements IElementChangedListener { - private final boolean[] changed = new boolean[1]; - - public ModelJoiner() { - CoreModel.getDefault().addElementChangedListener(this); - } - - public void clear() { - synchronized (changed) { - changed[0] = false; - changed.notifyAll(); - } - } - - public void join() throws CoreException { - try { - synchronized (changed) { - while (!changed[0]) { - changed.wait(); - } - } - } catch (InterruptedException e) { - throw new CoreException(CCorePlugin.createStatus("Interrupted", e)); - } - } - - public void dispose() { - CoreModel.getDefault().removeElementChangedListener(this); - } - - @Override - public void elementChanged(ElementChangedEvent event) { - // Only respond to post change events - if (event.getType() != ElementChangedEvent.POST_CHANGE) - return; - - synchronized (changed) { - changed[0] = true; - changed.notifyAll(); - } - } - } - public static void waitForIndexer(ICProject project) throws InterruptedException { - Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null); - assertTrue(CCoreInternals.getPDOMManager().joinIndexer(INDEXER_TIMEOUT_SEC * 1000, npm())); + BaseTestCase5.waitForIndexer(project); } public static void waitUntilFileIsIndexed(IIndex index, IFile file) throws Exception { - TestSourceReader.waitUntilFileIsIndexed(index, file, INDEXER_TIMEOUT_SEC * 1000); + BaseTestCase5.waitUntilFileIsIndexed(index, file); } - // Assertion helpers + // Assertion helpers (redirected to the common implementation) protected static T assertInstance(Object o, Class clazz, Class... cs) { - assertNotNull("Expected object of " + clazz.getName() + " but got a null value", o); - assertTrue("Expected " + clazz.getName() + " but got " + o.getClass().getName(), clazz.isInstance(o)); - for (Class c : cs) { - assertNotNull("Expected object of " + c.getName() + " but got a null value", o); - assertTrue("Expected " + c.getName() + " but got " + o.getClass().getName(), c.isInstance(o)); - } - return clazz.cast(o); + return BaseTestCase5.assertInstance(o, clazz, cs); } protected static void assertValue(IValue value, long expectedValue) { - assertNotNull(value); - assertTrue(value.numberValue() instanceof Long); - assertEquals(expectedValue, value.numberValue().longValue()); + BaseTestCase5.assertValue(value, expectedValue); } protected static void assertVariableValue(IVariable var, long expectedValue) { - assertValue(var.getInitialValue(), expectedValue); + BaseTestCase5.assertVariableValue(var, expectedValue); } protected static String formatForPrinting(IASTName name) { - String signature = name.getRawSignature(); - boolean saved = CPPASTNameBase.sAllowNameComputation; - CPPASTNameBase.sAllowNameComputation = true; - try { - String nameStr = name.toString(); - if (signature.replace(" ", "").equals(nameStr.replace(" ", ""))) - return signature; - return nameStr + " in " + signature; - } catch (Throwable e) { - return signature; - } finally { - CPPASTNameBase.sAllowNameComputation = saved; - } + return BaseTestCase5.formatForPrinting(name); } } diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase5.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase5.java new file mode 100644 index 00000000000..8f9c529924f --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase5.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Markus Schorn - initial API and implementation + * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.core.testplugin.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; + +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.ResourceHelper; +import org.eclipse.cdt.core.testplugin.TestScannerProvider; +import org.eclipse.cdt.internal.core.CCoreInternals; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; +import org.eclipse.cdt.internal.core.pdom.CModelListener; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInfo; + +import junit.framework.TestResult; + +/** + * BaseTestCase for JUnit5. + */ +public abstract class BaseTestCase5 { + protected static final String DEFAULT_INDEXER_TIMEOUT_SEC = "10"; + protected static final String INDEXER_TIMEOUT_PROPERTY = "indexer.timeout"; + /** + * Indexer timeout used by tests. To avoid this timeout expiring during debugging add + * -Dindexer.timeout=some_large_number to VM arguments of the test launch configuration. + */ + protected static final int INDEXER_TIMEOUT_SEC = Integer + .parseInt(System.getProperty(INDEXER_TIMEOUT_PROPERTY, DEFAULT_INDEXER_TIMEOUT_SEC)); + protected static final int INDEXER_TIMEOUT_MILLISEC = INDEXER_TIMEOUT_SEC * 1000; + + /** + * The GCC version to emulate when running tests. + * We emulate the latest version whose extensions we support. + */ + protected static final int GCC_MAJOR_VERSION_FOR_TESTS = 10; + protected static final int GCC_MINOR_VERSION_FOR_TESTS = 1; + + /** + * This provides the systems new line separator. Use this if you do String comparisons in tests + * instead of hard coding '\n' or '\r\n' respectively. + */ + protected static final String NL = System.getProperty("line.separator"); + + private boolean fExpectFailure; + private int fBugNumber; + private int fExpectedLoggedNonOK; + private Deque filesToDeleteOnTearDown = new ArrayDeque<>(); + private TestInfo testInfo; + + LogMonitoring logMonitoring = new LogMonitoring(); + + /** + * Backwards support for JUnit3 style test that had a getName. This is not 100% the same, but close + * enough for the general use case of getName. + */ + public String getName() { + return testInfo.getDisplayName(); + } + + public static NullProgressMonitor npm() { + return new NullProgressMonitor(); + } + + @BeforeEach + protected void setupBase(TestInfo testInfo) throws Exception { + this.testInfo = testInfo; + + logMonitoring.start(); + + CPPASTNameBase.sAllowRecursionBindings = false; + CPPASTNameBase.sAllowNameComputation = false; + CModelListener.sSuppressUpdateOfLastRecentlyUsed = true; + } + + @AfterEach + protected void tearDownBase() throws Exception { + for (File file; (file = filesToDeleteOnTearDown.pollLast()) != null;) { + file.delete(); + } + ResourceHelper.cleanUp(getName()); + TestScannerProvider.clear(); + + logMonitoring.stop(fExpectedLoggedNonOK); + } + + protected void deleteOnTearDown(File file) { + filesToDeleteOnTearDown.add(file); + } + + protected File createTempFile(String prefix, String suffix) throws IOException { + File file = File.createTempFile(prefix, suffix); + filesToDeleteOnTearDown.add(file); + return file; + } + + protected File nonExistentTempFile(String prefix, String suffix) { + File file = new File(System.getProperty("java.io.tmpdir"), prefix + System.currentTimeMillis() + suffix); + filesToDeleteOnTearDown.add(file); + return file; + } + + /** + * The last value passed to this method in the body of a testXXX method + * will be used to determine whether or not the presence of non-OK status objects + * in the log should fail the test. If the logged number of non-OK status objects + * differs from the last value passed, the test is failed. If this method is not called + * at all, the expected number defaults to zero. + * @param count the expected number of logged error and warning messages + */ + public void setExpectedNumberOfLoggedNonOKStatusObjects(int count) { + fExpectedLoggedNonOK = count; + } + + public static void waitForIndexer(ICProject project) throws InterruptedException { + Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null); + assertTrue(CCoreInternals.getPDOMManager().joinIndexer(INDEXER_TIMEOUT_SEC * 1000, npm())); + } + + public static void waitUntilFileIsIndexed(IIndex index, IFile file) throws Exception { + TestSourceReader.waitUntilFileIsIndexed(index, file, INDEXER_TIMEOUT_SEC * 1000); + } + + // Assertion helpers + + /** + * Asserts that the file does exist and prints a niceish error message if not. + */ + public static void assertExists(File f) { + assertTrue(f.exists(), "File " + f + " does not exist"); + } + + /** + * Asserts that the resource does exist and prints a niceish error message if not. + */ + public static void assertExists(IResource f) { + assertTrue(f.exists(), "Resource " + f + " does not exist"); + } + + /** + * Asserts that the file does exist and prints a niceish error message if not. + */ + public static void assertNotExists(File f) { + assertFalse(f.exists(), "File " + f + " should not exist"); + } + + /** + * Asserts that the Resource does exist and prints a niceish error message if not. + */ + public static void assertNotExists(IResource f) { + assertFalse(f.exists(), "Resource " + f + " should not exist"); + } + + public static T assertInstance(Object o, Class clazz, Class... cs) { + assertNotNull(o, "Expected object of " + clazz.getName() + " but got a null value"); + assertTrue(clazz.isInstance(o), "Expected " + clazz.getName() + " but got " + o.getClass().getName()); + for (Class c : cs) { + assertNotNull(o, "Expected object of " + c.getName() + " but got a null value"); + assertTrue(c.isInstance(o), "Expected " + c.getName() + " but got " + o.getClass().getName()); + } + return clazz.cast(o); + } + + public static void assertValue(IValue value, long expectedValue) { + assertNotNull(value); + assertTrue(value.numberValue() instanceof Long); + assertEquals(expectedValue, value.numberValue().longValue()); + } + + public static void assertVariableValue(IVariable var, long expectedValue) { + assertValue(var.getInitialValue(), expectedValue); + } + + public static String formatForPrinting(IASTName name) { + String signature = name.getRawSignature(); + boolean saved = CPPASTNameBase.sAllowNameComputation; + CPPASTNameBase.sAllowNameComputation = true; + try { + String nameStr = name.toString(); + if (signature.replace(" ", "").equals(nameStr.replace(" ", ""))) + return signature; + return nameStr + " in " + signature; + } catch (Throwable e) { + return signature; + } finally { + CPPASTNameBase.sAllowNameComputation = saved; + } + } + + // These methods help migrate from JUnit3 to JUnit5 version by providing errors as early as possible + // in the migration cycle + + public BaseTestCase5() { + // This constructor is expected to be called + } + + /** + * This JUnit3 style constructor is not supported. + */ + private BaseTestCase5(String name) { + fail("Test not migrated properly to JUnit5 yet."); + } + + /** + * This method is declared as final to help transition to JUnit5 to ensure that + * accidental override of the method is not left in subclasses when migrating. + */ + final protected void setUp() { + fail("Test not migrated properly to JUnit5 yet."); + } + + /** + * This method is declared as final to help transition to JUnit5 to ensure that + * accidental override of the method is not left in subclasses when migrating. + */ + final protected void tearDown() { + fail("Test not migrated properly to JUnit5 yet."); + } + + /** + * This method is declared as final to help transition to JUnit5 to ensure that + * accidental override of the method is not left in subclasses when migrating. + */ + final protected void runBare() { + fail("Test not migrated properly to JUnit5 yet."); + } + + /** + * This method is declared as final to help transition to JUnit5 to ensure that + * accidental override of the method is not left in subclasses when migrating. + */ + final protected void run(TestResult result) { + fail("Test not migrated properly to JUnit5 yet."); + } + + /** + * This method is declared as final to help transition to JUnit5 to ensure that + * accidental override of the method is not left in subclasses when migrating. + */ + final protected void runTest() throws Throwable { + fail("Test not migrated properly to JUnit5 yet."); + } + + /** + * Setting expected failures in this way is not support with the BaseTestCase5. If this + * is functionality that is needed, please find a new way to do it. + */ + public void setExpectFailure(int bugNumber) { + fail("Test not migrated properly to JUnit5 yet."); + } + +} diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/LogMonitoring.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/LogMonitoring.java new file mode 100644 index 00000000000..88b630230d3 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/LogMonitoring.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cdt.core.testplugin.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.runtime.ILogListener; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; + +import junit.framework.AssertionFailedError; + +class LogMonitoring { + + private List statusLog; + + private ILogListener logListener; + + private CCorePlugin corePlugin; + + void start() { + statusLog = Collections.synchronizedList(new ArrayList()); + logListener = new ILogListener() { + @Override + public void logging(IStatus status, String plugin) { + if (!status.isOK() && status.getSeverity() != IStatus.INFO) { + switch (status.getCode()) { + case IResourceStatus.NOT_FOUND_LOCAL: + case IResourceStatus.NO_LOCATION_LOCAL: + case IResourceStatus.FAILED_READ_LOCAL: + case IResourceStatus.RESOURCE_NOT_LOCAL: + // Logged by the resources plugin. + return; + } + statusLog.add(status); + } + } + }; + corePlugin = CCorePlugin.getDefault(); + if (corePlugin != null) { // Iff we don't run as a JUnit Plugin Test. + corePlugin.getLog().addLogListener(logListener); + } + + } + + void stop(int expectedLoggedNonOK) { + if (statusLog.size() != expectedLoggedNonOK) { + StringBuilder msg = new StringBuilder("Expected number (").append(expectedLoggedNonOK).append(") of "); + msg.append("Non-OK status objects in log differs from actual (").append(statusLog.size()).append(").\n"); + Throwable cause = null; + if (!statusLog.isEmpty()) { + synchronized (statusLog) { + for (IStatus status : statusLog) { + IStatus[] ss = { status }; + ss = status instanceof MultiStatus ? ((MultiStatus) status).getChildren() : ss; + for (IStatus s : ss) { + msg.append('\t').append(s.getMessage()).append(' '); + + Throwable t = s.getException(); + cause = cause != null ? cause : t; + if (t != null) { + msg.append(t.getMessage() != null ? t.getMessage() : t.getClass().getCanonicalName()); + } + + msg.append("\n"); + } + } + } + } + AssertionFailedError afe = new AssertionFailedError(msg.toString()); + afe.initCause(cause); + throw afe; + } + if (corePlugin != null) { + corePlugin.getLog().removeLogListener(logListener); + } + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/ModelJoiner.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/ModelJoiner.java new file mode 100644 index 00000000000..189544d6bae --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/ModelJoiner.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2006, 2016 Wind River Systems, Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Markus Schorn - initial API and implementation + * Andrew Ferguson (Symbian) + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.core.testplugin.util; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.core.runtime.CoreException; + +/** + * Some test steps need synchronizing against a CModel event. This class + * is a very basic means of doing that. + */ +public class ModelJoiner implements IElementChangedListener { + private final boolean[] changed = new boolean[1]; + + public ModelJoiner() { + CoreModel.getDefault().addElementChangedListener(this); + } + + public void clear() { + synchronized (changed) { + changed[0] = false; + changed.notifyAll(); + } + } + + public void join() throws CoreException { + try { + synchronized (changed) { + while (!changed[0]) { + changed.wait(); + } + } + } catch (InterruptedException e) { + throw new CoreException(CCorePlugin.createStatus("Interrupted", e)); + } + } + + public void dispose() { + CoreModel.getDefault().removeElementChangedListener(this); + } + + @Override + public void elementChanged(ElementChangedEvent event) { + // Only respond to post change events + if (event.getType() != ElementChangedEvent.POST_CHANGE) + return; + + synchronized (changed) { + changed[0] = true; + changed.notifyAll(); + } + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/UITestCaseWithProject.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/UITestCaseWithProject.java index e2b01844a5c..15db270316e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/UITestCaseWithProject.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/UITestCaseWithProject.java @@ -27,6 +27,7 @@ import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.FileManager; +import org.eclipse.cdt.core.testplugin.util.ModelJoiner; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource;