package utils;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.tobject.findbugs.reporter.MarkerUtil;
import edu.umd.cs.findbugs.plugin.eclipse.quickfix.BugResolution;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IMarkerResolution;
public class TestingUtils {
private TestingUtils() {
// private constructor, static utils
}
public static void copyBrokenFiles(IFolder targetFolder, File... foldersToCopy) throws CoreException, IOException {
List<File> filesToCopy = new ArrayList<>();
for(File folder : foldersToCopy) {
File[] files = folder.listFiles();
if (files != null) {
filesToCopy.addAll(Arrays.asList(files));
}
}
for (File fileToCopy : filesToCopy) {
if (fileToCopy.isFile()) {
URL url = fileToCopy.getAbsoluteFile().toURI().toURL();
IFile file = targetFolder.getFile(new Path(fileToCopy.getName()));
if (!file.exists()) {
file.create(url.openStream(), true, null);
} else {
file.setContents(url.openStream(), true, false, null);
}
} else { // is directory, make a recursive call to copy
if (!(fileToCopy.isHidden() || fileToCopy.getName().startsWith("."))) {
IFolder newFolder = targetFolder.getFolder(fileToCopy.getName());
if (newFolder.exists()) {
newFolder.delete(true, null); // force deletion
}
newFolder.create(true, true, null); // force a local folder
copyBrokenFiles(newFolder, fileToCopy);
} else {
System.out.println("Skipping hidden folder " + fileToCopy);
}
}
}
}
public static void sortMarkersByPatterns(IMarker[] markers) {
Arrays.sort(markers, new Comparator<IMarker>() {
@Override
public int compare(IMarker marker1, IMarker marker2) {
String pattern1 = MarkerUtil.getBugPatternString(marker1);
if (pattern1 != null) {
String pattern2 = MarkerUtil.getBugPatternString(marker2);
if (pattern1.equals(pattern2)) {
return MarkerUtil.findPrimaryLineForMaker(marker1) -
MarkerUtil.findPrimaryLineForMaker(marker2);
}
return pattern1.compareTo(pattern2);
}
try {
fail("A marker did not have a bug pattern string " + marker1.getAttributes());
} catch (CoreException e) {
e.printStackTrace();
fail("Core exception");
}
return 0;
}
});
}
/**
* Run all UI events for at least the duration specified.
*
* @param duration
*/
public static void waitForUiEvents(long duration) {
long start = System.currentTimeMillis();
long sleepTime = duration > 30 ? 30 : duration;
while (true) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
handleAllUiEvents();
if (System.currentTimeMillis() - start > duration) {
break;
}
}
}
private static void handleAllUiEvents() {
while (Display.getDefault().readAndDispatch()) {
// do nothing, handle UI Events
}
}
public static IMarker[] getAllMarkersInResource(IResource resource) {
return MarkerUtil.getAllMarkers(resource);
}
public static IMarker[] getAllMarkersInResource(IJavaProject testProject, String fileName) throws JavaModelException {
return getAllMarkersInResource(elementFromProject(testProject, fileName).getCorrespondingResource());
}
public static IJavaElement elementFromProject(IJavaProject project, String fileName) throws JavaModelException {
return project.findElement(new Path(fileName));
}
public static void assertBugPatternsMatch(List<QuickFixTestPackage> packages, IMarker[] markers) {
for (int i = 0; i < packages.size(); i++) {
String actualBugpattern = MarkerUtil.getBugPatternString(markers[i]);
assertEquals("Bug Pattern should match", packages.get(i).expectedPattern, actualBugpattern);
}
}
public static void assertLabelsAndDescriptionsMatch(List<QuickFixTestPackage> packages, IMarker[] markers,
BugResolutionSource resolutionSource) {
Map<String, String> expectedLabelsAndDescriptions = new HashMap<>();
for (int i = 0; i < packages.size(); i++) {
IMarker marker = markers[i];
QuickFixTestPackage p = packages.get(i);
expectedLabelsAndDescriptions.clear();
for (int j = 0; j < p.expectedLabels.size(); j++)
expectedLabelsAndDescriptions.put(p.expectedLabels.get(j), p.expectedDescriptions.get(j));
IMarkerResolution[] resolutions = resolutionSource.getResolutions(marker);
assertEquals("The expected number of resolutions available was wrong " + p, expectedLabelsAndDescriptions.size(),
resolutions.length);
for (int j = 0; j < resolutions.length; j++) {
BugResolution resolution = (BugResolution) resolutions[j];
String label = resolution.getLabel();
assertTrue("Should not have seen label: " + label + " in " + expectedLabelsAndDescriptions,
expectedLabelsAndDescriptions.containsKey(label));
assertEquals("Description should have matched",
expectedLabelsAndDescriptions.get(label), resolution.getDescription());
expectedLabelsAndDescriptions.remove(label);
}
}
}
public static void assertLineNumbersMatch(List<QuickFixTestPackage> packages, IMarker[] markers) {
for (int i = 0; i < packages.size(); i++) {
int lineNumber = MarkerUtil.findPrimaryLineForMaker(markers[i]);
assertEquals("Line number should match", packages.get(i).lineNumber, lineNumber);
}
}
public static void assertAllMarkersHaveResolutions(IMarker[] markers, BugResolutionSource resolutionSource) {
for (int i = 0; i < markers.length; i++) {
IMarker marker = markers[i];
assertTrue("no resolution for: " + MarkerUtil.getBugPatternString(marker),
resolutionSource.hasResolutions(marker));
}
}
public static void assertOutputAndInputFilesMatch(URL expectedFile, IJavaElement actualFile) throws IOException,
JavaModelException {
if (actualFile instanceof ICompilationUnit) {
ICompilationUnit compilationUnit = (ICompilationUnit) actualFile;
String expectedSource = readFileContents(expectedFile);
assertEquals("Input and output should match", expectedSource, compilationUnit.getSource());
} else {
fail("The specified 'actual' file is not a file, but something else " + actualFile);
}
}
private static String readFileContents(URL url) throws IOException {
// Using a StringWriter here because it's about the same performance
// as StringBuilder (http://stackoverflow.com/questions/2980805/string-assembly-by-stringbuilder-vs-stringwriter-and-printwriter)
// and it handles the url streams better (the int to char conversion, specifically)
StringWriter writer = new StringWriter(100);
try (InputStream input = url.openStream();) {
int nextChar;
while ((nextChar = input.read()) != -1) {
writer.write(nextChar);
}
}
return writer.toString();
}
}