/*******************************************************************************
* Copyright (c) 2007, 2010 Symbian 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:
* Andrew Ferguson (Symbian) - Initial implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
* Ed Swartz (Nokia)
*******************************************************************************/
package org.eclipse.cdt.ui.tests.search;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.InvocationTargetException;
import junit.framework.TestSuite;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.search.ui.IQueryListener;
import org.eclipse.search.ui.ISearchQuery;
import org.eclipse.search.ui.ISearchResult;
import org.eclipse.search.ui.ISearchResultPage;
import org.eclipse.search.ui.ISearchResultViewPart;
import org.eclipse.search.ui.NewSearchUI;
import org.osgi.framework.Bundle;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.internal.ui.search.PDOMSearchPatternQuery;
import org.eclipse.cdt.internal.ui.search.PDOMSearchQuery;
import org.eclipse.cdt.internal.ui.search.PDOMSearchResult;
import org.eclipse.cdt.internal.ui.search.PDOMSearchViewPage;
public class BasicSearchTest extends BaseUITestCase {
ICProject fCProject;
CharSequence[] testData;
public static TestSuite suite() {
return suite(BasicSearchTest.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
fCProject = CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
Bundle b = CTestPlugin.getDefault().getBundle();
testData = TestSourceReader.getContentsForTest(b, "ui", this.getClass(), getName(), 2);
IFile file = TestSourceReader.createFile(fCProject.getProject(), new Path("header.h"), testData[0].toString());
CCorePlugin.getIndexManager().setIndexerId(fCProject, IPDOMManager.ID_FAST_INDEXER);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
IFile cppfile= TestSourceReader.createFile(fCProject.getProject(), new Path("references.cpp"), testData[1].toString());
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
}
@Override
protected void tearDown() throws Exception {
if (fCProject != null) {
fCProject.getProject().delete(true, npm());
}
super.tearDown();
}
// // empty
// #include "extHead.h"
// void bar() {
// foo();
// }
public void testExternalPathRenderedCorrectly_79193() throws Exception {
// make an external file
File dir= CProjectHelper.freshDir();
File externalFile= new File(dir, "extHead.h");
externalFile.deleteOnExit();
FileWriter fw= new FileWriter(externalFile);
fw.write("void foo() {}\n");
fw.close();
// rebuild the index
TestScannerProvider.sIncludes= new String[] {dir.getAbsolutePath()};
CCorePlugin.getIndexManager().reindex(fCProject);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
// open a query
PDOMSearchQuery query= makeProjectQuery("foo");
PDOMSearchResult result= runQuery(query);
assertEquals(2, result.getElements().length);
ISearchResultViewPart vp= NewSearchUI.getSearchResultView();
ISearchResultPage page= vp.getActivePage();
assertTrue(""+page, page instanceof PDOMSearchViewPage);
PDOMSearchViewPage pdomsvp= (PDOMSearchViewPage) page;
StructuredViewer viewer= pdomsvp.getViewer();
ILabelProvider labpv= (ILabelProvider) viewer.getLabelProvider();
IStructuredContentProvider scp= (IStructuredContentProvider) viewer.getContentProvider();
// project results are in a project node, containing directories and files
Object[] resultElements = scp.getElements(result);
String label0= labpv.getText(resultElements[0]);
String label1= labpv.getText(resultElements[1]);
// external results are in a tree, directory containing files
Object externalResult = resultElements[1];
String path1= labpv.getText(externalResult);
String file1= labpv.getText(scp.getElements(externalResult)[0]);
externalResult = resultElements[0];
String path2= labpv.getText(externalResult);
String file2= labpv.getText(scp.getElements(externalResult)[0]);
// check the results are rendered
String expected0= fCProject.getProject().getName();
String expected1= new Path(externalFile.getAbsolutePath()).toString();
assertTrue(expected0.equals(label0) || expected0.equals(label1));
assertTrue(expected1.equals(new Path(path1).append(file1).toString()) || expected1.equals(new Path(path2).append(file2).toString()));
}
// int x, y, xx, yy;
public void testNoIndexerEnabled_158955() throws Exception {
// rebuild the index with no indexer
CCorePlugin.getIndexManager().setIndexerId(fCProject, IPDOMManager.ID_NO_INDEXER);
CCorePlugin.getIndexManager().reindex(fCProject);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
// open a query
PDOMSearchQuery query= makeProjectQuery("x");
PDOMSearchResult result= runQuery(query);
assertEquals(0, result.getElements().length);
ISearchResultViewPart vp= NewSearchUI.getSearchResultView();
ISearchResultPage page= vp.getActivePage();
assertTrue(""+page, page instanceof PDOMSearchViewPage);
PDOMSearchViewPage pdomsvp= (PDOMSearchViewPage) page;
StructuredViewer viewer= pdomsvp.getViewer();
ILabelProvider labpv= (ILabelProvider) viewer.getLabelProvider();
IStructuredContentProvider scp= (IStructuredContentProvider) viewer.getContentProvider();
// first result is a project node
Object firstRootNode = scp.getElements(result)[0];
String label0= labpv.getText(firstRootNode);
// ... containing a status message
IStatus firstRootChildNode= (IStatus) scp.getElements(firstRootNode)[0];
assertEquals(IStatus.WARNING, firstRootChildNode.getSeverity());
// can't really verify text in case message is localized...
}
final int INDEXER_IN_PROGRESS_FILE_COUNT = 10;
final int INDEXER_IN_PROGRESS_STRUCT_COUNT = 100;
// #include "hugeHeader0.h"
public void testIndexerInProgress() throws Exception {
// make an external file
File dir= CProjectHelper.freshDir();
// make other project files so we can get incomplete results during indexing
for (int i = 1; i < 10; i++) {
TestSourceReader.createFile(fCProject.getProject(), new Path("references" + i + ".cpp"),
"#include \"hugeHeader" + i + ".h\"\n");
}
for (int f = 0; f < INDEXER_IN_PROGRESS_FILE_COUNT; f++) {
File externalFile= new File(dir, "hugeHeader" + f + ".h");
externalFile.deleteOnExit();
FileWriter fw= new FileWriter(externalFile);
for (int i = 0; i < INDEXER_IN_PROGRESS_STRUCT_COUNT; i++) {
fw.write("typedef struct confusingType_" + f + "_" + i + " {\n");
if (i == 0)
fw.write(" void *data" + i + ";\n");
else
fw.write(" myConfusingType_" + f + "_" + (i-1) +" *data" + i + ";\n");
fw.write(" int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;\n");
fw.write("} myConfusingType_" + f + "_" + i + ";\n");
}
fw.close();
}
// rebuild the index and DO NOT JOIN
TestScannerProvider.sIncludes= new String[] {dir.getAbsolutePath()};
CCorePlugin.getIndexManager().reindex(fCProject);
// immediate test, likely 0 matches
coreTestIndexerInProgress(false);
// wait some amount of time to get non-zero and hopefully non-complete results
Thread.sleep(500);
if (!CCorePlugin.getIndexManager().isIndexerIdle())
coreTestIndexerInProgress(false);
// now join and test again to get the full results
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
coreTestIndexerInProgress(true);
}
/**
*
*/
private void coreTestIndexerInProgress(boolean expectComplete) {
// open a query
PDOMSearchQuery query= makeProjectQuery("data*");
PDOMSearchResult result= runQuery(query);
final int maximumHits = INDEXER_IN_PROGRESS_FILE_COUNT * INDEXER_IN_PROGRESS_STRUCT_COUNT;
Object[] elements = result.getElements();
if (expectComplete)
assertEquals(maximumHits, elements.length);
else
assertTrue(maximumHits >= elements.length); // >= because may still be done
ISearchResultViewPart vp= NewSearchUI.getSearchResultView();
ISearchResultPage page= vp.getActivePage();
assertTrue(""+page, page instanceof PDOMSearchViewPage);
PDOMSearchViewPage pdomsvp= (PDOMSearchViewPage) page;
StructuredViewer viewer= pdomsvp.getViewer();
ILabelProvider labpv= (ILabelProvider) viewer.getLabelProvider();
IStructuredContentProvider scp= (IStructuredContentProvider) viewer.getContentProvider();
if (!expectComplete) {
// even if we don't think the indexer is complete, we can't be 100% sure
// the indexer didn't finish before the query started, so don't fail here
// if all the hits were found
if (elements.length < maximumHits) {
// first result is an IStatus indicating indexer was busy
Object[] nodeElements = scp.getElements(result);
Object node = nodeElements[0];
if (!(node instanceof IStatus))
node = nodeElements[1];
if (node instanceof IStatus) {
IStatus firstRootNode = (IStatus) node;
assertEquals(IStatus.WARNING, firstRootNode.getSeverity());
// can't really verify text in case message is localized...
} else {
fail("can't get status");
}
}
} else {
// must NOT have the IStatus
Object firstRootNode = scp.getElements(result)[0];
assertFalse(firstRootNode instanceof IStatus);
}
}
/**
* Run the specified query, and return the result. When tehis method returns the
* search page will have been opened.
* @param query
* @return
*/
protected PDOMSearchResult runQuery(PDOMSearchQuery query) {
final ISearchResult result[]= new ISearchResult[1];
IQueryListener listener= new IQueryListener() {
public void queryAdded(ISearchQuery query) {}
public void queryFinished(ISearchQuery query) {
result[0]= query.getSearchResult();
}
public void queryRemoved(ISearchQuery query) {}
public void queryStarting(ISearchQuery query) {}
};
NewSearchUI.addQueryListener(listener);
NewSearchUI.runQueryInForeground(new IRunnableContext() {
public void run(boolean fork, boolean cancelable,
IRunnableWithProgress runnable)
throws InvocationTargetException, InterruptedException {
runnable.run(npm());
}
}, query);
assertTrue(result[0] instanceof PDOMSearchResult);
runEventQueue(500);
return (PDOMSearchResult) result[0];
}
// void foo() {}
// void bar() {
// foo();
// }
public void testNewResultsOnSearchAgainA() throws Exception {
PDOMSearchQuery query= makeProjectQuery("foo");
assertOccurrences(query, 2);
assertOccurrences(query, 2);
String newContent= "void bar() {}";
IFile file = fCProject.getProject().getFile(new Path("references.cpp"));
file.setContents(new ByteArrayInputStream(newContent.getBytes()), IResource.FORCE, npm());
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
assertOccurrences(query, 1);
}
// void foo() {}
// void bar() {foo();foo();foo();}
public void testNewResultsOnSearchAgainB() throws Exception {
PDOMSearchQuery query= makeProjectQuery("foo");
assertOccurrences(query, 4);
assertOccurrences(query, 4);
// whitespace s.t. new match offset is same as older
String newContent= "void bar() { foo(); }";
IFile file = fCProject.getProject().getFile(new Path("references.cpp"));
file.setContents(new ByteArrayInputStream(newContent.getBytes()), IResource.FORCE, npm());
runEventQueue(1000);
IIndexManager indexManager = CCorePlugin.getIndexManager();
indexManager.update(new ICElement[] {fCProject}, IIndexManager.UPDATE_ALL);
assertTrue(indexManager.joinIndexer(360000, new NullProgressMonitor()));
assertOccurrences(query, 2);
String newContent2= "void bar() {foo(); foo();}";
file.setContents(new ByteArrayInputStream(newContent2.getBytes()), IResource.FORCE, npm());
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, null);
assertTrue(indexManager.joinIndexer(360000, new NullProgressMonitor()));
assertOccurrences(query, 3);
}
private PDOMSearchQuery makeProjectQuery(String pattern) {
String scope1= "Human Readable Description";
return new PDOMSearchPatternQuery(new ICElement[] {fCProject}, scope1, pattern, true, PDOMSearchQuery.FIND_ALL_OCCURRENCES | PDOMSearchPatternQuery.FIND_ALL_TYPES);
}
private void assertOccurrences(PDOMSearchQuery query, int expected) {
query.run(npm());
PDOMSearchResult result= (PDOMSearchResult) query.getSearchResult();
assertEquals(expected, result.getMatchCount());
}
// template<typename T> class CT {};
// template<typename T> class CT<T*> {};
// template<typename T> void f(T) {};
// template<typename T> void f(T*) {};
// void a() {
// CT<int>* r1;
// CT<char>* r2;
// CT<int*>* r3;
//
// int a;
// f(a);
// f(&a);
// f<int>(a);
// f<int>(&a);
// }
public void testSearchAndTemplateIDs() throws Exception {
PDOMSearchQuery query= makeProjectQuery("CT");
assertOccurrences(query, 5);
query= makeProjectQuery("f");
assertOccurrences(query, 6);
}
}