From 00fc40ee0b7f434f5c6f3ae6cda93f8e34628ed4 Mon Sep 17 00:00:00 2001 From: James Blackburn Date: Tue, 2 Jun 2009 17:14:46 +0000 Subject: [PATCH] Bug 269023 / Bug 278824 Additional EFS Error parsing tests --- .../tests/ErrorParserEfsFileMatchingTest.java | 121 +++++++- .../tests/filesystem/ram/MemoryFileStore.java | 82 ++++++ .../filesystem/ram/MemoryFileSystem.java | 52 ++++ .../tests/filesystem/ram/MemoryTree.java | 277 ++++++++++++++++++ .../internal/tests/filesystem/ram/Policy.java | 29 ++ core/org.eclipse.cdt.core.tests/plugin.xml | 9 + 6 files changed, 556 insertions(+), 14 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileStore.java create mode 100644 core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileSystem.java create mode 100644 core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryTree.java create mode 100644 core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/Policy.java diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserEfsFileMatchingTest.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserEfsFileMatchingTest.java index d4df4ddfd8d..9016e2f74da 100644 --- a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserEfsFileMatchingTest.java +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/errorparsers/tests/ErrorParserEfsFileMatchingTest.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.core.internal.errorparsers.tests; import java.io.ByteArrayInputStream; +import java.net.URI; import java.util.ArrayList; import junit.framework.Assert; @@ -27,6 +28,7 @@ import org.eclipse.cdt.core.errorparsers.AbstractErrorParser; import org.eclipse.cdt.core.errorparsers.ErrorPattern; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.core.internal.registry.ExtensionRegistry; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.ContributorFactoryOSGi; @@ -40,11 +42,13 @@ import org.eclipse.core.runtime.Platform; * properly locate and resolve filenames found in build output in case of EFS files/folders. */ public class ErrorParserEfsFileMatchingTest extends TestCase { + private static final String MAKE_ERRORPARSER_ID = "org.eclipse.cdt.core.MakeErrorParser"; + private String mockErrorParserId = null; + private final static String testName = "FindMatchingFilesEfsTest"; // Default project gets created once then used by all test cases. private IProject fProject = null; - private String mockErrorParserId = null; private ArrayList errorList; private final IMarkerGenerator markerGenerator = new IMarkerGenerator() { @@ -142,13 +146,31 @@ public class ErrorParserEfsFileMatchingTest extends TestCase { * * @param project - for which project to parse output. * @param buildDir - location of build for {@link ErrorParserManager}. + * @param errorParsers - error parsers used. * @param line - one line of output. * @throws Exception */ - private void parseOutput(IProject project, IPath buildDir, String line) throws Exception { - ErrorParserManager epManager = new ErrorParserManager(project, buildDir, markerGenerator, - new String[] { mockErrorParserId }); + private void parseOutput(IProject project, URI buildDirURI, String[] errorParsers, String line) throws Exception { + ErrorParserManager epManager = new ErrorParserManager(project, buildDirURI, markerGenerator, errorParsers); + line = line + '\n'; + epManager.write(line.getBytes(), 0, line.length()); + epManager.close(); + epManager.reportProblems(); + } + /** + * Convenience method to let {@link ErrorParserManager} parse one line of output. + * This method goes through the whole working cycle every time creating + * new {@link ErrorParserManager}. + * + * @param project - for which project to parse output. + * @param buildDir - location of build for {@link ErrorParserManager}. + * @param errorParsers - error parsers used. + * @param line - one line of output. + * @throws Exception + */ + private void parseOutput(IProject project, IPath buildDir, String[] errorParsers, String line) throws Exception { + ErrorParserManager epManager = new ErrorParserManager(project, buildDir, markerGenerator, errorParsers); line = line + '\n'; epManager.write(line.getBytes(), 0, line.length()); epManager.close(); @@ -159,23 +181,23 @@ public class ErrorParserEfsFileMatchingTest extends TestCase { * Convenience method to parse one line of output. */ private void parseOutput(IProject project, String buildDir, String line) throws Exception { - parseOutput(project, new Path(buildDir), line); + parseOutput(project, new Path(buildDir), new String[] {mockErrorParserId}, line); } -// /** -// * Convenience method to parse one line of output. -// * Search is done in project location. -// */ -// private void parseOutput(IProject project, String line) throws Exception { -// parseOutput(project, project.getLocation(), line); -// } + /** + * Convenience method to parse one line of output. + * Search is done in project location. + */ + private void parseOutput(IProject project, String line) throws Exception { + parseOutput(project, project.getLocation(), new String[] {mockErrorParserId}, line); + } /** * Convenience method to parse one line of output. * Search is done for current project in default location. */ private void parseOutput(String line) throws Exception { - parseOutput(fProject, fProject.getLocation(), line); + parseOutput(fProject, fProject.getLocation(), new String[] {mockErrorParserId}, line); } /** @@ -423,4 +445,75 @@ public class ErrorParserEfsFileMatchingTest extends TestCase { assertEquals("error",problemMarkerInfo.description); } -} \ No newline at end of file + /** + * Checks if a file from error output can be found. + * @throws Exception... + */ + public void testEfsProject() throws Exception { + IFile efsSmokeTest = ResourceHelper.createEfsFile(fProject, "efsSmokeTest.c", "mem:/efsSmokeTest.c"); + Assert.assertTrue(efsSmokeTest.exists()); + + IProject efsProject = ResourceHelper.createCDTProject("EfsProject", new URI("mem:/EfsProject")); + ResourceHelper.createFolder(efsProject, "Folder"); + ResourceHelper.createFile(efsProject, "Folder/testEfsProject.c"); + + parseOutput(efsProject, "testEfsProject.c:1:error"); + assertEquals(1, errorList.size()); + + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); + assertEquals("L/EfsProject/Folder/testEfsProject.c",problemMarkerInfo.file.toString()); + assertEquals("error",problemMarkerInfo.description); + } + + /** + * Checks if a file from error output can be found. + * @throws Exception... + */ + public void testEfsProjectBuildDirURI() throws Exception { + String fileName = "testEfsProjectBuildDirURI.c"; + + IProject efsProject = ResourceHelper.createCDTProject("EfsProject", new URI("mem:/EfsProject")); + ResourceHelper.createFolder(efsProject, "Folder"); + ResourceHelper.createFile(efsProject, "Folder/" + fileName); + ResourceHelper.createFolder(efsProject, "BuildDir"); + ResourceHelper.createFile(efsProject, "BuildDir/" + fileName); + + URI buildDirURI = new URI("mem:/EfsProject/BuildDir/"); + parseOutput(efsProject, buildDirURI, new String[] {mockErrorParserId}, fileName+":1:error"); + assertEquals(1, errorList.size()); + + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); + assertEquals("L/EfsProject/BuildDir/"+fileName,problemMarkerInfo.file.toString()); + assertEquals("error",problemMarkerInfo.description); + } + + /** + * Checks if a file from error output can be found. + * + * @throws Exception... + */ + public void testEfsProjectPushPopDirectory() throws Exception { + String fileName = "testEfsProjectPushPopDirectory.c"; + + IProject efsProject = ResourceHelper.createCDTProject("EfsProject", new URI("mem:/ProjectPushPopDirectory")); + ResourceHelper.createFolder(efsProject, "Folder"); + ResourceHelper.createFolder(efsProject, "Folder/SubFolder"); + ResourceHelper.createFile(efsProject, fileName); + ResourceHelper.createFile(efsProject, "Folder/"+fileName); + ResourceHelper.createFile(efsProject, "Folder/SubFolder/"+fileName); + + String lines = "make[1]: Entering directory `Folder'\n" + + "make[2]: Entering directory `SubFolder'\n" + + "make[2]: Leaving directory `SubFolder'\n" + + fileName+":1:error\n"; + + String[] errorParsers = {MAKE_ERRORPARSER_ID, mockErrorParserId }; + parseOutput(efsProject, efsProject.getLocation(), errorParsers, lines); + assertEquals(1, errorList.size()); + + ProblemMarkerInfo problemMarkerInfo = errorList.get(0); + assertEquals("L/EfsProject/Folder/"+fileName,problemMarkerInfo.file.toString()); + assertEquals(1,problemMarkerInfo.lineNumber); + assertEquals("error",problemMarkerInfo.description); + } +} diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileStore.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileStore.java new file mode 100644 index 00000000000..cce386693b2 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileStore.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 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 Gvozdev (Quoin Inc.) - contributed to CDT from org.eclipse.core.tests.resources v20090320 + *******************************************************************************/ +package org.eclipse.cdt.core.internal.tests.filesystem.ram; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import org.eclipse.core.filesystem.*; +import org.eclipse.core.filesystem.provider.FileStore; +import org.eclipse.core.runtime.*; + +/** + * In memory file system implementation used for testing. + */ +public class MemoryFileStore extends FileStore { + private static final MemoryTree TREE = MemoryTree.TREE; + + private final IPath path; + + public MemoryFileStore(IPath path) { + super(); + this.path = path.setDevice(null); + } + + public String[] childNames(int options, IProgressMonitor monitor) { + final String[] names = TREE.childNames(path); + return names == null ? EMPTY_STRING_ARRAY : names; + } + + public void delete(int options, IProgressMonitor monitor) { + TREE.delete(path); + } + + public IFileInfo fetchInfo(int options, IProgressMonitor monitor) { + return TREE.fetchInfo(path); + } + + public IFileStore getChild(String name) { + return new MemoryFileStore(path.append(name)); + } + + public String getName() { + final String name = path.lastSegment(); + return name == null ? "" : name; + } + + public IFileStore getParent() { + if (path.segmentCount() == 0) + return null; + return new MemoryFileStore(path.removeLastSegments(1)); + } + + public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException { + TREE.mkdir(path, (options & EFS.SHALLOW) == 0); + return this; + } + + public InputStream openInputStream(int options, IProgressMonitor monitor) throws CoreException { + return TREE.openInputStream(path); + } + + public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException { + return TREE.openOutputStream(path, options); + } + + public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException { + TREE.putInfo(path, info, options); + } + + public URI toURI() { + return MemoryFileSystem.toURI(path); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileSystem.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileSystem.java new file mode 100644 index 00000000000..6efae4e3664 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryFileSystem.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 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 Gvozdev (Quoin Inc.) - contributed to CDT from org.eclipse.core.tests.resources v20090320 + *******************************************************************************/ +package org.eclipse.cdt.core.internal.tests.filesystem.ram; + +import java.net.URI; +import java.net.URISyntaxException; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.provider.FileSystem; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * A test file system that keeps everything in memory. + */ +public class MemoryFileSystem extends FileSystem { + public static final String SCHEME_MEMORY = "mem"; + + /** + * Converts a path to a URI in the memory file system. + * @param path + * @return + */ + public static URI toURI(IPath path) { + try { + return new URI(MemoryFileSystem.SCHEME_MEMORY, path.setDevice(null).toPortableString(), null); + } catch (URISyntaxException e) { + //should not happen + throw new RuntimeException(e); + } + } + + public MemoryFileSystem() { + super(); + } + + public IFileStore getStore(URI uri) { + return new MemoryFileStore(Path.fromPortableString(uri.getSchemeSpecificPart())); + } + + public boolean isCaseSensitive() { + return true; + } +} diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryTree.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryTree.java new file mode 100644 index 00000000000..a9e45365bc1 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/MemoryTree.java @@ -0,0 +1,277 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 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 Gvozdev (Quoin Inc.) - contributed to CDT from org.eclipse.core.tests.resources v20090320 + *******************************************************************************/ +package org.eclipse.cdt.core.internal.tests.filesystem.ram; + +import java.io.*; +import java.util.ArrayList; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.provider.FileInfo; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +/** + * An in-memory file system. + */ +public class MemoryTree { + static class DirNode extends Node { + private final ArrayList children = new ArrayList(); + + DirNode(Node parent, String name) { + super(parent, name); + } + + void add(Node child) { + children.add(child); + } + + public String[] childNames() { + String[] names = new String[children.size()]; + for (int i = 0, imax = children.size(); i < imax; i++) { + Node child = (Node) children.get(i); + names[i] = child.getInfo(false).getName(); + } + return names; + } + + /** + * Returns the child with the given name, or null if not found. + * @param name + * @return + */ + Node getChild(String name) { + for (int i = 0, imax = children.size(); i < imax; i++) { + Node child = (Node) children.get(i); + if (child.getInfo(false).getName().equals(name)) + return child; + } + return null; + } + + protected void initializeInfo(FileInfo fileInfo) { + super.initializeInfo(fileInfo); + fileInfo.setDirectory(true); + } + + boolean isFile() { + return false; + } + + void remove(String name) { + Node child = getChild(name); + if (child != null) + children.remove(child); + } + + public String toString() { + return super.toString() + ' ' + children; + } + } + + static class FileNode extends Node { + byte[] contents = EMPTY_CONTENTS; + + FileNode(Node parent, String name) { + super(parent, name); + } + + boolean isFile() { + return true; + } + + public InputStream openInputStream() { + return new ByteArrayInputStream(contents); + } + + public OutputStream openOutputStream(final int options) { + return new ByteArrayOutputStream() { + public void close() throws IOException { + super.close(); + setContents(toByteArray(), options); + } + }; + } + + protected void setContents(byte[] bytes, int options) { + if ((options & EFS.APPEND) != 0) { + //create reference in case of concurrent modification + byte[] oldContents = this.contents; + byte[] newContents = new byte[oldContents.length + bytes.length]; + System.arraycopy(oldContents, 0, newContents, 0, oldContents.length); + System.arraycopy(bytes, 0, newContents, oldContents.length, bytes.length); + this.contents = newContents; + } else + this.contents = bytes; + info.setLastModified(System.currentTimeMillis()); + ((FileInfo) info).setLength(bytes.length); + } + } + + static abstract class Node { + protected IFileInfo info; + + Node(Node parent, String name) { + if (parent != null) + ((DirNode) parent).add(this); + FileInfo fileInfo = new FileInfo(name); + initializeInfo(fileInfo); + this.info = fileInfo; + } + + IFileInfo getInfo(boolean copy) { + return (IFileInfo) (copy ? ((FileInfo) info).clone() : info); + } + + protected void initializeInfo(FileInfo fileInfo) { + fileInfo.setExists(true); + fileInfo.setLastModified(System.currentTimeMillis()); + } + + abstract boolean isFile(); + + void putInfo(IFileInfo newInfo, int options) { + if ((options & EFS.SET_ATTRIBUTES) != 0) { + for (int i = 0; i < ALL_ATTRIBUTES.length; i++) + info.setAttribute(ALL_ATTRIBUTES[i], newInfo.getAttribute(ALL_ATTRIBUTES[i])); + } + if ((options & EFS.SET_LAST_MODIFIED) != 0) { + info.setLastModified(newInfo.getLastModified()); + } + } + + /** + * For debugging purposes only. + */ + public String toString() { + return info.getName(); + } + } + + static final int[] ALL_ATTRIBUTES = new int[] {EFS.ATTRIBUTE_ARCHIVE, EFS.ATTRIBUTE_EXECUTABLE, EFS.ATTRIBUTE_HIDDEN, EFS.ATTRIBUTE_READ_ONLY,}; + + public static final MemoryTree TREE = new MemoryTree(); + + static final byte[] EMPTY_CONTENTS = new byte[0]; + + private static final String ROOT_NAME = ""; + + private Node root = new DirNode(null, ROOT_NAME); + + private MemoryTree() { + // TREE singleton should be used rather than direct instantiation + } + + public String[] childNames(IPath path) { + Node node = findNode(path); + if (node == null || node.isFile()) + return null; + return ((DirNode) node).childNames(); + } + + public void delete(IPath path) { + //cannot delete the root + if (path.segmentCount() == 0) + return; + Node parent = findNode(path.removeLastSegments(1)); + if (parent == null || parent.isFile()) + return; + ((DirNode) parent).remove(path.lastSegment()); + + } + + /** + * Deletes the entire memory tree. Used during debugging and testing only. + */ + public void deleteAll() { + this.root = new DirNode(null, ROOT_NAME); + } + + /** + * Returns the file info for the given path. Never returns null. + * @param path + * @return + */ + public synchronized IFileInfo fetchInfo(IPath path) { + Node node = findNode(path); + if (node == null) + return new FileInfo(path.lastSegment()); + return node.getInfo(true); + } + + /** + * Returns the node at the given path, or null if not found. + * + * @param path + * @return + */ + private Node findNode(IPath path) { + Node current = root; + for (int i = 0, imax = path.segmentCount(); i < imax; i++) { + if (current == null || current.isFile()) + return null; + current = ((DirNode) current).getChild(path.segment(i)); + } + return current; + } + + public Node mkdir(IPath path, boolean deep) throws CoreException { + Node dir = findNode(path); + if (dir != null) { + if (dir.isFile()) + Policy.error("A file exists with this name: " + path); + return dir; + } + final IPath parentPath = path.removeLastSegments(1); + Node parent = findNode(parentPath); + if (parent != null) { + if (parent.isFile()) + Policy.error("Parent is a file: " + path); + } else { + if (!deep) + Policy.error("Parent does not exist: " + parentPath); + parent = mkdir(parentPath, deep); + } + //create the child directory + return new DirNode(parent, path.lastSegment()); + } + + public InputStream openInputStream(IPath path) throws CoreException { + Node node = findNode(path); + if (node == null) + Policy.error("File not found: " + path); + if (!node.isFile()) + Policy.error("Cannot open stream on directory: " + path); + return ((FileNode) node).openInputStream(); + } + + public OutputStream openOutputStream(IPath path, int options) throws CoreException { + Node node = findNode(path); + //if we already have such a file, just open a stream on it + if (node instanceof DirNode) + Policy.error("Could not create file: " + path); + if (node instanceof FileNode) + return ((FileNode) node).openOutputStream(options); + //if the parent exists we can create the file + Node parent = findNode(path.removeLastSegments(1)); + if (!(parent instanceof DirNode)) + Policy.error("Could not create file: " + path); + node = new FileNode(parent, path.lastSegment()); + return ((FileNode) node).openOutputStream(options); + } + + public void putInfo(IPath path, IFileInfo info, int options) throws CoreException { + Node node = findNode(path); + if (node == null) + Policy.error("File not found: " + path); + node.putInfo(info, options); + } +} diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/Policy.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/Policy.java new file mode 100644 index 00000000000..42fbb11e259 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/core/internal/tests/filesystem/ram/Policy.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 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 Gvozdev (Quoin Inc.) - contributed to CDT from org.eclipse.core.tests.resources v20090320 + *******************************************************************************/ +package org.eclipse.cdt.core.internal.tests.filesystem.ram; + +import org.eclipse.core.runtime.*; + +/** + * + */ +public class Policy { + + public static void error(String message) throws CoreException { + throw new CoreException(new Status(IStatus.ERROR, "org.eclipse.cdt.core.tests.internal.filesystem.ram", 1, message, null)); + } + + private Policy() { + super(); + } + +} diff --git a/core/org.eclipse.cdt.core.tests/plugin.xml b/core/org.eclipse.cdt.core.tests/plugin.xml index d4eb43ab32e..2ea4018d2dc 100644 --- a/core/org.eclipse.cdt.core.tests/plugin.xml +++ b/core/org.eclipse.cdt.core.tests/plugin.xml @@ -150,4 +150,13 @@ class="org.eclipse.cdt.core.internal.index.provider.test.Providers$Dummy5"> + + + + + +