blob: b103a4842312f9f2ffcd4729a71309a56cbdaf9e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2016 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
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.testplugin;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipFile;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IAdditionalInput;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IHoldsOptions;
import org.eclipse.cdt.managedbuilder.core.IInputType;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IManagedProject;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IProjectType;
import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature;
import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver;
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.IWorkspaceDescription;
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.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.jobs.Job;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.internal.ide.filesystem.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
public class ManagedBuildTestHelper {
private static final String rcbsToolId = "org.eclipse.cdt.managedbuilder.ui.rcbs"; //$NON-NLS-1$
private static final String rcbsToolName = "Resource Custom Build Step"; //$NON-NLS-1$
private static final String rcbsToolInputTypeId = "org.eclipse.cdt.managedbuilder.ui.rcbs.inputtype"; //$NON-NLS-1$
private static final String rcbsToolInputTypeName = "Resource Custom Build Step Input Type"; //$NON-NLS-1$
private static final String rcbsToolOutputTypeId = "org.eclipse.cdt.managedbuilder.ui.rcbs.outputtype"; //$NON-NLS-1$
private static final String rcbsToolOutputTypeName = "Resource Custom Build Step Output Type"; //$NON-NLS-1$
/* (non-Javadoc)
* Create a new project named <code>name</code> or return the project in
* the workspace of the same name if it exists.
*
* @param name The name of the project to create or retrieve.
* @return
* @throws CoreException
*/
static public IProject createProject(
final String name,
final IPath location,
final String projectId,
final String projectTypeId) throws CoreException {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
final IProject newProjectHandle = root.getProject(name);
IProject project = null;
if (!newProjectHandle.exists()) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if (projectId.equals(ManagedBuilderCorePlugin.MANAGED_MAKE_PROJECT_ID)) {
createNewManagedProject(newProjectHandle, name, location, projectId, projectTypeId);
project = newProjectHandle;
} else {
IWorkspaceDescription workspaceDesc = workspace.getDescription();
workspaceDesc.setAutoBuilding(false);
workspace.setDescription(workspaceDesc);
IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName());
//description.setLocation(root.getLocation());
project = CCorePlugin.getDefault().createCProject(description, newProjectHandle, new NullProgressMonitor(), ManagedBuilderCorePlugin.MANAGED_MAKE_PROJECT_ID);
}
} else {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
newProjectHandle.refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
};
NullProgressMonitor monitor = new NullProgressMonitor();
workspace.run(runnable, root, IWorkspace.AVOID_UPDATE, monitor);
project = newProjectHandle;
}
// Open the project if we have to
if (!project.isOpen()) {
project.open(new NullProgressMonitor());
// 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
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
}
}
return project;
}
static public IProject createProject(
final String name,
final String projectTypeId) {
try {
return createProject(name,
null,
ManagedBuilderCorePlugin.MANAGED_MAKE_PROJECT_ID,
projectTypeId);
} catch (CoreException e) {
TestCase.fail(e.getLocalizedMessage());
}
return null;
}
static public IFile createFile(IProject project, String name){
return createFile(project, name, new ByteArrayInputStream(new byte[0]));
}
static public IFile createFile(IProject project, String name, String contents){
return createFile(project, name, new ByteArrayInputStream(contents.getBytes()));
}
static public IFile createFile(IProject project, String name, InputStream contents){
IFile file = project.getFile(name);
if( !file.exists() ){
try {
IPath dirPath = file.getFullPath().removeLastSegments(1).removeFirstSegments(1);
if(dirPath.segmentCount() > 0){
IFolder rc = project.getFolder(dirPath);
if(!rc.exists()){
rc.create(true, true, null);
}
}
// file.create( new ByteArrayInputStream( "#include <stdio.h>\n extern void bar(); \n int main() { \nprintf(\"Hello, World!!\"); \n bar();\n return 0; }".getBytes() ), false, null );
file.create(contents, false, null );
} catch (CoreException e) {
TestCase.fail(e.getLocalizedMessage());
}
}
return file;
}
static public IFolder createFolder(IProject project, String name){
IFolder folder = project.getFolder(name);
if( !folder.exists() ){
try {
IPath dirPath = folder.getFullPath().removeLastSegments(1).removeFirstSegments(1);
if(dirPath.segmentCount() > 0){
IFolder rc = project.getFolder(dirPath);
if(!rc.exists()){
rc.create(true, true, null);
}
}
// file.create( new ByteArrayInputStream( "#include <stdio.h>\n extern void bar(); \n int main() { \nprintf(\"Hello, World!!\"); \n bar();\n return 0; }".getBytes() ), false, null );
folder.create(true , false, null );
} catch (CoreException e) {
TestCase.fail(e.getLocalizedMessage());
}
}
return folder;
}
/**
* Remove the <code>IProject</code> with the name specified in the argument from the
* receiver's workspace.
*
* @param name
*/
static public void removeProject(String name) {
ResourceHelper.joinIndexerBeforeCleanup(ManagedBuildTestHelper.class.getName());
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
final IProject project = root.getProject(name);
if (project.exists()) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
System.gc();
System.runFinalization();
project.delete(true, true, null);
}
};
NullProgressMonitor monitor = new NullProgressMonitor();
try {
workspace.run(runnable, root, IWorkspace.AVOID_UPDATE, monitor);
} catch (CoreException e2) {
Assert.fail("failed to remove the project: " + e2.getLocalizedMessage());
}
}
}
/**
* Import a test project into the test workspace.
* Project template must be located under:
* <ul>
* <li>resources/{path}/{name}/{name}.zip</li>
* <li>resources/{path}/{name}.zip</li>
* <li>resources/{path}/{name}</li>
* </ul>
* Where name is either an expanded or zip compressed project.
* @param name - name of the project to import
* @param path - path relative to /resources
* @return IProject or throws AssertionFailedError on failure
*/
public static IProject loadProject(String name, String path) {
IPath zipPath = new Path("resources").append(path).append(name).append(name).addFileExtension("zip");
File zipFile = CTestPlugin.getFileInPlugin(zipPath);
if (zipFile == null) {
zipPath = new Path("resources").append(path).append(name).addFileExtension("zip");
zipFile = CTestPlugin.getFileInPlugin(zipPath);
}
// Try loading as a project directory
if (zipFile == null) {
zipPath = new Path("resources").append(path).append(name);
zipFile = CTestPlugin.getFileInPlugin(zipPath);
}
if (zipFile == null) {
Assert.fail("zip file " + zipPath.toString() + " is missing.");
/* never get here */
return null;
}
try {
return createProject(name, zipFile, null, null);
} catch(Exception e){
Assert.fail("fail to create the project: " + e.getLocalizedMessage());
}
/* never get here */
return null;
}
static public IProject createProject(String projectName, File importFrom, IPath location, String projectTypeId) throws CoreException, InvocationTargetException, IOException {
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
IProject project= root.getProject(projectName);
if (project.exists())
removeProject(projectName);
IPath destPath = (location != null) ?
location :
project.getFullPath();
if (importFrom != null) {
IImportStructureProvider importStructure;
Object importRoot;
if (importFrom.isFile()) {
importStructure = new ZipFileStructureProvider(new ZipFile(importFrom));
importRoot = ((ZipFileStructureProvider)importStructure).getRoot();
} else {
importStructure = new FileSystemStructureProvider();
importRoot = importFrom;
}
try {
ImportOperation op= new ImportOperation(destPath, importRoot, importStructure, new IOverwriteQuery() {
@Override
public String queryOverwrite(String file) {
return ALL;
}
});
op.setCreateContainerStructure(false);
op.run(null);
} catch (InterruptedException e) {
// should not happen
Assert.assertTrue(false);
}
}
return createProject(projectName, location, ManagedBuilderCorePlugin.MANAGED_MAKE_PROJECT_ID, projectTypeId);
}
static public IProject createNewManagedProject(IProject newProjectHandle,
final String name,
final IPath location,
final String projectId,
final String projectTypeId) throws CoreException {
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
final IProject project = newProjectHandle;
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
// Create the base project
IWorkspaceDescription workspaceDesc = workspace.getDescription();
workspaceDesc.setAutoBuilding(false);
workspace.setDescription(workspaceDesc);
IProjectDescription description = workspace.newProjectDescription(project.getName());
if (location != null) {
description.setLocation(location);
}
CCorePlugin.getDefault().createCProject(description, project, new NullProgressMonitor(), projectId);
// Add the managed build nature and builder
addManagedBuildNature(project);
// Find the base project type definition
IProjectType projType = ManagedBuildManager.getProjectType(projectTypeId);
Assert.assertNotNull(projType);
// Create the managed-project (.cdtbuild) for our project that builds an executable.
IManagedProject newProject = null;
try {
newProject = ManagedBuildManager.createManagedProject(project, projType);
} catch (Exception e) {
Assert.fail("Failed to create managed project for: " + project.getName());
return;
}
Assert.assertEquals(newProject.getName(), projType.getName());
Assert.assertFalse(newProject.equals(projType));
ManagedBuildManager.setNewProjectVersion(project);
// Copy over the configs
IConfiguration defaultConfig = null;
IConfiguration[] configs = projType.getConfigurations();
for (int i = 0; i < configs.length; ++i) {
// Make the first configuration the default
if (i == 0) {
defaultConfig = newProject.createConfiguration(configs[i], projType.getId() + "." + i);
} else {
newProject.createConfiguration(configs[i], projType.getId() + "." + i);
}
}
ManagedBuildManager.setDefaultConfiguration(project, defaultConfig);
IConfiguration cfgs[] = newProject.getConfigurations();
for(int i = 0; i < cfgs.length; i++){
cfgs[i].setArtifactName(newProject.getDefaultArtifactName());
}
ManagedBuildManager.getBuildInfo(project).setValid(true);
}
};
NullProgressMonitor monitor = new NullProgressMonitor();
try {
workspace.run(runnable, root, IWorkspace.AVOID_UPDATE, monitor);
} catch (CoreException e2) {
Assert.fail(e2.getLocalizedMessage());
}
// 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
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
}
// Initialize the path entry container
IStatus initResult = ManagedBuildManager.initBuildInfoContainer(project);
if (initResult.getCode() != IStatus.OK) {
Assert.fail("Initializing build information failed for: " + project.getName() + " because: " + initResult.getMessage());
}
return project;
}
static public void addManagedBuildNature (IProject project) {
// Create the buildinformation object for the project
IManagedBuildInfo info = ManagedBuildManager.createBuildInfo(project);
Assert.assertNotNull(info);
// info.setValid(true);
// Add the managed build nature
try {
ManagedCProjectNature.addManagedNature(project, new NullProgressMonitor());
ManagedCProjectNature.addManagedBuilder(project, new NullProgressMonitor());
} catch (CoreException e) {
Assert.fail("Test failed on adding managed build nature or builder: " + e.getLocalizedMessage());
}
// Associate the project with the managed builder so the clients can get proper information
ICDescriptor desc = null;
try {
desc = CCorePlugin.getDefault().getCProjectDescription(project, true);
desc.remove(CCorePlugin.BUILD_SCANNER_INFO_UNIQ_ID);
desc.create(CCorePlugin.BUILD_SCANNER_INFO_UNIQ_ID, ManagedBuildManager.INTERFACE_IDENTITY);
} catch (CoreException e) {
Assert.fail("Test failed on adding managed builder as scanner info provider: " + e.getLocalizedMessage());
return;
}
try {
desc.saveProjectData();
} catch (CoreException e) {
Assert.fail("Test failed on saving the ICDescriptor data: " + e.getLocalizedMessage()); }
}
static public boolean compareBenchmarks(final IProject project, IPath testLocationBase, IPath[] files, IPath benchmarkLocationBase) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
};
try {
NullProgressMonitor monitor = new NullProgressMonitor();
workspace.run(runnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, monitor);
} catch (Exception e) {
Assert.fail("File " + files[0].lastSegment() + " - project refresh failed.");
}
for (int i=0; i<files.length; i++) {
IPath testFileLocation = testLocationBase.append(files[i]);
IPath benchmarkFileLocation = benchmarkLocationBase.append("Benchmarks").append(files[i]);
if (isMakefile(testFileLocation)) {
if (compareMakefiles(testFileLocation, benchmarkFileLocation)) {
continue;
}
}
if (isDependencyFile(testFileLocation)) {
if (compareDependencyFiles(testFileLocation, benchmarkFileLocation)) {
continue;
}
}
StringBuffer testBuffer = readContentsStripLineEnds(project, testFileLocation);
StringBuffer benchmarkBuffer = readContentsStripLineEnds(project, benchmarkFileLocation);
if (!testBuffer.toString().equals(benchmarkBuffer.toString())) {
StringBuffer buffer = new StringBuffer();
buffer.append("File ").append(testFileLocation.lastSegment()).append(" does not match its benchmark.\n ");
buffer.append("expected:\n ");
buffer.append('"').append(benchmarkBuffer).append('"');
buffer.append("\n\n ");
buffer.append("but was:\n ");
buffer.append('"').append(testBuffer).append('"');
buffer.append("\n\n ");
buffer.append(">>>>>>>>>>>>>>>start diff: \n");
String location1 = benchmarkFileLocation.isAbsolute()
? benchmarkFileLocation.toString()
: getFileLocation(project, benchmarkFileLocation);
String location2 = testFileLocation.isAbsolute()
? testFileLocation.toString()
: getFileLocation(project, testFileLocation);
String diff = DiffUtil.getInstance().diff(location1, location2);
if(diff == null)
diff = "!diff failed!";
buffer.append(diff);
buffer.append("\n<<<<<<<<<<<end diff");
buffer.append("\n\n ");
Assert.fail(buffer.toString());
}
}
return true;
}
private static boolean isMakefile(IPath file) {
String ext = file.getFileExtension();
if (ext==null) {
String name = file.lastSegment();
return name!=null && (
name.equals("makefile")
|| name.equals("Makefile")
|| name.equals("GNUmakefile")
);
}
return ext.equals("mk");
}
private static boolean isDependencyFile(IPath file) {
String ext = file.getFileExtension();
return "d".equals(ext);
}
/**
* Compare makefiles using a bunch of heuristics to avoid ordering mismatches
*
* @param testFile - location of actual makefile
* @param benchmarkFile - location of the benchmark file
* @return {@code true} if matches, {@code false} otherwise
*/
private static boolean compareMakefiles(IPath testFile, IPath benchmarkFile) {
final String ECHO_INVOKING_PATTERN = " @echo 'Invoking: .* C\\+\\+ .*'";
final String IFNEQ_PATTERN = "ifneq \\(\\$\\(strip \\$\\(.*\\)\\),\\)";
final String INCLUDE_PATTERN = "-include \\$\\(.*\\)";
final String MACRO_PATTERN = "\\S* [:+]=.*";
final String EMPTY_MACRO_PATTERN = "\\S* :=";
final String WORKSPACE_DIR_STR = CdtVariableResolver.createVariableReference(CdtVariableResolver.VAR_WORKSPACE_DIR_PATH);
ArrayList<String> testArray = mergeContinuationLines(getContents(testFile));
ArrayList<String> benchmarkArray = mergeContinuationLines(getContents(benchmarkFile));
Set<String> testNotMatchingLines = new TreeSet<String>();
Set<String> benchNotMatchingLines = new TreeSet<String>();
Set<String> extraLines = new TreeSet<String>();
for (int i=0;i<benchmarkArray.size() || i<testArray.size();i++) {
if (!(i<benchmarkArray.size())) {
System.err.println(testFile.lastSegment()+": extra line =["+testArray.get(i)+ "] not in benchmark. File "+testFile);
System.err.println(testFile.lastSegment()+": benchmark file "+benchmarkFile);
extraLines.add(testArray.get(i));
continue;
}
if (!(i<testArray.size())) {
System.err.println(testFile.lastSegment()+": missing line =["+benchmarkArray.get(i)+ "] comparing to benchmark. File "+testFile);
System.err.println(testFile.lastSegment()+": benchmark file "+benchmarkFile);
extraLines.add(benchmarkArray.get(i));
continue;
}
String testLine = testArray.get(i);
String benchmarkLine = benchmarkArray.get(i);
if (!testLine.equals(benchmarkLine)) {
if (testLine.startsWith(" -$(RM) ")) {
// accommodate to arbitrary order of 'rm' parameters
final String DELIMITERS = "[ $]";
String[] testMacros = new TreeSet<String>(Arrays.asList(testLine.split(DELIMITERS))).toArray(new String[0]);
String[] benchMacros = new TreeSet<String>(Arrays.asList(benchmarkLine.split(DELIMITERS))).toArray(new String[0]);
if (testMacros.length!=benchMacros.length) {
return false;
}
for (int j=0;j<testMacros.length;j++) {
if (!testMacros[j].equals(benchMacros[j])) {
return false;
}
}
} else if (testLine.matches(ECHO_INVOKING_PATTERN) && benchmarkLine.matches(ECHO_INVOKING_PATTERN)) {
// accommodate for variable linker name (GCC vs. Cygwin)
continue;
} else if (testLine.matches(IFNEQ_PATTERN) && benchmarkLine.matches(IFNEQ_PATTERN)) {
// accommodate for variable order of different macro's blocks (see also INCLUDE_PATTERN)
// ifneq ($(strip $(CXX_DEPS)),)
// -include $(CXX_DEPS)
// endif
testNotMatchingLines.add(testLine);
benchNotMatchingLines.add(benchmarkLine);
} else if (testLine.matches(INCLUDE_PATTERN) && benchmarkLine.matches(INCLUDE_PATTERN)) {
// accommodate for variable order of different macro's blocks (see IFNEQ_PATTERN)
testNotMatchingLines.add(testLine);
benchNotMatchingLines.add(benchmarkLine);
} else if (testLine.matches(MACRO_PATTERN) && benchmarkLine.matches(MACRO_PATTERN)) {
// accommodate for variable order of macros
testNotMatchingLines.add(testLine);
benchNotMatchingLines.add(benchmarkLine);
} else if (benchmarkLine.contains(WORKSPACE_DIR_STR)) {
String[] benchmarkSubstrings = benchmarkLine.split(" ");
String[] testSubstrings = testLine.split(" ");
if (testSubstrings.length!=benchmarkSubstrings.length) {
System.err.println("Following lines do not match ("+testFile.lastSegment()+"):");
System.err.println("actual : ["+testLine+"], file "+testFile);
System.err.println("expected: ["+benchmarkLine+"], file "+benchmarkFile);
return false;
}
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
final IWorkspaceRoot root = workspace.getRoot();
final String workspaceLocation = root.getLocation().toOSString();
final String platformFileSeparator = System.getProperty("file.separator", Character.toString(IPath.SEPARATOR)); //$NON-NLS-1$
for (int j=0;j<testSubstrings.length;j++) {
String testSubstring = testSubstrings[j];
String benchmarkSubstring = benchmarkSubstrings[j];
if (benchmarkSubstring.contains(WORKSPACE_DIR_STR)) {
benchmarkSubstring = benchmarkSubstring
.replace("/", platformFileSeparator)
.replace(WORKSPACE_DIR_STR,workspaceLocation);
}
if (!testSubstring.equals(benchmarkSubstring)) {
System.err.println("Following lines do not match ("+testFile.lastSegment()+"):");
System.err.println("actual : ["+testLine+"], file "+testFile);
System.err.println("expected: ["+benchmarkLine+"], file "+benchmarkFile);
System.err.println("substring actual : ["+testSubstring+"], file "+testFile);
System.err.println("substring expected: ["+benchmarkSubstring+"], file "+benchmarkFile);
return false;
}
}
} else {
System.err.println("Following lines do not match ("+testFile.lastSegment()+"):");
System.err.println("actual : ["+testLine+"], file "+testFile);
System.err.println("expected: ["+benchmarkLine+"], file "+benchmarkFile);
return false;
}
}
}
if (testArray.size()!=benchmarkArray.size()) {
System.err.println("testArray.size="+testArray.size()+ " while benchmarkArray.size="+benchmarkArray.size());
// Ignore benign differences
for (String line : extraLines) {
if (line==null || line.length()==0) {
continue;
}
if (line.matches(EMPTY_MACRO_PATTERN)) {
continue;
}
return false;
}
}
// Check if all collected lines match irrespective of order
String[] testNotMatchingLinesArray = testNotMatchingLines.toArray(new String[0]);
String[] benchNotMatchingLinesArray = benchNotMatchingLines.toArray(new String[0]);
for (int i=0;i<testNotMatchingLinesArray.length;i++) {
if (! testNotMatchingLinesArray[i].equals(benchNotMatchingLinesArray[i])) {
System.err.println("Following line is missing ("+testFile.lastSegment()+"):");
if (testNotMatchingLinesArray[i].compareTo(benchNotMatchingLinesArray[i]) < 0) {
System.err.println("line ["+testNotMatchingLinesArray[i]+"], missing in file "+benchmarkFile);
} else {
System.err.println("line ["+benchNotMatchingLinesArray[i]+"], missing in file "+testFile);
}
return false;
}
}
return true;
}
/**
* Compare dependency files *.d using some of heuristics to avoid mismatches
* related to different gcc versions
*
* @param testFile - location of actual file
* @param benchmarkFile - location of the benchmark file
* @return {@code true} if matches, {@code false} otherwise
*/
private static boolean compareDependencyFiles(IPath testFile, IPath benchmarkFile) {
boolean result = true;
ArrayList<String> testArray = getContents(testFile);
ArrayList<String> benchmarkArray = getContents(benchmarkFile);
for (int i=0;i<benchmarkArray.size() || i<testArray.size();i++) {
if (!(i<benchmarkArray.size())) {
System.err.println(testFile.lastSegment()+": extra line =["+testArray.get(i)+ "] not in benchmark. File "+testFile);
System.err.println(testFile.lastSegment()+": benchmark file "+benchmarkFile);
continue;
}
if (!(i<testArray.size())) {
System.err.println(testFile.lastSegment()+": missing line =["+benchmarkArray.get(i)+ "] comparing to benchmark. File "+testFile);
System.err.println(testFile.lastSegment()+": benchmark file "+benchmarkFile);
continue;
}
String testLine = testArray.get(i);
String benchmarkLine = benchmarkArray.get(i);
if (!testLine.equals(benchmarkLine)) {
// Accommodate for differences in amount of leading and trailing spaces
if (testLine.startsWith(" ") && benchmarkLine.startsWith(" ")) {
String testLineTrimmed = testLine;
String benchmarkLineTrimmed = benchmarkLine;
if (testLineTrimmed.endsWith("\\") && benchmarkLineTrimmed.endsWith("\\")) {
// trim ending "\"
testLineTrimmed = testLineTrimmed.substring(0, testLineTrimmed.length()-1);
benchmarkLineTrimmed = benchmarkLineTrimmed.substring(0, benchmarkLineTrimmed.length()-1);
}
if (testLineTrimmed.trim().equals(benchmarkLineTrimmed.trim())) {
continue;
}
System.err.println("Following lines do not match ("+testFile.lastSegment()+"):");
System.err.println("actual : ["+testLine+"], file "+testFile);
System.err.println("expected: ["+benchmarkLine+"], file "+benchmarkFile);
result = false;
}
}
}
return result;
}
private static ArrayList<String> getContents(IPath fullPath) {
ArrayList<String> lines = new ArrayList<String>();
try {
BufferedReader in = new BufferedReader(new FileReader(fullPath.toFile()));
String line;
do {
line = in.readLine();
if (line!=null) {
lines.add(line);
}
} while (line !=null);
} catch (IOException e) {
Assert.fail("File " + fullPath.toString() + " could not be read: " + e.getLocalizedMessage());
}
return lines;
}
private static ArrayList<String> mergeContinuationLines(ArrayList<String> lines) {
for (int i=0;i<lines.size();) {
String line = lines.get(i);
if (line.endsWith("\\") && i+1<lines.size()) {
lines.set(i, line.substring(0, line.length()-1)+lines.get(i+1));
lines.remove(i+1);
// do not advance i and check the renewed line again
continue;
}
i++;
}
return lines;
}
static public boolean compareBenchmarks(final IProject project, IPath testDir, String[] fileNames) {
return compareBenchmarks(project, testDir, new Path("benchmarks").append(testDir), fileNames);
}
static public boolean compareBenchmarks(final IProject project, IPath testDir, IPath benchmarkDir, String[] fileNames) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
};
try {
NullProgressMonitor monitor = new NullProgressMonitor();
workspace.run(runnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, monitor);
} catch (Exception e) {
Assert.fail("File " + fileNames[0] + " - project refresh failed.");
}
IFolder testFolder = (IFolder)project.findMember(testDir);
IFolder bmFolder = (IFolder)project.findMember(benchmarkDir);
return compareBenchmarks(testFolder, bmFolder, fileNames);
}
static public boolean compareBenchmarks(IFolder testFolder, IFolder bmFolder, String[] fileNames) {
Assert.assertNotNull(testFolder);
Assert.assertNotNull(bmFolder);
for (int i=0; i<fileNames.length; i++) {
IFile tFile = testFolder.getFile(fileNames[i]);
IFile bmFile = bmFolder.getFile(fileNames[i]);
if(!tFile.exists() && !bmFile.exists())
continue;
compareBenchmarks(tFile, bmFile);
}
return true;
}
static public boolean compareBenchmarks(IFile tFile, IFile bmFile) {
IPath tFileLocation = tFile.getLocation();
IPath bmFileLocation = bmFile.getLocation();
if (isMakefile(tFileLocation)) {
if (compareMakefiles(tFileLocation, bmFileLocation)) {
return true;
}
}
if (isDependencyFile(tFileLocation)) {
if (compareDependencyFiles(tFileLocation, bmFileLocation)) {
return true;
}
}
StringBuffer testBuffer = readContentsStripLineEnds(tFile);
StringBuffer benchmarkBuffer = readContentsStripLineEnds(bmFile);
if (!testBuffer.toString().equals(benchmarkBuffer.toString())) {
StringBuffer buffer = new StringBuffer();
buffer.append("File ").append(tFile.getName()).append(" does not match its benchmark.\n ");
buffer.append("expected:\n ");
buffer.append('"').append(benchmarkBuffer).append('"');
buffer.append("\n\n ");
buffer.append("but was:\n ");
buffer.append('"').append(testBuffer).append('"');
buffer.append("\n\n ");
buffer.append(">>>>>>>>>>>>>>>start diff: \n");
String location1 = getFileLocation(bmFile.getProject(), bmFile.getProjectRelativePath());
String location2 = getFileLocation(tFile.getProject(), tFile.getProjectRelativePath());
String diff = DiffUtil.getInstance().diff(location1, location2);
if(diff == null)
diff = "!diff failed!";
buffer.append(diff);
buffer.append("\n<<<<<<<<<<<end diff");
buffer.append("\n\n ");
Assert.fail(buffer.toString());
}
return true;
}
static public boolean verifyFilesDoNotExist(final IProject project, IPath testDir, IPath[] files) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
};
try {
NullProgressMonitor monitor = new NullProgressMonitor();
workspace.run(runnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, monitor);
} catch (Exception e) {
Assert.fail("File " + files[0].lastSegment() + " - project refresh failed.");
}
for (int i=0; i<files.length; i++) {
IPath testFile = testDir.append(files[i]);
IPath fullPath = project.getLocation().append(testFile);
try {
if (fullPath.toFile().exists()) {
Assert.fail("File " + testFile.lastSegment() + " unexpectedly found.");
return false;
}
} catch (Exception e) {
Assert.fail("File " + fullPath.toString() + " could not be referenced.");
}
}
return true;
}
static public String getFileLocation(IProject project, IPath path){
return project.getLocation().append(path).toString();
}
static public StringBuffer readContentsStripLineEnds(IFile file) {
return readContentsStripLineEnds(file.getProject(), file.getProjectRelativePath());
}
static public StringBuffer readContentsStripLineEnds(IProject project, IPath path) {
StringBuffer buff = new StringBuffer();
IPath fullPath = path;
if (!fullPath.isAbsolute()) {
fullPath = project.getLocation().append(path);
}
try {
FileReader input = null;
try {
input = new FileReader(fullPath.toFile());
} catch (Exception e) {
Assert.fail("File " + fullPath.toString() + " could not be read: " + e.getLocalizedMessage());
}
//InputStream input = file.getContents(true); // A different way to read the file...
int c;
do {
c = input.read();
if (c == -1) break;
if (c != '\r' && c != '\n') {
buff.append((char)c);
}
} while (c != -1);
input.close();
} catch (Exception e) {
Assert.fail("File " + fullPath.toString() + " could not be read.");
}
return buff;
}
static public IPath copyFilesToTempDir(IPath srcDir, IPath tmpRootDir, IPath tmpSubDir, IPath[] files) {
IPath tmpSrcDir = null;
tmpSrcDir = tmpRootDir.append(tmpSubDir);
if (tmpRootDir.toString().equalsIgnoreCase(tmpSrcDir.toString())) {
Assert.fail("Temporary sub-directory cannot be the empty string.");
} else {
File tmpSrcDirFile = tmpSrcDir.toFile();
if (tmpSrcDirFile.exists()) {
// Make sure that this is the expected directory before we delete it...
if (tmpSrcDir.lastSegment().equals(tmpSubDir.lastSegment())) {
deleteDirectory(tmpSrcDirFile);
} else {
Assert.fail("Temporary directory " + tmpSrcDirFile.toString() + " already exists.");
}
}
tmpSrcDirFile.mkdir();
if (!tmpSrcDirFile.exists()) {
Assert.fail("Can't create temporary directory " + tmpSrcDirFile.toString());
}
for (int i=0; i<files.length; i++) {
IPath file = files[i];
IPath srcFile = srcDir.append(file);
FileReader srcReader = null;
try {
srcReader = new FileReader(srcFile.toFile());
} catch (Exception e) {
Assert.fail("File " + file.toString() + " could not be read.");
return null;
}
if (file.segmentCount() > 1) {
IPath newDir = tmpSrcDir;
do {
IPath dir = file.uptoSegment(1);
newDir = newDir.append(dir);
file = file.removeFirstSegments(1);
newDir.toFile().mkdir();
if (!newDir.toFile().exists()) {
Assert.fail("Can't create temporary directory " + tmpSrcDirFile.toString());
}
} while (file.segmentCount() > 1);
}
IPath destFile = tmpSrcDir.append(files[i]);
FileWriter writer = null;
try {
writer = new FileWriter(destFile.toFile());
} catch (Exception e) {
Assert.fail("File " + files[i].toString() + " could not be written.");
return null;
}
try {
int c;
do {
c = srcReader.read();
if (c == -1) break;
writer.write(c);
} while (c != -1);
srcReader.close();
writer.close();
} catch (Exception e) {
Assert.fail("File " + file.toString() + " could not be copied.");
}
}
}
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
for (IFile rc : root.findFilesForLocation(tmpSrcDir)) {
try {
rc.refreshLocal(IFile.DEPTH_INFINITE, null);
} catch (CoreException e) {
// ignore exception
}
}
return tmpSrcDir;
}
static public void deleteTempDir(IPath tmpRootDir, IPath tmpSubDir, IPath[] files) {
IPath tmpSrcDir = null;
tmpSrcDir = tmpRootDir.append(tmpSubDir);
if (tmpRootDir.toString().equalsIgnoreCase(tmpSrcDir.toString())) {
Assert.fail("Temporary sub-directory cannot be the empty string.");
} else {
File tmpSrcDirFile = tmpSrcDir.toFile();
if (tmpSrcDirFile.exists()) {
for (int i=0; i<files.length; i++) {
// Delete the file
IPath thisFile = tmpSrcDir.append(files[i]);
thisFile.toFile().delete();
}
// Delete the dir
tmpSrcDirFile.delete();
}
tmpRootDir.toFile().delete();
}
}
/*
* Cloned from core CProjectHelper
*/
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) {
Assert.fail(getMessage(e2.getStatus()));
}
}
}
}
/*
* Cloned from core CProjectHelper
*/
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();
}
static private void deleteDirectory(File dir) {
File[] toDelete = dir.listFiles();
for (int i=0; i<toDelete.length; i++) {
File fileToDelete = toDelete[i];
if (fileToDelete.isDirectory()) {
deleteDirectory(fileToDelete);
}
fileToDelete.delete();
}
dir.delete();
}
public static ITool createRcbsTool(IConfiguration cfg, String file, String inputs, String outputs, String cmds){
IProject project = cfg.getOwner().getProject();
IResource f = project.findMember(file);
Assert.assertTrue("file does not exist", f != null);
Assert.assertEquals("resource is not a file", f.getType(), IResource.FILE);
return createRcbsTool(cfg, (IFile)f, inputs, outputs, cmds);
}
public static ITool createRcbsTool(IConfiguration cfg, IFile file, String inputs, String outputs, String cmds){
IResourceConfiguration rcCfg = cfg.getResourceConfiguration(file.getFullPath().toString());
if(rcCfg == null)
rcCfg = cfg.createResourceConfiguration(file);
Assert.assertTrue("failed to create resource configuration", rcCfg != null);
ITool tool = getRcbsTool(rcCfg, true);
setRcbsInputs(tool, inputs);
setRcbsOutputs(tool, outputs);
tool.setToolCommand(cmds);
tool.setAnnouncement("default test rcbs announcement");
rcCfg.setRcbsApplicability(IResourceConfiguration.KIND_APPLY_RCBS_TOOL_AS_OVERRIDE);
return tool;
}
public static ITool setRcbsInputs(ITool tool, String inputs){
tool.getInputTypes()[0].getAdditionalInputs()[0].setPaths(inputs);
return tool;
}
public static ITool setRcbsOutputs(ITool tool, String outputs){
tool.getOutputTypes()[0].setOutputNames(outputs);
return tool;
}
public static ITool getRcbsTool(IResourceConfiguration rcConfig, boolean create){
ITool rcbsTools[] = getRcbsTools(rcConfig);
ITool rcbsTool = null;
if(rcbsTools != null)
rcbsTool = rcbsTools[0];
else if (create) {
rcbsTool = rcConfig.createTool(null,rcbsToolId + "." + ManagedBuildManager.getRandomNumber(),rcbsToolName,false); //$NON-NLS-1$
rcbsTool.setCustomBuildStep(true);
IInputType rcbsToolInputType = rcbsTool.createInputType(null,rcbsToolInputTypeId + "." + ManagedBuildManager.getRandomNumber(),rcbsToolInputTypeName,false); //$NON-NLS-1$
IAdditionalInput rcbsToolInputTypeAdditionalInput = rcbsToolInputType.createAdditionalInput(""); //$NON-NLS-1$
rcbsToolInputTypeAdditionalInput.setKind(IAdditionalInput.KIND_ADDITIONAL_INPUT_DEPENDENCY);
rcbsTool.createOutputType(null,rcbsToolOutputTypeId + "." + ManagedBuildManager.getRandomNumber(),rcbsToolOutputTypeName,false); //$NON-NLS-1$
}
return rcbsTool;
}
public static ITool[] getRcbsTools(IResourceConfiguration rcConfig){
List<ITool> list = new ArrayList<ITool>();
ITool tools[] = rcConfig.getTools();
for (int i = 0; i < tools.length; i++) {
ITool tool = tools[i];
if (tool.getCustomBuildStep() && !tool.isExtensionElement()) {
list.add(tool);
}
}
if(list.size() != 0)
return list.toArray(new ITool[list.size()]);
return null;
}
public static boolean setObjs(IConfiguration cfg, String[] objs){
return setOption(cfg, IOption.OBJECTS, objs);
}
public static boolean setLibs(IConfiguration cfg, String[] objs){
return setOption(cfg, IOption.LIBRARIES, objs);
}
public static boolean setOption(IConfiguration cfg, int type, Object value){
return setOption(cfg.getFilteredTools(), type, value);
}
public static boolean setOption(IResourceConfiguration rcCfg, int type, Object value){
return setOption(rcCfg.getToolsToInvoke()[0], type, value);
}
public static boolean setOption(ITool tools[], int type, Object value){
for(int i = 0; i < tools.length; i++){
if(setOption(tools[i], type, value))
return true;
}
return false;
}
public static IBuildObject[] getOption(IConfiguration cfg, int type){
return getOption(cfg.getFilteredTools(), type);
}
public static IBuildObject[] getOption(IResourceConfiguration rcCfg, int type, Object value){
return getOption(new ITool[]{rcCfg.getToolsToInvoke()[0]}, type);
}
public static IBuildObject[] getOption(ITool tools[], int type){
for(int i = 0; i < tools.length; i++){
IOption option = getOption(tools[i], type);
if(option != null)
return new IBuildObject[]{tools[i],option};
}
return null;
}
public static IOption getOption(IHoldsOptions tool, int type){
IOption opts[] = tool.getOptions();
for(int i = 0; i < opts.length; i++){
IOption option = opts[i];
try {
if(option.getValueType() == type){
return option;
}
} catch (BuildException e) {
}
}
return null;
}
public static boolean setOption(ITool tool, int type, Object value){
IOption option = getOption(tool, type);
if(option == null)
return false;
IBuildObject obj = tool.getParent();
IConfiguration cfg = null;
IResourceConfiguration rcCfg = null;
if(obj instanceof IToolChain)
cfg = ((IToolChain)obj).getParent();
else
rcCfg = (IResourceConfiguration)obj;
try {
if(option.getValueType() == type){
switch(type){
case IOption.BOOLEAN:
{
boolean val = ((Boolean)value).booleanValue();
if(rcCfg != null)
rcCfg.setOption(tool, option, val);
else
cfg.setOption(tool, option, val);
}
return true;
case IOption.ENUMERATED:
case IOption.STRING:
{
String val = (String)value;
if(rcCfg != null)
rcCfg.setOption(tool, option, val);
else
cfg.setOption(tool, option, val);
}
return true;
case IOption.STRING_LIST:
case IOption.INCLUDE_PATH:
case IOption.PREPROCESSOR_SYMBOLS:
case IOption.LIBRARIES:
case IOption.OBJECTS:
case IOption.INCLUDE_FILES:
case IOption.LIBRARY_PATHS:
case IOption.LIBRARY_FILES:
case IOption.MACRO_FILES:
{
String val[] = (String[])value;
if(rcCfg != null)
rcCfg.setOption(tool, option, val);
else
cfg.setOption(tool, option, val);
}
return true;
default:
Assert.fail("wrong option type passed");
}
}
} catch (BuildException e) {
}
return false;
}
}