Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Johnston2014-03-12 21:25:54 +0000
committerAlexander Kurtakov2014-04-05 05:51:56 +0000
commitd42f1aa8fc3ef77ee436f65da8b38c1023f234ac (patch)
tree9bee07651e3c5032048cc7bbf912eef92c75188a /libhover/org.eclipse.linuxtools.cdt.libhover.tests
parent4f497bdc9479160a8be9a3f1eefdae4d7b9dfbc1 (diff)
downloadorg.eclipse.linuxtools-d42f1aa8fc3ef77ee436f65da8b38c1023f234ac.tar.gz
org.eclipse.linuxtools-d42f1aa8fc3ef77ee436f65da8b38c1023f234ac.tar.xz
org.eclipse.linuxtools-d42f1aa8fc3ef77ee436f65da8b38c1023f234ac.zip
Fix for Bug 428037 - Libhover doesn't respect qualified names
- Added check for C++ and then if it is a completion context, if the location is qualified Change-Id: Id55d78f9fa944066e4f457338038077078db021c Reviewed-on: https://git.eclipse.org/r/23282 Tested-by: Hudson CI Reviewed-by: Torbjörn Svensson <azoff@svenskalinuxforeningen.se> Reviewed-by: Alexander Kurtakov <akurtako@redhat.com> IP-Clean: Alexander Kurtakov <akurtako@redhat.com> Tested-by: Alexander Kurtakov <akurtako@redhat.com>
Diffstat (limited to 'libhover/org.eclipse.linuxtools.cdt.libhover.tests')
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/.classpath7
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/.gitignore2
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/.project28
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/META-INF/MANIFEST.MF20
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/about.html28
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/build.properties5
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/pom.xml47
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseTestCase.java323
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseUITestCase.java355
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/CProjectHelper.java448
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ContentAssistTests.java312
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ResourceHelper.java745
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestCfgDataProvider.java68
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerInfo.java58
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerProvider.java47
-rw-r--r--libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestSourceReader.java405
17 files changed, 2905 insertions, 0 deletions
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.classpath b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.classpath
new file mode 100644
index 0000000000..098194ca4b
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.gitignore b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.gitignore
new file mode 100644
index 0000000000..934e0e06ff
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/target
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.project b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.project
new file mode 100644
index 0000000000..007a253318
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.linuxtools.cdt.libhover.tests</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.settings/org.eclipse.jdt.core.prefs b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..f42de363af
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/META-INF/MANIFEST.MF b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..2e61baacb7
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Tests
+Bundle-SymbolicName: org.eclipse.linuxtools.cdt.libhover.tests
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Require-Bundle: org.eclipse.cdt.core;bundle-version="5.7.0",
+ org.eclipse.swt;bundle-version="3.103.0",
+ org.eclipse.core.commands;bundle-version="3.6.100",
+ org.eclipse.core.resources;bundle-version="3.9.0",
+ org.eclipse.core.runtime;bundle-version="3.10.0",
+ org.eclipse.ui;bundle-version="3.106.0",
+ org.eclipse.cdt.ui;bundle-version="5.8.0",
+ org.junit;bundle-version="4.11.0",
+ org.eclipse.jface.text;bundle-version="3.9.0",
+ org.eclipse.ui.ide;bundle-version="3.10.0",
+ org.eclipse.ui.workbench.texteditor;bundle-version="3.9.0",
+ org.eclipse.ui.editors;bundle-version="3.8.100",
+ org.eclipse.linuxtools.cdt.libhover;bundle-version="1.2.0",
+ org.eclipse.linuxtools.cdt.libhover.glibc;bundle-version="1.2.0"
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/about.html b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/about.html
new file mode 100644
index 0000000000..c258ef55d8
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/build.properties b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/build.properties
new file mode 100644
index 0000000000..17daa5b49c
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ about.html
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/pom.xml b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/pom.xml
new file mode 100644
index 0000000000..9794f34852
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2014, Red Hat, Inc.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>linuxtools-libhover-parent</artifactId>
+ <groupId>org.eclipse.linuxtools.cdt.libhover</groupId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.linuxtools.cdt.libhover.tests</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>eclipse-test-plugin</packaging>
+
+ <name>Linux Tools Libhover Core Tests Plug-in</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-surefire-plugin</artifactId>
+ <version>${tycho-version}</version>
+ <configuration>
+ <excludes>
+ <!-- test mojo matches TestProject be default and treats it as PojoTest -->
+ <exclude>**/Test*.class</exclude>
+ </excludes>
+ <testSuite>org.eclipse.linuxtools.cdt.libhover.tests</testSuite>
+ <testClass>org.eclipse.linuxtools.cdt.libhover.tests.ContentAssistTests</testClass>
+ <useUIHarness>true</useUIHarness>
+ <useUIThread>true</useUIThread>
+ <product>org.eclipse.platform.ide</product>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseTestCase.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseTestCase.java
new file mode 100644
index 0000000000..db87e6384d
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseTestCase.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2013 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Markus Schorn - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestFailure;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.CCorePlugin;
+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.internal.core.CCoreInternals;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
+import org.eclipse.cdt.internal.core.pdom.CModelListener;
+import org.eclipse.cdt.internal.core.pdom.PDOMManager;
+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;
+
+@SuppressWarnings("restriction")
+public class BaseTestCase extends TestCase {
+ private static final String DEFAULT_INDEXER_TIMEOUT_SEC = "10";
+ private 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;
+
+ private boolean fExpectFailure;
+ private int fBugNumber;
+ private int fExpectedLoggedNonOK;
+
+ public BaseTestCase() {
+ super();
+ }
+
+ public BaseTestCase(String name) {
+ super(name);
+ }
+
+ public static NullProgressMonitor npm() {
+ return new NullProgressMonitor();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ CPPASTNameBase.sAllowRecursionBindings= false;
+ CPPASTNameBase.sAllowNameComputation= false;
+ CModelListener.sSuppressUpdateOfLastRecentlyUsed= true;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ ResourceHelper.cleanUp();
+ TestScannerProvider.clear();
+ }
+
+ protected static TestSuite suite(Class<?> clazz) {
+ return suite(clazz, null);
+ }
+
+ protected static TestSuite suite(Class<?> clazz, String failingTestPrefix) {
+ TestSuite suite= new TestSuite(clazz);
+ Test failing= getFailingTests(clazz, failingTestPrefix);
+ if (failing != null) {
+ suite.addTest(failing);
+ }
+ return suite;
+ }
+
+ private static Test getFailingTests(Class<?> clazz, String prefix) {
+ TestSuite suite= new TestSuite("Failing Tests");
+ HashSet<String> names= new HashSet<String>();
+ Class<?> superClass= clazz;
+ while (Test.class.isAssignableFrom(superClass) && !TestCase.class.equals(superClass)) {
+ Method[] methods= superClass.getDeclaredMethods();
+ for (Method method : methods) {
+ addFailingMethod(suite, method, names, clazz, prefix);
+ }
+ superClass= superClass.getSuperclass();
+ }
+ if (suite.countTestCases() == 0) {
+ return null;
+ }
+ return suite;
+ }
+
+ private static void addFailingMethod(TestSuite suite, Method m, Set<String> names, Class<?> clazz, String prefix) {
+ String name= m.getName();
+ if (!names.add(name)) {
+ return;
+ }
+ if (name.startsWith("test") || (prefix != null && !name.startsWith(prefix))) {
+ return;
+ }
+ if (name.equals("tearDown") || name.equals("setUp") || name.equals("runBare")) {
+ return;
+ }
+ if (Modifier.isPublic(m.getModifiers())) {
+ @SuppressWarnings("rawtypes")
+ Class[] parameters= m.getParameterTypes();
+ Class<?> returnType= m.getReturnType();
+ if (parameters.length == 0 && returnType.equals(Void.TYPE)) {
+ Test test= TestSuite.createTest(clazz, name);
+ ((BaseTestCase) test).setExpectFailure(0);
+ suite.addTest(test);
+ }
+ }
+ }
+
+ @Override
+ public void runBare() throws Throwable {
+ final List<IStatus> statusLog= Collections.synchronizedList(new ArrayList<IStatus>());
+ 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) { //Iif we don't run a JUnit Plugin Test
+ corePlugin.getLog().addLogListener(logListener);
+ }
+
+ Throwable testThrowable= null;
+ try {
+ try {
+ super.runBare();
+ } catch (Throwable e) {
+ testThrowable= e;
+ }
+
+ if (statusLog.size() != fExpectedLoggedNonOK) {
+ StringBuffer msg= new StringBuffer("Expected number (" + fExpectedLoggedNonOK + ") of ");
+ msg.append("non-OK status objects in log differs from actual (" + statusLog.size() + ").\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" + s.getMessage() + " ");
+
+ 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;
+ }
+ } finally {
+ if (corePlugin != null) {
+ corePlugin.getLog().removeLogListener(logListener);
+ }
+ }
+
+ if (testThrowable != null)
+ throw testThrowable;
+ }
+
+ @Override
+ public void run(TestResult result) {
+ if (!fExpectFailure || "true".equals(System.getProperty("SHOW_EXPECTED_FAILURES"))) {
+ super.run(result);
+ return;
+ }
+
+ result.startTest(this);
+
+ TestResult r = new TestResult();
+ super.run(r);
+ if (r.failureCount() == 1) {
+ TestFailure failure= r.failures().nextElement();
+ String msg= failure.exceptionMessage();
+ if (msg != null && msg.startsWith("Method \"" + getName() + "\"")) {
+ result.addFailure(this, new AssertionFailedError(msg));
+ }
+ } else if (r.errorCount() == 0 && r.failureCount() == 0) {
+ String err = "Unexpected success of " + getName();
+ if (fBugNumber > 0) {
+ err += ", bug #" + fBugNumber;
+ }
+ result.addFailure(this, new AssertionFailedError(err));
+ }
+
+ result.endTest(this);
+ }
+
+ public void setExpectFailure(int bugNumber) {
+ fExpectFailure= true;
+ fBugNumber= bugNumber;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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);
+
+ final PDOMManager indexManager = CCoreInternals.getPDOMManager();
+ assertTrue(indexManager.joinIndexer(INDEXER_TIMEOUT_SEC * 1000, npm()));
+ long waitms= 1;
+ while (waitms < 2000 && !indexManager.isProjectRegistered(project)) {
+ Thread.sleep(waitms);
+ waitms *= 2;
+ }
+ assertTrue(indexManager.isProjectRegistered(project));
+ assertTrue(indexManager.joinIndexer(INDEXER_TIMEOUT_SEC * 1000, npm()));
+ }
+
+ public static void waitUntilFileIsIndexed(IIndex index, IFile file) throws Exception {
+ TestSourceReader.waitUntilFileIsIndexed(index, file, INDEXER_TIMEOUT_SEC * 1000);
+ }
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseUITestCase.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseUITestCase.java
new file mode 100644
index 0000000000..7a23b046c8
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/BaseUITestCase.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Markus Schorn - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.utils.Platform;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.NotEnabledException;
+import org.eclipse.core.commands.NotHandledException;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.internal.WorkbenchPartReference;
+
+@SuppressWarnings("restriction")
+public class BaseUITestCase extends BaseTestCase {
+
+ public BaseUITestCase() {
+ super();
+ }
+
+ public BaseUITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IViewPart view= activePage.findView("org.eclipse.cdt.ui.tests.DOMAST.DOMAST");
+ if (view != null) {
+ activePage.hideView(view);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ runEventQueue(0);
+ super.tearDown();
+ }
+
+ /**
+ * Reads a section in comments form the source of the given class. Fully
+ * equivalent to <code>readTaggedComment(getClass(), tag)</code>
+ * @since 4.0
+ */
+ protected String readTaggedComment(final String tag) throws IOException {
+ return TestSourceReader.readTaggedComment(Platform.getBundle(CProjectHelper.PLUGIN_ID), "ui", getClass(), tag);
+ }
+
+ /**
+ * Reads multiple sections in comments from the source of the given class.
+ * @since 4.0
+ */
+ public StringBuilder[] getContentsForTest(int sections) throws IOException {
+ return TestSourceReader.getContentsForTest(Platform.getBundle(CProjectHelper.PLUGIN_ID), "ui",
+ getClass(), getName(), sections);
+ }
+
+ public String getAboveComment() throws IOException {
+ return getContentsForTest(1)[0].toString();
+ }
+
+ protected IFile createFile(IContainer container, String fileName, String contents) throws Exception {
+ return TestSourceReader.createFile(container, new Path(fileName), contents);
+ }
+
+ protected IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
+ return TestSourceReader.createIndexBasedAST(index, project, file);
+ }
+
+ protected void runEventQueue(int time) {
+ final long endTime= System.currentTimeMillis() + time;
+ while (true) {
+ while (Display.getCurrent().readAndDispatch())
+ ;
+ long diff= endTime - System.currentTimeMillis();
+ if (diff <= 0) {
+ break;
+ }
+ try {
+ Thread.sleep(Math.min(20, diff));
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ }
+
+ protected void expandTreeItem(Tree tree, int idx) {
+ expandTreeItem(tree, new int[] { idx });
+ }
+
+ protected void expandTreeItem(Tree tree, int idx1, int idx2) {
+ expandTreeItem(tree, new int[] { idx1, idx2 });
+ }
+
+ protected void expandTreeItem(Tree tree, int[] idxs) {
+ TreeItem item= tree.getItem(idxs[0]);
+ assertNotNull(item);
+ expandTreeItem(item);
+ for (int i= 1; i < idxs.length; i++) {
+ item= item.getItem(idxs[i]);
+ assertNotNull(item);
+ expandTreeItem(item);
+ }
+ }
+
+ protected void expandTreeItem(TreeItem item) {
+ Event event = new Event();
+ event.item = item;
+ item.getParent().notifyListeners(SWT.Expand, event);
+ item.setExpanded(true);
+ runEventQueue(0);
+ }
+
+ protected void selectTreeItem(Tree tree, int idx) {
+ selectTreeItem(tree, new int[] {idx});
+ }
+
+ protected void selectTreeItem(Tree tree, int idx1, int idx2) {
+ selectTreeItem(tree, new int[] {idx1, idx2});
+ }
+
+ protected void selectTreeItem(Tree tree, int[] idxs) {
+ TreeItem item= tree.getItem(idxs[0]);
+ assertNotNull(item);
+ for (int i= 1; i < idxs.length; i++) {
+ item= item.getItem(idxs[i]);
+ assertNotNull(item);
+ }
+ tree.setSelection(item);
+ Event event = new Event();
+ event.item = item;
+ item.getParent().notifyListeners(SWT.Selection, event);
+ runEventQueue(0);
+ }
+
+ protected void closeEditor(IEditorPart editor) {
+ IWorkbenchPartSite site;
+ IWorkbenchPage page;
+ if (editor != null && (site= editor.getSite()) != null && (page= site.getPage()) != null) {
+ page.closeEditor(editor, false);
+ }
+ }
+
+ protected void closeAllEditors() {
+ IWorkbenchWindow[] windows= PlatformUI.getWorkbench().getWorkbenchWindows();
+ for (IWorkbenchWindow window : windows) {
+ IWorkbenchPage[] pages= window.getPages();
+ for (IWorkbenchPage page : pages) {
+ page.closeAllEditors(false);
+ }
+ }
+ }
+
+ protected void restoreAllParts() throws WorkbenchException {
+ IWorkbenchPage page= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ page.zoomOut();
+ runEventQueue(0);
+
+ IViewReference[] viewRefs= page.getViewReferences();
+ for (IViewReference ref : viewRefs) {
+ page.setPartState(ref, IWorkbenchPage.STATE_RESTORED);
+ }
+ IEditorReference[] editorRefs= page.getEditorReferences();
+ for (IEditorReference ref : editorRefs) {
+ page.setPartState(ref, IWorkbenchPage.STATE_RESTORED);
+ }
+ runEventQueue(0);
+ }
+
+ protected IViewPart activateView(String id) throws PartInitException {
+ IViewPart view= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(id);
+ assertNotNull(view);
+ runEventQueue(0);
+ return view;
+ }
+
+ protected void executeCommand(IViewPart viewPart, String commandID) throws ExecutionException, NotDefinedException, NotEnabledException, NotHandledException {
+ IHandlerService hs= (IHandlerService)viewPart.getSite().getService(IHandlerService.class);
+ assertNotNull(hs);
+ hs.executeCommand(commandID, null);
+ }
+
+ private Control[] findControls(Control w, Class<?> clazz) {
+ ArrayList<Control> result= new ArrayList<Control>();
+ findControls(w, clazz, result);
+ return result.toArray(new Control[result.size()]);
+ }
+
+ private void findControls(Control w, Class<?> clazz, List<Control> result) {
+ if (clazz.isInstance(w)) {
+ result.add(w);
+ }
+ if (w instanceof Composite) {
+ Composite comp= (Composite) w;
+ Control[] children= comp.getChildren();
+ for (Control element : children) {
+ findControls(element, clazz, result);
+ }
+ }
+ }
+
+ final protected TreeItem checkTreeNode(IViewPart part, int i0, String label) {
+ assertNotNull(label); // we don't handle testing for a base node to not appear; can be added if/when needed
+ IViewReference viewRef = part.getViewSite().getPage().findViewReference(part.getViewSite().getId());
+ Control viewControl = ((WorkbenchPartReference) viewRef).getPane().getControl();
+
+ Tree tree= null;
+ TreeItem root= null;
+ StringBuilder cands= new StringBuilder();
+ for (int i= 0; i < 400; i++) {
+ cands.setLength(0);
+ Control[] trees= findControls(viewControl, Tree.class);
+ for (int j = 0; j < trees.length; j++) {
+ try {
+ tree= (Tree) trees[j];
+ root= tree.getItem(i0);
+ if (label.equals(root.getText())) {
+ return root;
+ }
+ if (j > 0) {
+ cands.append('|');
+ }
+ cands.append(root.getText());
+ } catch (SWTException e) {
+ // in case widget was disposed, item may be replaced
+ } catch (IllegalArgumentException e) {
+ // item does not yet exist.
+ }
+ }
+ runEventQueue(10);
+ }
+ assertNotNull("No tree in viewpart", tree);
+ assertNotNull("Tree node " + label + "{" + i0 + "} does not exist!", root);
+ assertEquals(label, cands.toString());
+ return root;
+ }
+
+ final protected TreeItem checkTreeNode(Tree tree, int i0, String label) {
+ assertNotNull(label); // we don't handle testing for a base node to not appear; can be added if/when needed
+ TreeItem root= null;
+ for (int millis= 0; millis < 5000; millis= millis == 0 ? 1 : millis * 2) {
+ runEventQueue(millis);
+ try {
+ root= tree.getItem(i0);
+ if (label.equals(root.getText())) {
+ return root;
+ }
+ } catch (SWTException e) {
+ // in case widget was disposed, item may be replaced
+ } catch (IllegalArgumentException e) {
+ // item does not yet exist.
+ }
+ }
+ fail("Tree node " + label + "{" + i0 + "} does not exist!");
+ return null;
+ }
+
+ /**
+ * Pass label=null to test that the {i0,i1} node doesn't exist
+ */
+ final protected TreeItem checkTreeNode(Tree tree, int i0, int i1, String label) {
+ String firstItemText= null;
+ int timeout = (label == null) ? 1000 : 5000; // see footnote[0]
+
+ // If {i0,i1} exists, whether or not it matches label (when label != null)
+ boolean nodePresent = false;
+
+ for (int millis= 0; millis < timeout; millis= millis == 0 ? 1 : millis * 2) {
+ nodePresent = false;
+ runEventQueue(millis);
+ TreeItem i0Node= tree.getItem(i0);
+ if (!i0Node.getExpanded()) {
+ expandTreeItem(i0Node);
+ }
+ try {
+ TreeItem firstItem= i0Node.getItem(0);
+ firstItemText= firstItem.getText();
+ if (firstItemText.length() > 0 && !firstItemText.equals("...")) {
+ TreeItem item = i0Node.getItem(i1);
+ nodePresent = true;
+ if (label != null && label.equals(item.getText())) {
+ return item;
+ }
+ }
+ } catch (SWTException e) {
+ // in case widget was disposed, item may be replaced
+ } catch (IllegalArgumentException e) {
+ // item does not yet exist.
+ }
+ }
+
+ if (label == null) {
+ assertFalse("Tree node {" + i0 + "," + i1 + "} exists but shouldn't!", nodePresent);
+ } else {
+ fail("Tree node " + label + "{" + i0 + "," + i1 + "} does not exist!");
+ }
+ return null;
+ }
+
+ public static void assertEqualString(String actual, String expected) {
+ assertEqualString(actual, expected);
+ }
+}
+
+// Footnotes
+// [0] Waiting for something to appear is very efficient; waiting for it to not
+// appear is very inefficient. In the former case, regardless of how much time
+// is alloted, we stop waiting as soon as the item appears, whereas in the
+// latter we have to wait the entire timeout. In test suites with thousands of
+// tests, efficiency is critical. Thus, in testing that a tree node doesn't have
+// an Nth child, we shoot for efficiency and accept the risk of a false
+// negative. More specifically, we wait only one second for the item TO NOT
+// appear, whereas we give an item up to five seconds TO appear. This compromise
+// is better than not having that sort of test at all, which some would argue is
+// the better approach. In practice, it takes about 60-150 ms for the item to
+// appear (on my machine), but we give it up to five seconds. Waiting one second
+// for it to not appear should be more than adequate
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/CProjectHelper.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/CProjectHelper.java
new file mode 100644
index 0000000000..7ba4763d21
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/CProjectHelper.java
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Markus Schorn (Wind River Systems)
+ * Anton Leherbauer (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.zip.ZipFile;
+
+import static org.junit.Assert.*;
+
+import org.eclipse.cdt.core.CCProjectNature;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CProjectNature;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.IArchive;
+import org.eclipse.cdt.core.model.IArchiveContainer;
+import org.eclipse.cdt.core.model.IBinary;
+import org.eclipse.cdt.core.model.IBinaryContainer;
+import org.eclipse.cdt.core.model.ICContainer;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ISourceRoot;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
+import org.eclipse.cdt.core.settings.model.util.CDataUtil;
+import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
+import org.osgi.framework.Bundle;
+/**
+ * Helper methods to set up a ICProject.
+ */
+@SuppressWarnings("restriction")
+public class CProjectHelper {
+
+ public final static String PLUGIN_ID = "org.eclipse.linuxtools.cdt.libhover.tests"; //$NON-NLS-1$
+
+ private final static IOverwriteQuery OVERWRITE_QUERY= new IOverwriteQuery() {
+ @Override
+ public String queryOverwrite(String file) {
+ return ALL;
+ }
+ };
+
+ public static ICProject createCProject(final String projectName, String binFolderName) throws CoreException {
+ return createCCProject(projectName, binFolderName, null);
+ }
+
+ /**
+ * Creates a ICProject.
+ */
+ public static ICProject createCProject(final String projectName, String binFolderName, final String indexerID) throws CoreException {
+ final IWorkspace ws = ResourcesPlugin.getWorkspace();
+ final ICProject newProject[] = new ICProject[1];
+ ws.run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IWorkspaceRoot root = ws.getRoot();
+ IProject project = root.getProject(projectName);
+ if (indexerID != null) {
+ IndexerPreferences.set(project, IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, "true");
+ IndexerPreferences.set(project, IndexerPreferences.KEY_INDEXER_ID, indexerID);
+ }
+ if (!project.exists()) {
+ project.create(null);
+ } else {
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ }
+ if (!project.isOpen()) {
+ project.open(null);
+ }
+ if (!project.hasNature(CProjectNature.C_NATURE_ID)) {
+ String projectId = PLUGIN_ID + ".TestProject";
+ addNatureToProject(project, CProjectNature.C_NATURE_ID, null);
+ CCorePlugin.getDefault().mapCProjectOwner(project, projectId, false);
+ }
+ addDefaultBinaryParser(project);
+ newProject[0] = CCorePlugin.getDefault().getCoreModel().create(project);
+ }
+ }, null);
+
+ return newProject[0];
+ }
+
+ /**
+ * Add the default binary parser if no binary parser configured.
+ *
+ * @param project
+ * @throws CoreException
+ */
+ public static boolean addDefaultBinaryParser(IProject project) throws CoreException {
+ ICConfigExtensionReference[] binaryParsers= CCorePlugin.getDefault().getDefaultBinaryParserExtensions(project);
+ if (binaryParsers == null || binaryParsers.length == 0) {
+ ICProjectDescription desc= CCorePlugin.getDefault().getProjectDescription(project);
+ if (desc == null) {
+ return false;
+ }
+
+ desc.getDefaultSettingConfiguration().create(CCorePlugin.BINARY_PARSER_UNIQ_ID, CCorePlugin.DEFAULT_BINARY_PARSER_UNIQ_ID);
+ CCorePlugin.getDefault().setProjectDescription(project, desc);
+ }
+ return true;
+ }
+
+ /**
+ * Creates a ICProject.
+ */
+ public static ICProject createNewStileCProject(final String projectName, final String indexerID) throws CoreException {
+ return createNewStileCProject(projectName, indexerID, false);
+ }
+
+ /**
+ * Creates a ICProject.
+ */
+ public static ICProject createNewStileCProject(final String projectName, String providerId, final String indexerID) throws CoreException {
+ return createNewStileCProject(projectName, providerId, indexerID, false);
+ }
+
+ /**
+ * Creates a ICProject.
+ */
+ public static ICProject createNewStileCProject(final String projectName, final String indexerID, boolean markCreating) throws CoreException {
+ return createNewStileCProject(projectName, null, indexerID, markCreating);
+ }
+
+ /**
+ * Creates a ICProject.
+ */
+ public static ICProject createNewStileCProject(final String projectName, String cfgProviderId, final String indexerID, final boolean markCreating) throws CoreException {
+ final IWorkspace ws = ResourcesPlugin.getWorkspace();
+ final ICProject newProject[] = new ICProject[1];
+ if(cfgProviderId == null)
+ cfgProviderId = TestCfgDataProvider.PROVIDER_ID;
+
+ final String finalCfgProviderId = cfgProviderId;
+ ws.run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IWorkspaceRoot root = ws.getRoot();
+ IProject project = root.getProject(projectName);
+ if (indexerID != null) {
+ IndexerPreferences.set(project, IndexerPreferences.KEY_INDEXER_ID, indexerID);
+ }
+ if (!project.exists()) {
+ project.create(null);
+ } else {
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ }
+ if (!project.isOpen()) {
+ project.open(null);
+ }
+ if (!project.hasNature(CProjectNature.C_NATURE_ID)) {
+ addNatureToProject(project, CProjectNature.C_NATURE_ID, null);
+ ICConfigurationDescription prefCfg = CCorePlugin.getDefault().getPreferenceConfiguration(finalCfgProviderId);
+ ICProjectDescriptionManager mngr = CCorePlugin.getDefault().getProjectDescriptionManager();
+ ICProjectDescription projDes = mngr.createProjectDescription(project, false, markCreating);
+ projDes.createConfiguration(CDataUtil.genId(null), CDataUtil.genId("test"), prefCfg);
+ mngr.setProjectDescription(project, projDes);
+// CCorePlugin.getDefault().mapCProjectOwner(project, projectId, false);
+ }
+ addDefaultBinaryParser(project);
+ newProject[0] = CCorePlugin.getDefault().getCoreModel().create(project);
+ }
+ }, null);
+
+ return newProject[0];
+ }
+
+
+ private static String getMessage(IStatus status) {
+ StringBuffer message = new StringBuffer("[");
+ message.append(status.getMessage());
+ if (status.isMultiStatus()) {
+ IStatus children[] = status.getChildren();
+ for( int i = 0; i < children.length; i++) {
+ message.append(getMessage(children[i]));
+ }
+ }
+ message.append("]");
+ return message.toString();
+ }
+
+ public static ICProject createCCProject(final String projectName, final String binFolderName) throws CoreException {
+ return createCCProject(projectName, binFolderName, null);
+ }
+
+ public static ICProject createCCProject(final String projectName, final String binFolderName, final String indexerID) throws CoreException {
+ final IWorkspace ws = ResourcesPlugin.getWorkspace();
+ final ICProject newProject[] = new ICProject[1];
+ ws.run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ ICProject cproject = createCProject(projectName, binFolderName, indexerID);
+ if (!cproject.getProject().hasNature(CCProjectNature.CC_NATURE_ID)) {
+ addNatureToProject(cproject.getProject(), CCProjectNature.CC_NATURE_ID, null);
+ }
+ newProject[0] = cproject;
+ }
+ }, null);
+ return newProject[0];
+ }
+
+ /**
+ * Removes a ICProject.
+ */
+ public static void delete(ICProject cproject) {
+ try {
+ cproject.getProject().delete(true, true, null);
+ } catch (CoreException e) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e1) {
+ } finally {
+ try {
+ System.gc();
+ System.runFinalization();
+ cproject.getProject().delete(true, true, null);
+ } catch (CoreException e2) {
+ fail(getMessage(e2.getStatus()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a folder container to a ICProject.
+ */
+ public static ICContainer addCContainer(ICProject cproject, String containerName) throws CoreException {
+ IProject project = cproject.getProject();
+ ICContainer container = null;
+ if (containerName == null || containerName.length() == 0) {
+ ICContainer[] conts = cproject.getSourceRoots();
+ if (conts.length > 0) {
+ container = conts[0];
+ }
+ } else {
+ IFolder folder = project.getFolder(containerName);
+ if (!folder.exists()) {
+ folder.create(false, true, null);
+ }
+ container = CoreModel.getDefault().create(folder);
+ }
+ return container;
+ }
+
+ /**
+ * Adds a folder container to a ICProject and imports all files contained in the given Zip file.
+ */
+ public static ICContainer addCContainerWithImport(ICProject cproject, String containerName, ZipFile zipFile)
+ throws InvocationTargetException, CoreException {
+ ICContainer root = addCContainer(cproject, containerName);
+ importFilesFromZip(zipFile, root.getPath(), null);
+ return root;
+ }
+
+ /**
+ * Removes a folder from a ICProject.
+ */
+ public static void removeCContainer(ICProject cproject, String containerName) throws CoreException {
+ IFolder folder = cproject.getProject().getFolder(containerName);
+ folder.delete(true, null);
+ }
+
+ /**
+ * Attempts to find an archive with the given name in the workspace
+ */
+ public static IArchive findArchive(ICProject testProject, String name) throws CModelException {
+ int x;
+ IArchive[] myArchives;
+ IArchiveContainer archCont;
+ /***************************************************************************************************************************
+ * Since ArchiveContainer.getArchives does not wait until all the archives in the project have been parsed before returning
+ * the list, we have to do a sync ArchiveContainer.getChildren first to make sure we find all the archives.
+ */
+ archCont = testProject.getArchiveContainer();
+ myArchives = archCont.getArchives();
+ if (myArchives.length < 1)
+ return null;
+ for (x = 0; x < myArchives.length; x++) {
+ if (myArchives[x].getElementName().equals(name))
+ return (myArchives[x]);
+ }
+ return null;
+ }
+
+ /**
+ * Attempts to find a binary with the given name in the workspace
+ */
+ public static IBinary findBinary(ICProject testProject, String name) throws CModelException {
+ IBinaryContainer binCont;
+ int x;
+ IBinary[] myBinaries;
+ binCont = testProject.getBinaryContainer();
+ myBinaries = binCont.getBinaries();
+ if (myBinaries.length < 1)
+ return null;
+ for (x = 0; x < myBinaries.length; x++) {
+ if (myBinaries[x].getElementName().equals(name))
+ return (myBinaries[x]);
+ }
+ return null;
+ }
+
+ /**
+ * Attempts to find an object with the given name in the workspace
+ */
+ public static IBinary findObject(ICProject testProject, String name) throws CModelException {
+ ICElement[] sourceRoots = testProject.getChildren();
+ for (int i = 0; i < sourceRoots.length; i++) {
+ ISourceRoot root = (ISourceRoot) sourceRoots[i];
+ ICElement[] myElements = root.getChildren();
+ for (int x = 0; x < myElements.length; x++) {
+ if (myElements[x].getElementName().equals(name)) {
+ if (myElements[x] instanceof IBinary) {
+ return ((IBinary) myElements[x]);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Attempts to find a TranslationUnit with the given name in the workspace
+ * @throws InterruptedException
+ */
+ public static ITranslationUnit findTranslationUnit(ICProject testProject, String name) throws CModelException, InterruptedException {
+ for (int j=0; j<20; j++) {
+ ICElement[] sourceRoots = testProject.getChildren();
+ for (int i = 0; i < sourceRoots.length; i++) {
+ ISourceRoot root = (ISourceRoot) sourceRoots[i];
+ ICElement[] myElements = root.getChildren();
+ for (int x = 0; x < myElements.length; x++) {
+ if (myElements[x].getElementName().equals(name)) {
+ if (myElements[x] instanceof ITranslationUnit) {
+ return ((ITranslationUnit) myElements[x]);
+ }
+ }
+ }
+ }
+ Thread.sleep(100);
+ }
+ return null;
+ }
+
+ /**
+ * Attempts to find an element with the given name in the workspace
+ */
+ public static ICElement findElement(ICProject testProject, String name) throws CModelException {
+ ICElement[] sourceRoots = testProject.getChildren();
+ for (int i = 0; i < sourceRoots.length; i++) {
+ ISourceRoot root = (ISourceRoot) sourceRoots[i];
+ ICElement[] myElements = root.getChildren();
+ for (int x = 0; x < myElements.length; x++) {
+ if (myElements[x].getElementName().equals(name)) {
+ return myElements[x];
+ }
+ }
+ }
+ return null;
+ }
+
+ public static void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException {
+ IProjectDescription description = proj.getDescription();
+ String[] prevNatures = description.getNatureIds();
+ String[] newNatures = new String[prevNatures.length + 1];
+ System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
+ newNatures[prevNatures.length] = natureId;
+ description.setNatureIds(newNatures);
+ proj.setDescription(description, monitor);
+ }
+
+ private static void importFilesFromZip(ZipFile srcZipFile, IPath destPath, IProgressMonitor monitor)
+ throws InvocationTargetException {
+ ZipFileStructureProvider structureProvider = new ZipFileStructureProvider(srcZipFile);
+ try {
+ ImportOperation op = new ImportOperation(destPath, structureProvider.getRoot(), structureProvider,
+ OVERWRITE_QUERY);
+ op.run(monitor);
+ } catch (InterruptedException e) {
+ // should not happen
+ }
+ }
+
+
+ public static void importSourcesFromPlugin(ICProject project, Bundle bundle, String sources) throws CoreException {
+ try {
+ String baseDir= FileLocator.toFileURL(FileLocator.find(bundle, new Path(sources), null)).getFile();
+ ImportOperation importOp = new ImportOperation(project.getProject().getFullPath(),
+ new File(baseDir), FileSystemStructureProvider.INSTANCE, OVERWRITE_QUERY);
+ importOp.setCreateContainerStructure(false);
+ importOp.run(new NullProgressMonitor());
+ }
+ catch (Exception e) {
+ throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, 0, "Import Interrupted", e));
+ }
+ }
+
+ /**
+ * @return the location of a newly created directory in temporary area.
+ * Note that cleanup should be done with {@link ResourceHelper#cleanUp()}.
+ * @throws IOException
+ * @throws CoreException
+ */
+ public static File freshDir() throws IOException, CoreException {
+ IPath folderPath = ResourceHelper.createTemporaryFolder();
+ File folder = new File(folderPath.toOSString());
+ assertTrue(folder.exists());
+ assertTrue(folder.isDirectory());
+ assertTrue(folder.canWrite());
+
+ return folder;
+ }
+} \ No newline at end of file
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ContentAssistTests.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ContentAssistTests.java
new file mode 100644
index 0000000000..7c70c8bfb4
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ContentAssistTests.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008, 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Markus Schorn (Wind River Systems)
+ * Red Hat Inc. - modified to test Linux Tools libhover
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.dom.IPDOMManager;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.internal.ui.CHelpProviderManager;
+import org.eclipse.cdt.internal.ui.editor.CEditor;
+import org.eclipse.cdt.internal.ui.text.CHelpBookDescriptor;
+import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
+import org.eclipse.cdt.ui.text.ICHelpInvocationContext;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+
+/**
+ * @author aniefer
+ */
+@SuppressWarnings("restriction")
+public class ContentAssistTests extends BaseUITestCase {
+ private final NullProgressMonitor monitor= new NullProgressMonitor();
+ static IProject project;
+ static ICProject cproject;
+ static boolean disabledHelpContributions = false;
+
+ @Override
+ public void setUp() throws InterruptedException {
+ //(CCorePlugin.getDefault().getCoreModel().getIndexManager()).reset();
+
+ if (project == null) {
+ try {
+ cproject = CProjectHelper.createCCProject("ContentAssistTestProject", "bin", IPDOMManager.ID_FAST_INDEXER); //$NON-NLS-1$ //$NON-NLS-2$
+ project = cproject.getProject();
+ waitForIndexer(cproject);
+ } catch ( CoreException e ) {
+ /*boo*/
+ }
+ if (project == null)
+ fail("Unable to create project"); //$NON-NLS-1$
+ }
+ }
+ public ContentAssistTests()
+ {
+ super();
+ }
+ /**
+ * @param name
+ */
+ public ContentAssistTests(String name)
+ {
+ super(name);
+ }
+
+ private void disableContributions (){
+ //disable the help books so we don't get proposals we weren't expecting
+ CHelpBookDescriptor helpBooks[];
+ helpBooks = CHelpProviderManager.getDefault().getCHelpBookDescriptors(new ICHelpInvocationContext(){
+ @Override
+ public IProject getProject(){return project;}
+ @Override
+ public ITranslationUnit getTranslationUnit(){return null;}
+ }
+ );
+ for (CHelpBookDescriptor helpBook : helpBooks) {
+ if( helpBook != null && !helpBook.getCHelpBook().getTitle().contains("glibc") ) //$NON-NLS-1$
+ helpBook.enable( false );
+ }
+ }
+
+ public static Test suite() {
+ TestSuite suite= suite(ContentAssistTests.class, "_");
+ suite.addTest( new ContentAssistTests("cleanupProject") ); //$NON-NLS-1$
+ return suite;
+ }
+
+ public void cleanupProject() throws Exception {
+ closeAllEditors();
+ try{
+ project.delete( true, false, monitor );
+ project = null;
+ } catch( Throwable e ){
+ /*boo*/
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if( project == null || !project.exists() )
+ return;
+
+ closeAllEditors();
+
+ // wait for indexer before deleting project to avoid errors in the log
+ waitForIndexer(cproject);
+
+ IResource [] members = project.members();
+ for (IResource member : members) {
+ if( member.getName().equals( ".project" ) || member.getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$
+ continue;
+ if (member.getName().equals(".settings"))
+ continue;
+ try{
+ member.delete( false, monitor );
+ } catch( Throwable e ){
+ /*boo*/
+ }
+ }
+
+ }
+
+ protected IFile importFile(String fileName, String contents ) throws Exception{
+ //Obtain file handle
+ IFile file = project.getProject().getFile(fileName);
+
+ InputStream stream = new ByteArrayInputStream( contents.getBytes() );
+ //Create file input stream
+ if( file.exists() )
+ file.setContents( stream, false, false, monitor );
+ else
+ file.create( stream, false, monitor );
+
+ return file;
+ }
+
+ protected ICompletionProposal[] getResults( IFile file, int offset ) throws Exception {
+ disableContributions();
+ ITranslationUnit tu = (ITranslationUnit)CoreModel.getDefault().create( file );
+ @SuppressWarnings("unused")
+ String buffer = tu.getBuffer().getContents();
+ @SuppressWarnings("unused")
+ IWorkingCopy wc = null;
+ try{
+ wc = tu.getWorkingCopy();
+ }catch (CModelException e){
+ fail("Failed to get working copy"); //$NON-NLS-1$
+ }
+
+ // call the ContentAssistProcessor
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ FileEditorInput editorInput = new FileEditorInput(file);
+ IEditorPart editorPart = page.openEditor(editorInput, "org.eclipse.cdt.ui.editor.CEditor");
+ CEditor editor = (CEditor) editorPart ;
+ @SuppressWarnings("unused")
+ IAction completionAction = editor.getAction("ContentAssistProposal");
+
+ String contentType = editor.getViewer().getDocument().getContentType(offset);
+ ContentAssistant assistant = new ContentAssistant();
+ CContentAssistProcessor processor = new CContentAssistProcessor(editor, assistant, contentType);
+ return processor.computeCompletionProposals(editor.getViewer(), offset);
+ }
+
+ public void testBug69334a() throws Exception {
+ importFile( "test.h", "class Test{ public : Test( int ); }; \n" ); //$NON-NLS-1$//$NON-NLS-2$
+ StringWriter writer = new StringWriter();
+ writer.write( "#include \"test.h\" \n"); //$NON-NLS-1$
+ writer.write( "Test::Test( int i ) { return; } \n"); //$NON-NLS-1$
+ writer.write( "int main() { \n"); //$NON-NLS-1$
+ writer.write( " int veryLongName = 1; \n"); //$NON-NLS-1$
+ writer.write( " Test * ptest = new Test( very \n"); //$NON-NLS-1$
+
+ String code = writer.toString();
+ IFile cu = importFile( "test.cpp", code ); //$NON-NLS-1$
+
+ ICompletionProposal [] results = getResults( cu, code.indexOf( "very " ) + 4 ); //$NON-NLS-1$
+
+ assertEquals( 1, results.length );
+ assertEquals( "veryLongName : int", results[0].getDisplayString() ); //$NON-NLS-1$
+ }
+
+ public void testBug69334b() throws Exception {
+ importFile( "test.h", "class Test{ public : Test( int ); }; \n" ); //$NON-NLS-1$//$NON-NLS-2$
+ StringWriter writer = new StringWriter();
+ writer.write( "#include \"test.h\" \n"); //$NON-NLS-1$
+ writer.write( "Test::Test( int i ) { return; } \n"); //$NON-NLS-1$
+ writer.write( "int main() { \n"); //$NON-NLS-1$
+ writer.write( " int veryLongName = 1; \n"); //$NON-NLS-1$
+ writer.write( " Test test( very \n"); //$NON-NLS-1$
+
+ String code = writer.toString();
+ IFile cu = importFile( "test.cpp", code ); //$NON-NLS-1$
+
+ ICompletionProposal [] results = getResults( cu, code.indexOf( "very " ) + 4 ); //$NON-NLS-1$
+
+ assertEquals( 1, results.length );
+ // We should not match anything in glibc and only see something from the source code
+ assertEquals( "veryLongName : int", results[0].getDisplayString() ); //$NON-NLS-1$
+ }
+
+ public void testBug428037() throws Exception {
+ StringWriter writer = new StringWriter();
+ writer.write( "class Strategy { \n"); //$NON-NLS-1$
+ writer.write( "public : \n"); //$NON-NLS-1$
+ writer.write( " enum _Ability { IDIOT, NORMAL, CHEAT } ; \n"); //$NON-NLS-1$
+ writer.write( " Strategy( _Ability a ) { } \n"); //$NON-NLS-1$
+ writer.write( " _Ability getAbility(); \n"); //$NON-NLS-1$
+ writer.write( "}; \n"); //$NON-NLS-1$
+ writer.write( "int main(){ \n"); //$NON-NLS-1$
+
+ String code = writer.toString();
+ String c2 = code + " Strategy *p[3] = { new Strategy( Str \n"; //$NON-NLS-1$
+
+ IFile cu = importFile( "strategy.cpp", c2 ); //$NON-NLS-1$
+
+ ICompletionProposal [] results = getResults( cu, c2.indexOf( "Str " ) + 3 ); //$NON-NLS-1$
+ assertEquals( 1, results.length );
+ assertEquals( "Strategy", results[0].getDisplayString() ); //$NON-NLS-1$
+
+ c2 = code + " Strategy *p[3] = { new Strategy( Strategy:: \n"; //$NON-NLS-1$
+
+ cu = importFile( "strategy.cpp", c2 ); //$NON-NLS-1$
+
+ results = getResults( cu, c2.indexOf( "::" ) + 2 ); //$NON-NLS-1$
+
+ // Verify we only get back completions from the source code and not glibc function completions
+ assertEquals( 4, results.length );
+ assertEquals( "CHEAT", results[0].getDisplayString() ); //$NON-NLS-1$
+ assertEquals( "IDIOT", results[1].getDisplayString() ); //$NON-NLS-1$
+ assertEquals( "NORMAL", results[2].getDisplayString() ); //$NON-NLS-1$
+ // "_Ability" is here due to fix for bug 199598
+ // Difficult to differentiate between declaration and expression context
+ assertEquals( "_Ability", results[3].getDisplayString() ); //$NON-NLS-1$
+
+ // in a method definition context, constructors and methods should be proposed
+
+ c2 = code + "return 0;}\nStrategy::\n"; //$NON-NLS-1$
+
+ cu = importFile( "strategy.cpp", c2 ); //$NON-NLS-1$
+
+ results = getResults( cu, c2.indexOf( "::" ) + 2 ); //$NON-NLS-1$
+ assertEquals( 3, results.length );
+ assertEquals( "getAbility(void) : enum _Ability", results[1].getDisplayString() ); //$NON-NLS-1$
+ assertEquals( "Strategy(enum _Ability a)", results[0].getDisplayString() ); //$NON-NLS-1$
+ assertEquals( "_Ability", results[2].getDisplayString() ); //$NON-NLS-1$
+}
+
+ public void testBug72559() throws Exception {
+ StringWriter writer = new StringWriter();
+ writer.write("void foo(){ \n"); //$NON-NLS-1$
+ writer.write(" int var; \n"); //$NON-NLS-1$
+ writer.write(" { \n"); //$NON-NLS-1$
+ writer.write(" float var; \n"); //$NON-NLS-1$
+ writer.write(" v \n"); //$NON-NLS-1$
+ writer.write(" } \n"); //$NON-NLS-1$
+ writer.write("} \n"); //$NON-NLS-1$
+
+ String code = writer.toString();
+ IFile cu = importFile( "t.cpp", code ); //$NON-NLS-1$
+ ICompletionProposal [] results = getResults( cu, code.indexOf( "v " ) + 1 ); //$NON-NLS-1$
+
+ assertTrue( results.length >= 5 );
+
+ // Verify first 2 suggestions come from glibc
+ assertEquals( results[0].getDisplayString(), "valloc (size_t size) void *" ); //$NON-NLS-1$
+ assertEquals( results[1].getDisplayString(), "vasprintf (char **ptr, const char *template, va_list ap) int" ); //$NON-NLS-1$
+
+
+ // Verify end of list contains completions from indexer
+ assertEquals( results[results.length - 3].getDisplayString(), "var : float" ); //$NON-NLS-1$
+ assertEquals( results[results.length - 2].getDisplayString(), "virtual" ); //$NON-NLS-1$
+ assertEquals( results[results.length - 1].getDisplayString(), "volatile" ); //$NON-NLS-1$
+ }
+
+ public void testCfunc() throws Exception {
+ StringWriter writer = new StringWriter();
+ writer.write("void foo(){ \n"); //$NON-NLS-1$
+ writer.write(" int var; \n"); //$NON-NLS-1$
+ writer.write(" var = strle \n"); //$NON-NLS-1$
+ writer.write("} \n"); //$NON-NLS-1$
+
+ String code = writer.toString();
+ IFile cu = importFile( "t.c", code ); //$NON-NLS-1$
+ ICompletionProposal [] results = getResults( cu, code.indexOf( "strle " ) + 5 ); //$NON-NLS-1$
+
+ assertTrue( results.length >= 1 );
+
+ // Verify we find the glibc strlen function
+ assertEquals( results[0].getDisplayString(), "strlen (const char *s) size_t" ); //$NON-NLS-1$
+
+ if (results.length > 1) // if newlib book also enabled, verify it is correct too
+ assertEquals( results[1].getDisplayString(), "strlen (const char *str) size_t " ); //$NON-NLS-1$
+ }
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ResourceHelper.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ResourceHelper.java
new file mode 100644
index 0000000000..7705d01888
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/ResourceHelper.java
@@ -0,0 +1,745 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 Andrew Gvozdev and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andrew Gvozdev - Initial API and implementation
+ * James Blackburn (Broadcom Corp.)
+ * Liviu Ionescu - bug 392416
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.IPDOMManager;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
+import org.eclipse.cdt.internal.core.Cygwin;
+import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.Job;
+import org.junit.Assert;
+
+/**
+ * This class contains utility methods for creating resources
+ * such as projects, files, folders etc. which are being used
+ * in test fixture of unit tests.
+ *
+ * Some classes with similar idea worth to look at:
+ * org.eclipse.core.filebuffers.tests.ResourceHelper,
+ * org.eclipse.cdt.ui.tests.text.ResourceHelper.
+ *
+ * @since 6.0
+ */
+@SuppressWarnings("restriction")
+public class ResourceHelper {
+ private final static IProgressMonitor NULL_MONITOR = new NullProgressMonitor();
+ private static final int MAX_RETRY= 5;
+
+ private final static Set<String> externalFilesCreated = new HashSet<String>();
+ private final static Set<IResource> resourcesCreated = new HashSet<IResource>();
+
+ /**
+ * Creates CDT project in a specific path in workspace and opens it.
+ *
+ * @param projectName - project name.
+ * @param pathInWorkspace - path relative to workspace root.
+ * @return - new {@link IProject}.
+ * @throws CoreException - if the project can't be created.
+ * @throws OperationCanceledException...
+ */
+ public static IProject createCDTProject(String projectName, String pathInWorkspace) throws OperationCanceledException, CoreException {
+ return createCDTProject(projectName, pathInWorkspace, null);
+ }
+
+ /**
+ * Creates CDT project in a specific path in workspace adding specified configurations and opens it.
+ *
+ * @param projectName - project name.
+ * @param pathInWorkspace - path relative to workspace root.
+ * @param configurationIds - array of configuration IDs.
+ * @return - new {@link IProject}.
+ * @throws CoreException - if the project can't be created.
+ * @throws OperationCanceledException...
+ */
+ public static IProject createCDTProject(String projectName, String pathInWorkspace, String[] configurationIds) throws OperationCanceledException, CoreException {
+ CCorePlugin cdtCorePlugin = CCorePlugin.getDefault();
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+
+ IProject project = root.getProject(projectName);
+ IndexerPreferences.set(project, IndexerPreferences.KEY_INDEXER_ID, IPDOMManager.ID_NO_INDEXER);
+ resourcesCreated.add(project);
+
+ IProjectDescription prjDescription = workspace.newProjectDescription(projectName);
+ if(pathInWorkspace != null) {
+ IPath absoluteLocation = root.getLocation().append(pathInWorkspace);
+ prjDescription.setLocation(absoluteLocation);
+ }
+
+ if (configurationIds != null && configurationIds.length > 0) {
+ ICProjectDescriptionManager prjDescManager = cdtCorePlugin.getProjectDescriptionManager();
+
+ project.create(NULL_MONITOR);
+ project.open(NULL_MONITOR);
+
+ ICProjectDescription icPrjDescription = prjDescManager.createProjectDescription(project, false);
+ ICConfigurationDescription baseConfiguration = cdtCorePlugin.getPreferenceConfiguration(TestCfgDataProvider.PROVIDER_ID);
+
+ for (String cfgId : configurationIds) {
+ icPrjDescription.createConfiguration(cfgId, cfgId + " Name", baseConfiguration);
+ }
+ prjDescManager.setProjectDescription(project, icPrjDescription);
+ }
+ project = cdtCorePlugin.createCDTProject(prjDescription, project, NULL_MONITOR);
+ waitForProjectRefreshToFinish();
+ Assert.assertNotNull(project);
+
+ project.open(null);
+ Assert.assertTrue(project.isOpen());
+
+ return project;
+ }
+
+ /**
+ * Creates CDT project in a specific location and opens it.
+ *
+ * @param projectName - project name.
+ * @param locationURI - location.
+ * @return - new {@link IProject}.
+ * @throws CoreException - if the project can't be created.
+ * @throws OperationCanceledException...
+ */
+ public static IProject createCDTProject(String projectName, URI locationURI) throws OperationCanceledException, CoreException {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+
+ IProject project = root.getProject(projectName);
+ IndexerPreferences.set(project, IndexerPreferences.KEY_INDEXER_ID, IPDOMManager.ID_NO_INDEXER);
+ resourcesCreated.add(project);
+
+ IProjectDescription description = workspace.newProjectDescription(projectName);
+ description.setLocationURI(locationURI);
+ project = CCorePlugin.getDefault().createCDTProject(description, project, NULL_MONITOR);
+ waitForProjectRefreshToFinish();
+ Assert.assertNotNull(project);
+
+ project.open(null);
+ Assert.assertTrue(project.isOpen());
+
+ return project;
+ }
+
+ /**
+ * Creates a project in the workspace and opens it.
+ *
+ * @param projectName - project name.
+ * @return - new {@link IProject}.
+ * @throws CoreException - if the project can't be created.
+ * @throws OperationCanceledException...
+ */
+ public static IProject createCDTProject(String projectName) throws OperationCanceledException, CoreException {
+ return createCDTProject(projectName, null, null);
+ }
+
+ /**
+ * Creates a project with 1 test configuration and opens it.
+ *
+ * @param projectName - project name.
+ * @return - new {@link IProject}.
+ * @throws CoreException - if the project can't be created.
+ * @throws OperationCanceledException...
+ */
+ public static IProject createCDTProjectWithConfig(String projectName) throws Exception {
+ IProject project = createCDTProject(projectName, null,
+ new String[] {"org.eclipse.cdt.core.tests.configuration"});
+ resourcesCreated.add(project);
+ return project;
+ }
+
+ /**
+ * Creates a plain Eclipse project.
+ *
+ * @param projectName
+ * @return the project handle
+ * @throws CoreException if project could not be created
+ */
+ public static IProject createProject(String projectName) throws CoreException {
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ IProject project= root.getProject(projectName);
+ if (!project.exists()) {
+ project.create(NULL_MONITOR);
+ } else {
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ }
+
+ if (!project.isOpen())
+ project.open(NULL_MONITOR);
+
+ resourcesCreated.add(project);
+ return project;
+ }
+
+ /**
+ * Deletes project by name.
+ *
+ * @param projectName
+ * @throws CoreException
+ */
+ public static void deleteProject(String projectName) throws CoreException {
+ IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
+ IProject project= root.getProject(projectName);
+ if (project.exists())
+ delete(project);
+ }
+
+ /**
+ * Deletes given project with content.
+ *
+ * @param project
+ * @throws CoreException
+ */
+ public static void delete(final IProject project) throws CoreException {
+ delete(project, true);
+ }
+
+ /**
+ * Deletes project.
+ *
+ * @param project
+ * @param deleteContent whether to delete project content
+ * @throws CoreException
+ */
+ public static void delete(final IProject project, boolean deleteContent) throws CoreException {
+ for (int i= 0; i < MAX_RETRY; i++) {
+ try {
+ project.delete(deleteContent, true, NULL_MONITOR);
+ i= MAX_RETRY;
+ } catch (CoreException x) {
+ if (i == MAX_RETRY - 1) {
+ x.printStackTrace();
+ }
+ try {
+ Thread.sleep(1000); // sleep a second
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates a file with specified content.
+ *
+ * @param file - file name.
+ * @param contents - contents of the file.
+ * @return file handle.
+ * @throws CoreException - if the file can't be created.
+ */
+ public static IFile createFile(IFile file, String contents) throws CoreException {
+ if (contents == null) {
+ contents= "";
+ }
+
+ InputStream inputStream = new ByteArrayInputStream(contents.getBytes());
+ file.create(inputStream, true, NULL_MONITOR);
+ resourcesCreated.add(file);
+ return file;
+ }
+
+ /**
+ * Creates new file from project root with empty content. The filename
+ * can include relative path as a part of the name but the the path
+ * has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param name - filename.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFile createFile(IProject project, String name) throws CoreException {
+ if (new Path(name).segmentCount() > 1)
+ createFolder(project, new Path(name).removeLastSegments(1).toString());
+ return createFile(project.getFile(name), null);
+ }
+
+ /**
+ * Creates new file from workspace root with empty content. The filename
+ * can include relative path as a part of the name but the the path
+ * has to be present on disk.
+ * The intention of the method is to create files which do not belong to any project.
+ *
+ * @param name - filename.
+ * @return full path of the created file.
+ *
+ * @throws CoreException...
+ * @throws IOException...
+ */
+ public static IPath createWorkspaceFile(String name) throws CoreException, IOException {
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IPath fullPath = workspaceRoot.getLocation().append(name);
+ java.io.File file = new java.io.File(fullPath.toOSString());
+ if (!file.exists()) {
+ boolean result = file.createNewFile();
+ Assert.assertTrue(result);
+ }
+ Assert.assertTrue(file.exists());
+
+ externalFilesCreated.add(fullPath.toOSString());
+ workspaceRoot.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
+ return fullPath;
+ }
+
+ /**
+ * Creates new folder from project root. The folder name
+ * can include relative path as a part of the name.
+ * Nonexistent parent directories are being created.
+ *
+ * @param project - project where to create the folder.
+ * @param name - folder name.
+ * @return folder handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFolder createFolder(IProject project, String name) throws CoreException {
+ final IPath p = new Path(name);
+ IContainer folder = project;
+ for (String seg : p.segments()) {
+ folder = folder.getFolder(new Path(seg));
+ if (!folder.exists())
+ ((IFolder)folder).create(true, true, NULL_MONITOR);
+ }
+ resourcesCreated.add(folder);
+ return (IFolder)folder;
+ }
+
+ /**
+ * Creates new folder from workspace root. The folder name
+ * can include relative path as a part of the name.
+ * Nonexistent parent directories are being created as per {@link File#mkdirs()}.
+ * The intention of the method is to create folders which do not belong to any project.
+ *
+ * @param name - folder name.
+ * @return absolute location of the folder on the file system.
+ * @throws IOException if something goes wrong.
+ */
+ public static IPath createWorkspaceFolder(String name) throws CoreException, IOException {
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IPath fullPath = workspaceRoot.getLocation().append(name);
+ java.io.File folder = new java.io.File(fullPath.toOSString());
+ if (!folder.exists()) {
+ boolean result = folder.mkdirs();
+ Assert.assertTrue(result);
+ }
+ Assert.assertTrue(folder.exists());
+
+ externalFilesCreated.add(fullPath.toOSString());
+ workspaceRoot.refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR);
+ return fullPath;
+ }
+
+ /**
+ * Creates new temporary folder with generated name from workspace root.
+ *
+ * @return absolute location of the folder on the file system.
+ * @throws IOException if something goes wrong.
+ */
+ public static IPath createTemporaryFolder() throws CoreException, IOException {
+ return ResourceHelper.createWorkspaceFolder("tmp/" + System.currentTimeMillis() + '.' + UUID.randomUUID());
+ }
+
+ /**
+ * Creates new eclipse file-link from project root to file system file. The filename
+ * can include relative path as a part of the name but the the path
+ * has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param fileLink - filename of the link being created.
+ * @param realFile - file on the file system, the target of the link.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFile createLinkedFile(IProject project, String fileLink, IPath realFile) throws CoreException {
+ IFile file = project.getFile(fileLink);
+ file.createLink(realFile, IResource.REPLACE, null);
+ Assert.assertTrue(file.exists());
+ resourcesCreated.add(file);
+ return file;
+ }
+
+ /**
+ * Creates new eclipse file-link from project root to file system file. The filename
+ * can include relative path as a part of the name but the the path
+ * has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param fileLink - filename of the link being created.
+ * @param realFile - file on the file system, the target of the link.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFile createLinkedFile(IProject project, String fileLink, String realFile) throws CoreException {
+ return createLinkedFile(project, fileLink, new Path(realFile));
+ }
+
+ /**
+ * Creates new eclipse file-link from project root to EFS file.
+ *
+ * @param project - project where to create the file.
+ * @param fileLink - filename of the link being created.
+ * @param realFile - file on the EFS file system, the target of the link.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFile createEfsFile(IProject project, String fileLink, URI realFile) throws CoreException {
+ IFile file= project.getFile(fileLink);
+ file.createLink(realFile, IResource.ALLOW_MISSING_LOCAL, NULL_MONITOR);
+ resourcesCreated.add(file);
+ return file;
+ }
+
+ /**
+ * Creates new eclipse file-link from project root to EFS file.
+ *
+ * @param project - project where to create the file.
+ * @param fileLink - filename of the link being created.
+ * @param realFile - file on the EFS file system, the target of the link.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ * @throws URISyntaxException if wrong URI syntax
+ */
+ public static IFile createEfsFile(IProject project, String fileLink, String realFile) throws CoreException, URISyntaxException {
+ return createEfsFile(project,fileLink,new URI(realFile));
+ }
+
+ /**
+ * Creates new eclipse folder-link from project root to file system folder. The folder name
+ * can include relative path as a part of the name but the the path
+ * has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param folderLink - name of the link being created.
+ * @param realFolder - folder on the file system, the target of the link.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFolder createLinkedFolder(IProject project, String folderLink, IPath realFolder) throws CoreException {
+ IFolder folder = project.getFolder(folderLink);
+ folder.createLink(realFolder, IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null);
+ Assert.assertTrue(folder.exists());
+ resourcesCreated.add(folder);
+ return folder;
+ }
+
+ /**
+ * Creates new eclipse folder-link from project root to file system folder. The folder name
+ * can include relative path as a part of the name but the the path
+ * has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param folderLink - name of the link being created.
+ * @param realFolder - folder on the file system, the target of the link.
+ * @return file handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFolder createLinkedFolder(IProject project, String folderLink, String realFolder) throws CoreException {
+ return createLinkedFolder(project, folderLink, new Path(realFolder));
+ }
+
+ /**
+ * Creates new eclipse folder-link from project root to EFS folder.
+ *
+ * @param project - project where to create the folder.
+ * @param folderLink - folder name of the link being created.
+ * @param realFolder - folder on the EFS file system, the target of the link.
+ * @return folder handle.
+ * @throws CoreException if something goes wrong.
+ */
+ public static IFolder createEfsFolder(IProject project, String folderLink, URI realFolder) throws CoreException {
+ IFolder folder= project.getFolder(folderLink);
+ if (folder.exists()) {
+ Assert.assertEquals("Folder with the same name but different location already exists",
+ realFolder, folder.getLocationURI());
+ return folder;
+ }
+
+ folder.createLink(realFolder, IResource.ALLOW_MISSING_LOCAL, new NullProgressMonitor());
+ resourcesCreated.add(folder);
+ return folder;
+ }
+
+ /**
+ * Creates new eclipse folder-link from project root to EFS folder.
+ *
+ * @param project - project where to create the folder.
+ * @param folderLink - folder name of the link being created.
+ * @param realFolder - folder on the EFS file system, the target of the link.
+ * @return folder handle.
+ * @throws CoreException if something goes wrong.
+ * @throws URISyntaxException if wrong URI syntax
+ */
+ public static IFolder createEfsFolder(IProject project, String folderLink, String realFolder) throws CoreException, URISyntaxException {
+ return createEfsFolder(project,folderLink,new URI(realFolder));
+ }
+
+ /**
+ * Checks if symbolic links are supported on the system.
+ * Used in particular by method {@link #createSymbolicLink(IPath, IPath)}
+ * and other flavors to create symbolic links.
+ *
+ * Note that Windows links .lnk are not supported here.
+ * @return {@code true} if symbolic links are suppoted, {@code false} otherwise.
+ */
+ public static boolean isSymbolicLinkSupported() {
+ return ! Platform.getOS().equals(Platform.OS_WIN32);
+ }
+
+ /**
+ * Creates new symbolic file system link from file or folder on project root
+ * to another file system file. The filename can include relative path
+ * as a part of the name but the the path has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param linkName - name of the link being created.
+ * @param realPath - file or folder on the file system, the target of the link.
+ * @return file handle.
+ *
+ * @throws UnsupportedOperationException on Windows where links are not supported.
+ * @throws IOException...
+ * @throws CoreException...
+ */
+ public static IResource createSymbolicLink(IProject project, String linkName, IPath realPath)
+ throws IOException, CoreException, UnsupportedOperationException {
+ if (!isSymbolicLinkSupported()) {
+ throw new UnsupportedOperationException("Windows links .lnk are not supported.");
+ }
+
+ Assert.assertTrue("Path for symbolic link does not exist: [" + realPath.toOSString() + "]",
+ new File(realPath.toOSString()).exists());
+
+ IPath linkedPath = project.getLocation().append(linkName);
+ createSymbolicLink(linkedPath, realPath);
+
+ IResource resource = project.getFile(linkName);
+ resource.refreshLocal(IResource.DEPTH_ZERO, null);
+
+ if (!resource.exists()) {
+ resource = project.getFolder(linkName);
+ resource.refreshLocal(IResource.DEPTH_ZERO, null);
+ }
+ Assert.assertTrue("Failed to create resource form symbolic link", resource.exists());
+
+ externalFilesCreated.add(linkedPath.toOSString());
+ ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR);
+ return resource;
+ }
+
+ /**
+ * Creates new symbolic file system link from file or folder to another filesystem file.
+ * The target path has to be present on disk.
+ *
+ * @param linkPath - filesystem path of the link being created.
+ * @param realPath - file or folder on the file system, the target of the link.
+ *
+ * @throws UnsupportedOperationException on Windows where links are not supported.
+ * @throws IOException if execution of the command fails.
+ */
+ public static void createSymbolicLink(IPath linkPath, IPath realPath) throws IOException {
+ if (!isSymbolicLinkSupported()) {
+ throw new UnsupportedOperationException("Windows links .lnk are not supported.");
+ }
+
+ String command[] = { "ln", "-s", realPath.toOSString(), linkPath.toOSString()};
+ Process process = Runtime.getRuntime().exec(command);
+
+ // Wait for up to 2.5s...
+ for (int i = 0; i < 5; i++) {
+ try {
+ Assert.assertTrue("ln process exited with non-zero status", process.waitFor() == 0);
+ // If exitValue succeeded, then the process has exited successfully.
+ break;
+ } catch (InterruptedException e) {
+ // Clear interrupted state, see Java bug http://bugs.sun.com/view_bug.do?bug_id=6420270
+ Thread.interrupted();
+ }
+ // Wait for a 500ms before checking again.
+ try { Thread.sleep(500); } catch (InterruptedException e) {/*don't care*/}
+ }
+ Assert.assertTrue("Symbolic link not created, command=[" + command + "]", linkPath.toFile().exists());
+ }
+
+ /**
+ * Creates new symbolic file system link from file or folder on project root
+ * to another file system file. The filename can include relative path
+ * as a part of the name but the the path has to be present on disk.
+ *
+ * @param project - project where to create the file.
+ * @param linkName - name of the link being created.
+ * @param realPath - file or folder on the file system, the target of the link.
+ * @return file handle.
+ *
+ * @throws UnsupportedOperationException on Windows where links are not supported.
+ * @throws IOException...
+ * @throws CoreException...
+ */
+ public static IResource createSymbolicLink(IProject project, String linkName, String realPath)
+ throws IOException, CoreException, UnsupportedOperationException {
+ return createSymbolicLink(project, linkName, new Path(realPath));
+ }
+
+ /**
+ * Conversion from Windows path to Cygwin path.
+ *
+ * @param windowsPath - Windows path.
+ * @return Cygwin style converted path.
+ * @throws UnsupportedOperationException if Cygwin is unavailable.
+ * @throws IOException on IO problem.
+ */
+ public static String windowsToCygwinPath(String windowsPath) throws IOException, UnsupportedOperationException {
+ return Cygwin.windowsToCygwinPath(windowsPath);
+ }
+
+ /**
+ * Conversion from Cygwin path to Windows path.
+ *
+ * @param cygwinPath - Cygwin path.
+ * @return Windows style converted path.
+ * @throws UnsupportedOperationException if Cygwin is unavailable.
+ * @throws IOException on IO problem.
+ */
+ public static String cygwinToWindowsPath(String cygwinPath) throws IOException, UnsupportedOperationException {
+ return Cygwin.cygwinToWindowsPath(cygwinPath);
+ }
+
+ /**
+ * Get contents of file on file-system.
+ *
+ * @param fullPath - full path to the file on the file-system.
+ * @return contents of the file.
+ * @throws IOException on IO problem.
+ */
+ public static String getContents(IPath fullPath) throws IOException {
+ FileInputStream stream = new FileInputStream(fullPath.toFile());
+ try {
+ // Avoid using java.nio.channels.FileChannel,
+ // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154
+ Reader reader = new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset()));
+ StringBuilder builder = new StringBuilder();
+ char[] buffer = new char[8192];
+ int read;
+ while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
+ builder.append(buffer, 0, read);
+ }
+ return builder.toString();
+ } finally {
+ stream.close();
+ }
+ }
+
+ /**
+ * Get contents of file on file-system.
+ *
+ * @param fullPath - full path to the file on the file-system.
+ * @return contents of the file.
+ * @throws IOException on IO problem.
+ */
+ public static String getContents(String fullPath) throws IOException {
+ return getContents(new Path(fullPath));
+ }
+
+ /**
+ * Clean-up any files created as part of a unit test.
+ * This method removes *all* Workspace IResources and any external
+ * files / folders created with the #createWorkspaceFile #createWorkspaceFolder
+ * methods in this class
+ */
+ public static void cleanUp() throws CoreException, IOException {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ root.refreshLocal(IResource.DEPTH_INFINITE, NULL_MONITOR);
+
+ // Delete all external files & folders created using ResourceHelper
+ for (String loc : externalFilesCreated) {
+ File f = new File(loc);
+ if (f.exists())
+ deleteRecursive(f);
+ }
+ externalFilesCreated.clear();
+
+ // Remove IResources created by this helper
+ for (IResource r : resourcesCreated) {
+ if (r.exists()) {
+ try {
+ r.delete(true, NULL_MONITOR);
+ } catch (CoreException e) {
+ // Ignore
+ }
+ }
+ }
+ resourcesCreated.clear();
+ }
+
+ private static void waitForProjectRefreshToFinish() {
+ try {
+ // CDT opens the Project with BACKGROUND_REFRESH enabled which causes the
+ // refresh manager to refresh the project 200ms later. This Job interferes
+ // with the resource change handler firing see: bug 271264
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null);
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Recursively delete a directory / file
+ *
+ * For safety this method only deletes files created under the workspace
+ *
+ * @param file
+ */
+ private static final void deleteRecursive(File f) throws IllegalArgumentException {
+ // Ensure that the file being deleted is a child of the workspace
+ // root to prevent anything nasty happening
+ if (!f.getAbsolutePath().startsWith(
+ ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile().getAbsolutePath())) {
+ throw new IllegalArgumentException("File must exist within the workspace!");
+ }
+
+ if (f.isDirectory()) {
+ for (File f1 : f.listFiles()) {
+ deleteRecursive(f1);
+ }
+ }
+ f.delete();
+ }
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestCfgDataProvider.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestCfgDataProvider.java
new file mode 100644
index 0000000000..41a31507da
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestCfgDataProvider.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Intel Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Intel Corporation - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import org.eclipse.cdt.core.settings.model.ICSettingEntry;
+import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
+import org.eclipse.cdt.core.settings.model.extension.CLanguageData;
+import org.eclipse.cdt.core.settings.model.extension.CResourceData;
+import org.eclipse.cdt.core.settings.model.extension.impl.CDataFactory;
+import org.eclipse.cdt.core.settings.model.extension.impl.CDefaultConfigurationDataProvider;
+import org.eclipse.cdt.core.settings.model.extension.impl.CDefaultLanguageData;
+import org.eclipse.cdt.core.settings.model.util.CDataUtil;
+
+/**
+ * Basic CDefaultConfigurationDataProvider
+ *
+ * This is extended to allow persisting Library path + Library file language
+ * settings which aren't supported by the base default configuration data provider
+ * i.e. cdt.core without managedbuild...
+ */
+public class TestCfgDataProvider extends CDefaultConfigurationDataProvider {
+ public static final String PROVIDER_ID = CProjectHelper.PLUGIN_ID + ".testCfgDataProvider";
+
+
+ // Overriden so it supports saving Library file and Library path entries
+ private static final class TestDataFactory extends CDataFactory {
+
+ @Override
+ public CLanguageData createLanguageData(CConfigurationData cfg,
+ CResourceData rcBase,
+ CLanguageData base,
+ String id,
+ boolean clone){
+ if(id == null)
+ id = clone ? base.getId() : CDataUtil.genId(rcBase.getId());
+ return new CDefaultLanguageData(id, base);
+ }
+
+ @Override
+ public CLanguageData createLanguageData(CConfigurationData cfg,
+ CResourceData rcBase,
+ String id,
+ String name,
+ String languageId,
+ int supportedEntryKinds,
+ String[] rcTypes,
+ boolean isContentTypes) {
+ return super.createLanguageData(cfg, rcBase, id, name, languageId,
+ supportedEntryKinds | ICSettingEntry.LIBRARY_FILE | ICSettingEntry.LIBRARY_PATH,
+ rcTypes, isContentTypes);
+ }
+
+ }
+
+ @Override
+ protected CDataFactory getDataFactory(){
+ return new TestDataFactory();
+ }
+
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerInfo.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerInfo.java
new file mode 100644
index 0000000000..bbcc3076e1
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerInfo.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
+
+public class TestScannerInfo extends ExtendedScannerInfo {
+ private static final String[] EMPTY = {};
+ private String[] fIncludes;
+ private String[] fIncludeFiles;
+ private String[] fMacroFiles;
+ private Map<String, String> fDefinedSymbols;
+
+ public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles,
+ Map<String, String> definedSymbols) {
+ fIncludes= includes;
+ fIncludeFiles= includeFiles;
+ fMacroFiles= macroFiles;
+ fDefinedSymbols= definedSymbols;
+ }
+
+ @Override
+ public Map getDefinedSymbols() {
+ return fDefinedSymbols == null ? Collections.emptyMap() : fDefinedSymbols;
+ }
+
+ @Override
+ public String[] getIncludePaths() {
+ return fIncludes == null ? EMPTY : fIncludes;
+ }
+
+ @Override
+ public String[] getIncludeFiles() {
+ return fIncludeFiles == null ? EMPTY: fIncludeFiles;
+ }
+
+ @Override
+ public String[] getLocalIncludePath() {
+ return null;
+ }
+
+ @Override
+ public String[] getMacroFiles() {
+ return fMacroFiles == null ? EMPTY: fMacroFiles;
+ }
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerProvider.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerProvider.java
new file mode 100644
index 0000000000..847aca4605
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestScannerProvider.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.core.AbstractCExtension;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoChangeListener;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.core.resources.IResource;
+
+public class TestScannerProvider extends AbstractCExtension implements IScannerInfoProvider {
+ public static String[] sIncludes;
+ public static String[] sIncludeFiles;
+ public static String[] sMacroFiles;
+ public static Map<String, String> sDefinedSymbols = new HashMap<String, String>();
+ public final static String SCANNER_ID = CProjectHelper.PLUGIN_ID + ".TestScanner";
+
+ public static void clear() {
+ sIncludes= sIncludeFiles= sMacroFiles= null;
+ sDefinedSymbols.clear();
+ }
+
+ @Override
+ public IScannerInfo getScannerInformation(IResource resource) {
+ return new TestScannerInfo(sIncludes, sMacroFiles, sIncludeFiles, sDefinedSymbols);
+ }
+
+ @Override
+ public void subscribe(IResource resource, IScannerInfoChangeListener listener) {
+ }
+
+ @Override
+ public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) {
+ }
+}
diff --git a/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestSourceReader.java b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestSourceReader.java
new file mode 100644
index 0000000000..b9b68ad529
--- /dev/null
+++ b/libhover/org.eclipse.linuxtools.cdt.libhover.tests/src/org/eclipse/linuxtools/cdt/libhover/tests/TestSourceReader.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2012 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Markus Schorn - initial API and implementation
+ * Andrew Ferguson (Symbian)
+ * Sergey Prigogin (Google)
+ *******************************************************************************/
+package org.eclipse.linuxtools.cdt.libhover.tests;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ILinkage;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.index.IIndexFile;
+import org.eclipse.cdt.core.index.IIndexFileLocation;
+import org.eclipse.cdt.core.index.IndexLocationFactory;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+/**
+ * Utilities for reading test source code from plug-in .java sources
+ */
+public class TestSourceReader {
+ private final Bundle bundle;
+ private final String srcRoot;
+ private final Class<?> clazz;
+ private final int numSections;
+
+ /**
+ * @param bundle the bundle containing the source, if {@code null} can try to load using
+ * classpath (source folder has to be in the classpath for this to work)
+ * @param srcRoot the directory inside the bundle containing the packages
+ * @param clazz the name of the class containing the test
+ */
+ public TestSourceReader(Bundle bundle, String srcRoot, Class<?> clazz) {
+ this(bundle, srcRoot, clazz, 0);
+ }
+
+ /**
+ * @param bundle the bundle containing the source, if {@code null} can try to load using
+ * classpath (source folder has to be in the classpath for this to work)
+ * @param srcRoot the directory inside the bundle containing the packages
+ * @param clazz the name of the class containing the test
+ * @param numSections the number of comment sections preceding the named test to return.
+ * Pass zero to get all available sections.
+ */
+ public TestSourceReader(Bundle bundle, String srcRoot, Class<?> clazz, int numSections) {
+ this.bundle = bundle;
+ this.srcRoot = srcRoot;
+ this.clazz = clazz;
+ this.numSections = numSections;
+ }
+
+ public StringBuilder[] getContentsForTest(final String testName) throws IOException {
+ return getContentsForTest(bundle, srcRoot, clazz, testName, numSections);
+ }
+
+ public String readTaggedComment(String tag) throws IOException {
+ return readTaggedComment(bundle, tag, clazz, tag);
+ }
+
+ /**
+ * Returns an array of StringBuilder objects for each comment section found preceding the named
+ * test in the source code.
+ *
+ * @param bundle the bundle containing the source, if {@code null} can try to load using
+ * classpath (source folder has to be in the classpath for this to work)
+ * @param srcRoot the directory inside the bundle containing the packages
+ * @param clazz the name of the class containing the test
+ * @param testName the name of the test
+ * @param numSections the number of comment sections preceding the named test to return.
+ * Pass zero to get all available sections.
+ * @return an array of StringBuilder objects for each comment section found preceding the named
+ * test in the source code.
+ * @throws IOException
+ */
+ public static StringBuilder[] getContentsForTest(Bundle bundle, String srcRoot, Class<?> clazz,
+ final String testName, int numSections) throws IOException {
+ // Walk up the class inheritance chain until we find the test method.
+ try {
+ while (clazz.getMethod(testName).getDeclaringClass() != clazz) {
+ clazz = clazz.getSuperclass();
+ }
+ } catch (SecurityException e) {
+ fail(e.getMessage());
+ } catch (NoSuchMethodException e) {
+ fail(e.getMessage());
+ }
+
+ while (true) {
+ // Find and open the .java file for the class clazz.
+ String fqn = clazz.getName().replace('.', '/');
+ fqn = fqn.indexOf("$") == -1 ? fqn : fqn.substring(0, fqn.indexOf("$"));
+ String classFile = fqn + ".java";
+ IPath filePath= new Path(srcRoot + '/' + classFile);
+
+ InputStream in;
+ Class<?> superclass = clazz.getSuperclass();
+ try {
+ if (bundle != null) {
+ in = FileLocator.openStream(bundle, filePath, false);
+ } else {
+ in = clazz.getResourceAsStream('/' + classFile);
+ }
+ } catch (IOException e) {
+ if (superclass == null || !superclass.getPackage().equals(clazz.getPackage())) {
+ throw e;
+ }
+ clazz = superclass;
+ continue;
+ }
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+ try {
+ // Read the java file collecting comments until we encounter the test method.
+ List<StringBuilder> contents = new ArrayList<StringBuilder>();
+ StringBuilder content = new StringBuilder();
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ line = line.replaceFirst("^\\s*", ""); // Replace leading whitespace, preserve trailing
+ if (line.startsWith("//")) {
+ content.append(line.substring(2) + "\n");
+ } else {
+ if (!line.startsWith("@") && content.length() > 0) {
+ contents.add(content);
+ if (numSections > 0 && contents.size() == numSections + 1)
+ contents.remove(0);
+ content = new StringBuilder();
+ }
+ if (line.length() > 0 && !contents.isEmpty()) {
+ int idx= line.indexOf(testName);
+ if (idx != -1 && !Character.isJavaIdentifierPart(line.charAt(idx + testName.length()))) {
+ return contents.toArray(new StringBuilder[contents.size()]);
+ }
+ if (!line.startsWith("@")) {
+ contents.clear();
+ }
+ }
+ }
+ }
+ } finally {
+ br.close();
+ }
+
+ if (superclass == null || !superclass.getPackage().equals(clazz.getPackage())) {
+ throw new IOException("Test data not found for " + clazz.getName() + "." + testName);
+ }
+ clazz = superclass;
+ }
+ }
+
+ /**
+ * Searches for the offset of the first occurrence of a string in a workspace file.
+ * @param lookfor string to be searched for
+ * @param fullPath full path of the workspace file
+ * @return the offset or -1
+ * @throws Exception
+ * @throws UnsupportedEncodingException
+ * @since 4.0
+ */
+ public static int indexOfInFile(String lookfor, Path fullPath) throws Exception {
+ IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(fullPath);
+ Reader reader= new BufferedReader(new InputStreamReader(file.getContents(), file.getCharset()));
+ assertTrue(lookfor.indexOf('\n') == -1);
+ try {
+ int c= 0;
+ int offset= 0;
+ StringBuilder buf= new StringBuilder();
+ while ((c = reader.read()) >= 0) {
+ buf.append((char) c);
+ if (c == '\n') {
+ int idx= buf.indexOf(lookfor);
+ if (idx >= 0) {
+ return idx + offset;
+ }
+ offset += buf.length();
+ buf.setLength(0);
+ }
+ }
+ int idx= buf.indexOf(lookfor);
+ if (idx >= 0) {
+ return idx + offset;
+ }
+ return -1;
+ } finally {
+ reader.close();
+ }
+ }
+
+ public static int getLineNumber(int offset, Path fullPath) throws Exception {
+ IFile file= ResourcesPlugin.getWorkspace().getRoot().getFile(fullPath);
+ Reader reader= new BufferedReader(new InputStreamReader(file.getContents(), file.getCharset()));
+ try {
+ int line = 1;
+ for (int i = 0; i < offset; i++) {
+ int c= reader.read();
+ assertTrue(c >= 0);
+ if (c == '\n')
+ line++;
+ }
+ return line;
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * Reads a section in comments form the source of the given class. The section
+ * is started with '// {tag}' and ends with the first line not started by '//'
+ * @since 4.0
+ */
+ public static String readTaggedComment(Bundle bundle, String srcRoot, Class<?> clazz, final String tag) throws IOException {
+ IPath filePath= new Path(srcRoot + '/' + clazz.getName().replace('.', '/') + ".java");
+
+ InputStream in= FileLocator.openStream(bundle, filePath, false);
+ LineNumberReader reader= new LineNumberReader(new InputStreamReader(in));
+ boolean found= false;
+ final StringBuilder content= new StringBuilder();
+ try {
+ String line= reader.readLine();
+ while (line != null) {
+ line= line.trim();
+ if (line.startsWith("//")) {
+ line= line.substring(2);
+ if (found) {
+ content.append(line);
+ content.append('\n');
+ } else {
+ line= line.trim();
+ if (line.startsWith("{" + tag)) {
+ if (line.length() == tag.length() + 1 ||
+ !Character.isJavaIdentifierPart(line.charAt(tag.length() + 1))) {
+ found= true;
+ }
+ }
+ }
+ } else if (found) {
+ break;
+ }
+ line= reader.readLine();
+ }
+ } finally {
+ reader.close();
+ }
+ assertTrue("Tag '" + tag + "' is not defined inside of '" + filePath + "'.", found);
+ return content.toString();
+ }
+
+ /**
+ * Creates a file with content at the given path inside the given container.
+ * If the file exists its content is replaced.
+ * @param container a container to create the file in
+ * @param filePath the path relative to the container to create the file at
+ * @param contents the content for the file
+ * @return a file object.
+ * @throws CoreException
+ * @since 4.0
+ */
+ public static IFile createFile(final IContainer container, final IPath filePath,
+ final CharSequence contents) throws CoreException {
+ final IWorkspace ws = ResourcesPlugin.getWorkspace();
+ final IFile result[] = new IFile[1];
+ ws.run(new IWorkspaceRunnable() {
+ @Override
+ public void run(IProgressMonitor monitor) throws CoreException {
+ // Obtain file handle
+ IFile file = container.getFile(filePath);
+
+ InputStream stream;
+ try {
+ stream = new ByteArrayInputStream(contents.toString().getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new CoreException(new Status(IStatus.ERROR, CProjectHelper.PLUGIN_ID, null, e));
+ }
+ // Create file input stream
+ if (file.exists()) {
+ long timestamp= file.getLocalTimeStamp();
+ file.setContents(stream, false, false, new NullProgressMonitor());
+ if (file.getLocalTimeStamp() == timestamp) {
+ file.setLocalTimeStamp(timestamp + 1000);
+ }
+ } else {
+ createFolders(file);
+ file.create(stream, true, new NullProgressMonitor());
+ }
+ result[0]= file;
+ }
+
+ private void createFolders(IResource res) throws CoreException {
+ IContainer container= res.getParent();
+ if (!container.exists() && container instanceof IFolder) {
+ createFolders(container);
+ ((IFolder) container).create(true, true, new NullProgressMonitor());
+ }
+ }
+ }, null);
+ return result[0];
+ }
+
+ /**
+ * Creates a file with content at the given path inside the given container.
+ * If the file exists its content is replaced.
+ * @param container a container to create the file in
+ * @param filePath the path relative to the container to create the file at
+ * @param contents the content for the file
+ * @return a file object.
+ * @since 4.0
+ */
+ public static IFile createFile(IContainer container, String filePath, String contents) throws CoreException {
+ return createFile(container, new Path(filePath), contents);
+ }
+
+ /**
+ * Waits until the given file is indexed. Fails if this does not happen within the
+ * given time.
+ * @param file
+ * @param maxmillis
+ * @throws Exception
+ * @since 4.0
+ */
+ public static void waitUntilFileIsIndexed(IIndex index, IFile file, int maxmillis) throws Exception {
+ long fileTimestamp = file.getLocalTimeStamp();
+ IIndexFileLocation indexFileLocation = IndexLocationFactory.getWorkspaceIFL(file);
+
+ long endTime= System.currentTimeMillis() + maxmillis;
+ int timeLeft= maxmillis;
+ while (timeLeft >= 0) {
+ assertTrue(CCorePlugin.getIndexManager().joinIndexer(timeLeft, new NullProgressMonitor()));
+ index.acquireReadLock();
+ try {
+ IIndexFile[] files= index.getFiles(ILinkage.CPP_LINKAGE_ID, indexFileLocation);
+ if (files.length > 0 && areAllFilesNotOlderThan(files, fileTimestamp)) {
+ assertTrue(CCorePlugin.getIndexManager().joinIndexer(timeLeft, new NullProgressMonitor()));
+ return;
+ }
+ files= index.getFiles(ILinkage.C_LINKAGE_ID, indexFileLocation);
+ if (files.length > 0 && areAllFilesNotOlderThan(files, fileTimestamp)) {
+ assertTrue(CCorePlugin.getIndexManager().joinIndexer(timeLeft, new NullProgressMonitor()));
+ return;
+ }
+ } finally {
+ index.releaseReadLock();
+ }
+
+ Thread.sleep(50);
+ timeLeft= (int) (endTime - System.currentTimeMillis());
+ }
+ fail("Indexing of " + file.getFullPath() + " did not complete in " + maxmillis / 1000. + " sec");
+ }
+
+ private static boolean areAllFilesNotOlderThan(IIndexFile[] files, long timestamp) throws CoreException {
+ for (IIndexFile file : files) {
+ if (file.getTimestamp() < timestamp) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
+ ICElement elem= project.findElement(file.getFullPath());
+ if (elem instanceof ITranslationUnit) {
+ ITranslationUnit tu= (ITranslationUnit) elem;
+ return tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
+ }
+ fail("Could not create AST for " + file.getFullPath());
+ return null;
+ }
+}

Back to the top