/*******************************************************************************
* Copyright (c) 2009, 2015 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.cdt.internal.index.tests;
import java.io.File;
import java.io.FileWriter;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IPathEntry;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import junit.framework.TestSuite;
public class Bug246129 extends IndexTestBase {
public static TestSuite suite() {
TestSuite suite = suite(Bug246129.class, "_");
// suite.addTest(new Bug246129("include ext/../type.h"));
return suite;
}
private ICProject fProject;
private IFile fSource;
private IFolder fWrapperIncludeFolder;
private IFolder fIncludeFolder;
private File fTmpDir;
private File fExternalWrapperIncludeFolder;
private File fExternalWrapperHeader;
private File fExternalIncludeFolder;
private File fExternalHeader;
private File fExternalExtFolder;
IIndex fIndex;
boolean fFalseFriendsAccepted;
public Bug246129(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
if (fProject == null) {
// Populate workspace
fProject = createProject(true, "resources/indexTests/bug246129");
fSource = fProject.getProject().getFile("source.cpp");
fWrapperIncludeFolder = fProject.getProject().getFolder("wrapper_include");
fIncludeFolder = fProject.getProject().getFolder("include");
// Create header files external to the workspace.
fTmpDir = CProjectHelper.freshDir();
fExternalWrapperIncludeFolder = new File(fTmpDir, "wrapper_include");
fExternalWrapperIncludeFolder.mkdir();
fExternalWrapperHeader = new File(fExternalWrapperIncludeFolder, "external_type.h");
fExternalWrapperHeader.createNewFile();
FileWriter writer = new FileWriter(fExternalWrapperHeader);
writer.write("#ifndef EXTERNAL_WRAPPER_TYPE_H_\n");
writer.write("#define EXTERNAL_WRAPPER_TYPE_H_\n");
writer.write("#include <ext/../external_type.h>\n");
writer.write("class ExternalWrapper {\n");
writer.write("};\n");
writer.write("#endif\n");
writer.close();
fExternalIncludeFolder = new File(fTmpDir, "include");
fExternalIncludeFolder.mkdir();
fExternalExtFolder = new File(fExternalIncludeFolder, "ext");
fExternalExtFolder.mkdir();
fExternalHeader = new File(fExternalIncludeFolder, "external_type.h");
fExternalHeader.createNewFile();
writer = new FileWriter(fExternalHeader);
writer.write("#ifndef EXTERNAL_TYPE_H_\n");
writer.write("#define EXTERNAL_TYPE_H_\n");
writer.write("class ExternalType {\n");
writer.write("};\n");
writer.write("#endif\n");
writer.close();
// The indexer needs non-empty build info in order to index
// source files if index-all-files is turned off.
IPathEntry[] entries = new IPathEntry[] {
CoreModel.newIncludeEntry(fProject.getPath(), null, fWrapperIncludeFolder.getLocation()),
CoreModel.newIncludeEntry(fProject.getPath(), null, fIncludeFolder.getLocation()) };
fProject.setRawPathEntries(entries, npm());
// However, the scanner info provider used by the unit tests
// needs separate setup, and this one must be complete.
TestScannerProvider.sIncludes = new String[] {
fWrapperIncludeFolder.getLocation().toOSString(),
fIncludeFolder.getLocation().toOSString(),
fExternalWrapperIncludeFolder.getAbsolutePath(),
fExternalIncludeFolder.getAbsolutePath() };
IndexerPreferences.set(fProject.getProject(),
IndexerPreferences.KEY_INDEX_UNUSED_HEADERS_WITH_DEFAULT_LANG, "false");
File falseFriendDirectory = new File(fWrapperIncludeFolder.getLocation().toOSString() + "/ext/..");
fFalseFriendsAccepted = falseFriendDirectory.exists();
CCorePlugin.getIndexManager().reindex(fProject);
waitForIndexer(fProject);
fIndex = CCorePlugin.getIndexManager().getIndex(fProject);
}
}
@Override
protected void tearDown() throws Exception {
fExternalWrapperHeader.delete();
fExternalWrapperIncludeFolder.delete();
fExternalHeader.delete();
fExternalExtFolder.delete();
fExternalIncludeFolder.delete();
fTmpDir.delete();
super.tearDown();
}
private void assertSymbolInIndex(String symbolName) throws Exception {
IIndexBinding[] bindings = fIndex.findBindings(symbolName.toCharArray(), false, IndexFilter.ALL, npm());
assertTrue(bindings.length != 0);
}
public void testIndex() throws Exception {
try {
fIndex.acquireReadLock();
IIndexFile[] indexFiles = fIndex.getAllFiles();
// Check that all header files have been found, provided the
// File implementation does support it.
if (fFalseFriendsAccepted) {
assertEquals(3, indexFiles.length);
} else {
assertEquals(5, indexFiles.length);
}
// The wrapper classes are found regardless whether false friends
// are accepted or not.
assertSymbolInIndex("Wrapper");
assertSymbolInIndex("ExternalWrapper");
// The Type class is only known on platforms with a File
// implementation sorting out the false friends.
if (!fFalseFriendsAccepted) {
assertSymbolInIndex("Type");
assertSymbolInIndex("ExternalType");
}
// Check that all paths are normalized.
for (IIndexFile indexFile : indexFiles) {
IIndexInclude[] includes = indexFile.getIncludes();
for (IIndexInclude i : includes) {
IIndexFileLocation location = i.getIncludesLocation();
assertNotNull(location);
assertFalse(location.getURI().toASCIIString().contains(".."));
String fullPath = location.getFullPath();
if (fullPath != null) {
assertFalse(fullPath.contains(".."));
}
}
}
} finally {
fIndex.releaseReadLock();
}
}
private void assertSymbolInAst(IScope scope, String symbolName, IASTTranslationUnit ast) throws Exception {
IBinding[] bindings = scope.find(symbolName, ast);
assertTrue(bindings.length > 0);
}
public void testAst() throws Exception {
ITranslationUnit tu =
CoreModel.getDefault().createTranslationUnitFrom(fProject, fSource.getLocation());
IASTTranslationUnit ast = tu.getAST();
// The wrapper classes are found regardless whether false friends
// are
// accepted or not.
IScope topLevel = ast.getScope();
assertSymbolInAst(topLevel, "Wrapper", ast);
assertSymbolInAst(topLevel, "ExternalWrapper", ast);
// The Type class is only known on platforms with a File
// implementation sorting out the false friends.
if (!fFalseFriendsAccepted) {
assertSymbolInAst(topLevel, "Type", ast);
assertSymbolInAst(topLevel, "ExternalType", ast);
}
// Check that all paths are normalized.
IASTPreprocessorIncludeStatement[] includes = ast.getIncludeDirectives();
for (IASTPreprocessorIncludeStatement i : includes) {
String includedPath = i.getPath();
assertNotNull(includedPath);
assertFalse(includedPath.contains(".."));
}
}
}