/******************************************************************************* * Copyright (c) 2006, 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 *******************************************************************************/ package org.eclipse.cdt.internal.index.tests; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import junit.framework.Test; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.index.ResourceContainerRelativeLocationConverter; import org.eclipse.cdt.core.index.URIRelativeLocationConverter; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.core.filesystem.URIUtil; 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.ResourcesPlugin; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.osgi.framework.Bundle; public class IndexLocationTest extends BaseTestCase { private static final boolean isWin= Platform.getOS().equals(Platform.OS_WIN32); protected List projects= new ArrayList(); protected ICProject cproject; public static Test suite() { return suite(IndexLocationTest.class); } @Override protected void setUp() throws Exception { super.setUp(); cproject= CProjectHelper.createCProject("LocationTests"+System.currentTimeMillis(), "bin", IPDOMManager.ID_FAST_INDEXER); deleteOnTearDown(cproject); } @Override protected void tearDown() throws Exception { for (Iterator i= projects.iterator(); i.hasNext(); ) { ICProject ptd= (ICProject) i.next(); if (ptd != null) { ptd.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor()); } } super.tearDown(); } // //header // class foo {}; // // external.h // class bar {}; // //source // #include "header.h" // #include "ABS_EXTERNAL" // class baz {}; public void testBasicLocations() throws Exception { File externalHeader = new File(CProjectHelper.freshDir(),"external.h"); try { Bundle b = CTestPlugin.getDefault().getBundle(); CharSequence[] testData = TestSourceReader.getContentsForTest(b, "parser", getClass(), getName(), 3); IFile file1 = TestSourceReader.createFile(cproject.getProject(), "header.h", testData[0].toString()); createExternalFile(externalHeader, testData[1].toString()); String content = testData[2].toString().replaceAll("ABS_EXTERNAL", externalHeader.getAbsolutePath().replaceAll("\\\\","\\\\\\\\")); IFile file3 = TestSourceReader.createFile(cproject.getProject(), "source.cpp", content); CCorePlugin.getIndexManager().reindex(cproject); assertTrue(CCorePlugin.getIndexManager().joinIndexer(10000, new NullProgressMonitor())); IIndex index = CCorePlugin.getIndexManager().getIndex(cproject); index.acquireReadLock(); try { IBinding[] bs1 = index.findBindings(Pattern.compile("foo"), true, IndexFilter.ALL, new NullProgressMonitor()); IBinding[] bs2 = index.findBindings(Pattern.compile("bar"), true, IndexFilter.ALL, new NullProgressMonitor()); IBinding[] bs3 = index.findBindings(Pattern.compile("baz"), true, IndexFilter.ALL, new NullProgressMonitor()); assertEquals(1, bs1.length); assertEquals(1, bs2.length); assertEquals(1, bs3.length); bs1 = index.findBindings("foo".toCharArray(), IndexFilter.ALL, new NullProgressMonitor()); bs2 = index.findBindings("bar".toCharArray(), IndexFilter.ALL, new NullProgressMonitor()); bs3 = index.findBindings("baz".toCharArray(), IndexFilter.ALL, new NullProgressMonitor()); assertEquals(1, bs1.length); assertEquals(1, bs2.length); assertEquals(1, bs3.length); IIndexName[] nms1 = index.findNames(bs1[0], IIndex.FIND_ALL_OCCURRENCES); IIndexName[] nms2 = index.findNames(bs2[0], IIndex.FIND_ALL_OCCURRENCES); IIndexName[] nms3 = index.findNames(bs3[0], IIndex.FIND_ALL_OCCURRENCES); assertEquals(1, nms1.length); assertEquals(1, nms2.length); assertEquals(1, nms3.length); URI workspaceRoot = ResourcesPlugin.getWorkspace().getRoot().getLocationURI(); assertEquals( ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(cproject.getProject().getName()+"/header.h")).getLocationURI(), nms1[0].getFile().getLocation().getURI() ); assertEquals( externalHeader.toURI(), nms2[0].getFile().getLocation().getURI() ); assertEquals( ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(cproject.getProject().getName()+"/source.cpp")).getLocationURI(), nms3[0].getFile().getLocation().getURI() ); assertEquals( ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(cproject.getProject().getName()+"/header.h")).getFullPath(), new Path(nms1[0].getFile().getLocation().getFullPath()) ); assertEquals( null, nms2[0].getFile().getLocation().getFullPath() ); assertEquals( ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(cproject.getProject().getName()+"/source.cpp")).getFullPath(), new Path(nms3[0].getFile().getLocation().getFullPath()) ); } finally { index.releaseReadLock(); } } finally { externalHeader.delete(); externalHeader.getParentFile().delete(); } } public void testLinkedFilesIndexedAsWithinProject() throws Exception { File location = new File(CProjectHelper.freshDir(), "external2.h"); createExternalFile(location, "struct External {};\n"); IFolder content= cproject.getProject().getFolder("content"); content.createLink(new Path(location.getParentFile().getAbsolutePath()), IResource.NONE, npm()); CCorePlugin.getIndexManager().reindex(cproject); IIndex index = CCorePlugin.getIndexManager().getIndex(cproject); TestSourceReader.waitUntilFileIsIndexed(index, content.getFile("external2.h"), 4000); assertTrue(CCorePlugin.getIndexManager().joinIndexer(10000, new NullProgressMonitor())); index.acquireReadLock(); try { IBinding[] bs= index.findBindings("External".toCharArray(), IndexFilter.ALL, npm()); assertEquals(1, bs.length); IIndexName[] nms= index.findNames(bs[0], IIndex.FIND_ALL_OCCURRENCES); assertEquals(1, nms.length); IIndexFileLocation ilocation= nms[0].getFile().getLocation(); assertEquals("/"+cproject.getProject().getName()+"/content/external2.h", ilocation.getFullPath()); } finally { index.releaseReadLock(); } } public void testSameFileLinkedToOnceInTwoProjects_186214() throws Exception { File location = new File(CProjectHelper.freshDir(),"external2.h"); createExternalFile(location, "struct External {};\n"); assertTrue(location.isFile()); IFolder content= cproject.getProject().getFolder("content"); content.createLink(new Path(location.getParentFile().getAbsolutePath()), IResource.NONE, null); final IFile file = content.getFile("external2.h"); assertTrue(file.exists()); ICProject cproject2= CProjectHelper.createCProject("LocationTests2"+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER); deleteOnTearDown(cproject2); IFolder content2= cproject2.getProject().getFolder("content"); content2.createLink(new Path(location.getParentFile().getAbsolutePath()), IResource.NONE, null); assertTrue(content2.getFile("external2.h").exists()); IIndex index = CCorePlugin.getIndexManager().getIndex(cproject); CCorePlugin.getIndexManager().reindex(cproject); TestSourceReader.waitUntilFileIsIndexed(index, file, 10000); waitForIndexer(cproject); index.acquireReadLock(); try { IBinding[] bs= index.findBindings("External".toCharArray(), IndexFilter.ALL, npm()); assertEquals(1, bs.length); IIndexName[] nms= index.findNames(bs[0], IIndex.FIND_ALL_OCCURRENCES); assertEquals(1, nms.length); IIndexFileLocation ilocation= nms[0].getFile().getLocation(); assertEquals("/"+cproject.getProject().getName()+"/content/external2.h", ilocation.getFullPath()); } finally { index.releaseReadLock(); } } public void testResourceContainerRelativeLocationConverter() throws Exception { ICProject emptyCProject= CProjectHelper.createCProject("Empty", "bin", IPDOMManager.ID_NO_INDEXER); deleteOnTearDown(emptyCProject); String[] paths = new String[] {"this.cpp", "inc/header.h", "a b c/d/e f/g.h", "a \\b /c.d"}; for (String path : paths) { IFile file= cproject.getProject().getFile(path); IIndexFileLocation ifl1= IndexLocationFactory.getWorkspaceIFL(file); ResourceContainerRelativeLocationConverter prlc1= new ResourceContainerRelativeLocationConverter(cproject.getProject()); String r1= prlc1.toInternalFormat(ifl1); assertNotNull(r1); ResourceContainerRelativeLocationConverter prlc2= new ResourceContainerRelativeLocationConverter(emptyCProject.getProject()); IIndexFileLocation ifl2= prlc2.fromInternalFormat(r1); assertNotNull(ifl2); assertEquals( new Path(ifl1.getFullPath()).removeFirstSegments(1), new Path(ifl2.getFullPath()).removeFirstSegments(1) ); } } public void testURLC_RCRLC_Interaction1() throws Exception { String[] winPaths = new String[] { "c:/foo/bar/baz.cpp", "c:\\foo\\bar\\a b c\\baz.cpp", "c:/foo/bar/a b/baz.cpp", "c:\\foo\\bar\\a b c\\a b/baz.cpp" }; String[] unxPaths = new String[] { "/home/cdt/foo/bar/baz.cpp", "/home/cdt/foo/bar/a b c/baz.cpp", "/home/cdt/foo/bar/a b/baz.cpp", "/home/cdt/foo/bar/a b c/a b/baz.cpp" }; URI base = URIUtil.toURI(isWin ? "c:/foo/bar/" : "/home/cdt/foo/bar/"); String[] paths= isWin ? winPaths : unxPaths; String[] expectedFullPaths = new String[] { "/"+cproject.getProject().getName()+"/baz.cpp", "/"+cproject.getProject().getName()+"/a b c/baz.cpp", "/"+cproject.getProject().getName()+"/a b/baz.cpp", "/"+cproject.getProject().getName()+"/a b c/a b/baz.cpp" }; IContainer root= ResourcesPlugin.getWorkspace().getRoot(); // loc -uri-> raw -project-> loc for (int i= 0; i < paths.length; i++) { IIndexFileLocation ifl1 = IndexLocationFactory.getExternalIFL(paths[i]); URIRelativeLocationConverter urlc = new URIRelativeLocationConverter(base); String r1 = urlc.toInternalFormat(ifl1); assertNotNull(r1); ResourceContainerRelativeLocationConverter prlc= new ResourceContainerRelativeLocationConverter(cproject.getProject()); IIndexFileLocation ifl2= prlc.fromInternalFormat(r1); String r2= prlc.toInternalFormat(ifl2); assertNotNull(r2); assertNull(ifl1.getFullPath()); assertEquals(expectedFullPaths[i], ifl2.getFullPath()); assertEquals(URIUtil.toURI(paths[i]).normalize(), ifl1.getURI()); assertEquals(root.getFile(new Path(expectedFullPaths[i])).getLocationURI(), ifl2.getURI()); } } public void testURLC_RCRLC_Interaction2() throws Exception { String[] winPaths = new String[] { "a b c/d/e f/g.h", "a \\b /c.d", "/a b c/d-e/f.g" }; String[] unxPaths = new String[] { "a b c/d/e f/g.h", "a /b /c.d", "/a b c/d-e/f.g" }; String[] paths= isWin ? winPaths : unxPaths; String basePath = isWin ? "c:/foo/bar/" : "/home/cdt/foo/bar/"; String[] expectedFullPaths = new String[] { "/"+cproject.getProject().getName()+"/a b c/d/e f/g.h", "/"+cproject.getProject().getName()+"/a /b /c.d", "/"+cproject.getProject().getName()+"/a b c/d-e/f.g" }; URI base = makeDirectoryURI(basePath); URIRelativeLocationConverter c1 = new URIRelativeLocationConverter(base); // loc -project-> raw -uri-> loc for (int i= 0; i < paths.length; i++) { IFile file= cproject.getProject().getFile(paths[i]); IIndexFileLocation ifl1= IndexLocationFactory.getWorkspaceIFL(file); ResourceContainerRelativeLocationConverter prlc= new ResourceContainerRelativeLocationConverter(cproject.getProject()); String r1= prlc.toInternalFormat(ifl1); assertNotNull(r1); IIndexFileLocation ifl2= c1.fromInternalFormat(r1); assertNotNull(ifl2); assertEquals(expectedFullPaths[i], ifl1.getFullPath()); assertNull(ifl2.getFullPath()); assertEquals(cproject.getProject().getFile(paths[i]).getLocationURI(), ifl1.getURI()); assertEquals(URIUtil.toURI(basePath+paths[i]).normalize(), ifl2.getURI()); } } public void testURLC_RCRLC_Interaction3() throws Exception { IFolder linkedFolder= cproject.getProject().getFolder("linkedFolder"); String[] winPaths = new String[] { "a b c/d/e f/g.h", "a \\b /c.d", "/a b c/d-e/f.g" }; String[] unxPaths = new String[] { "a b c/d/e f/g.h", "a /b /c.d", "/a b c/d-e/f.g" }; String[] paths= isWin ? winPaths : unxPaths; String basePath = isWin ? "c:/foo/bar/" : "/home/cdt/foo/bar/"; String[] expectedFullPaths = new String[] { linkedFolder.getFullPath()+"/a b c/d/e f/g.h", linkedFolder.getFullPath()+"/a /b /c.d", linkedFolder.getFullPath()+"/a b c/d-e/f.g" }; // loc -project-> raw -uri-> loc URI base = makeDirectoryURI(basePath); URIRelativeLocationConverter c1 = new URIRelativeLocationConverter(base); for (int i= 0; i < paths.length; i++) { IFile file= linkedFolder.getFile(paths[i]); IIndexFileLocation ifl1= IndexLocationFactory.getWorkspaceIFL(file); ResourceContainerRelativeLocationConverter prlc= new ResourceContainerRelativeLocationConverter(linkedFolder); String r1= prlc.toInternalFormat(ifl1); assertNotNull(r1); IIndexFileLocation ifl2= c1.fromInternalFormat(r1); assertNotNull(ifl2); assertEquals(expectedFullPaths[i], ifl1.getFullPath()); assertNull(ifl2.getFullPath()); assertEquals(linkedFolder.getFile(paths[i]).getLocationURI(), ifl1.getURI()); assertEquals(URIUtil.toURI(basePath+paths[i]).normalize(), ifl2.getURI()); } } private void deleteOnTearDown(ICProject cproject) { if (cproject != null) { projects.add(cproject); } } private void createExternalFile(File dest, String content) throws IOException { FileOutputStream fos = new FileOutputStream(dest); fos.write(content.getBytes()); fos.close(); } private URI makeDirectoryURI(String dir) throws URISyntaxException { URI uri = new File(dir).toURI(); return new URI(uri.toString() + "/"); } }