blob: ef3ebcf2c638b06e93450700fede5989d54af9dd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 CEA LIST, Zeligsoft
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST - initial API and implementation
* Based on work from Zeligsoft (in context of C++ test suite)
*
*******************************************************************************/
package org.eclipse.papyrus.designer.languages.common.testutils;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.InputStream;
import java.util.Scanner;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
@SuppressWarnings("nls")
public class FileComparison {
/**
* Compare the files in folder with what we expect to see. When comparing
* file content, filter out whitespace which will replace all whitespace
* with a single space in the actual file content and the expected file
* content in order to avoid problems with differences caused by code
* formatting options where the test suite is run. Then a simple string
* comparison is done.
*
* @param generatedFolder
* the generated folder
* @param modelProject
* the project containing the model
* @param fileName
* the filename to compare
* @param depthSegments
* hierarchical folders, if any
* @throws Exception
*/
public static void assertGeneratedMatchesExpected(IFolder generatedFolder, IProject modelProject, String fileName, String... depthSegments) throws Exception {
assertTrue("Default generated folder \"" + generatedFolder + "\" was not generated", generatedFolder.exists());
// test generated folder
IFolder generatedPackageFolder = null;
for (int i = 0; i < depthSegments.length; i++) {
if (i == 0) {
generatedPackageFolder = generatedFolder.getFolder(depthSegments[i]);
} else {
generatedPackageFolder = generatedPackageFolder.getFolder(depthSegments[i]);
}
assertTrue("Package folder \"" + depthSegments[i] + "\" was not generated.", generatedPackageFolder.exists());
}
// test generated file
IFile generatedFile = null;
if (generatedPackageFolder != null) {
generatedFile = generatedPackageFolder.getFile(fileName);
} else {
generatedFile = generatedFolder.getFile(fileName);
}
assertTrue("File " + fileName + " was not generated.", generatedFile.exists());
String fileContent = getFileContents(generatedFile);
// test expected folder
IFolder expectedFolder = null;
for (int i = 0; i < depthSegments.length; i++) {
if (i == 0) {
expectedFolder = modelProject.getFolder(depthSegments[i]);
} else {
expectedFolder = expectedFolder.getFolder(depthSegments[i]);
}
assertTrue("Expected folder \"" + depthSegments[i] + "\" does not exist.", expectedFolder.exists());
}
// test expected file
IFile expectedFile = null;
if (expectedFolder != null) {
expectedFile = expectedFolder.getFile(fileName);
} else {
expectedFile = modelProject.getFile(fileName);
}
assertTrue("Expected file " + fileName + " does not exist.", expectedFile.exists());
String expectedFileContent = getFileContents(expectedFile);
assertContentMatches(fileName, fileContent, expectedFileContent);
}
public static void assertGeneratedMatchesExpected(IContainer generatedFolder, IContainer expectedFolder) {
try {
for (IResource memberExp : expectedFolder.members()) {
IResource memberGen = generatedFolder.findMember(memberExp.getName());
assertThat(String.format("expected file or folder \"%s\" does not exist in generated code", memberExp.getName()), memberGen != null);
if (memberGen instanceof IFile) {
assertThat("expected resource exists, but is not a file in generated code", memberGen instanceof IFile);
String generatedFileContent = getFileContents((IFile) memberGen);
String expectedFileContent = getFileContents((IFile) memberExp);
assertContentMatches(memberGen.getName(), generatedFileContent, expectedFileContent);
}
else if (memberGen instanceof IFolder) {
assertThat("expected resource exists, but is not a folder in generated code", memberGen instanceof IFolder);
assertGeneratedMatchesExpected((IFolder) memberGen, (IFolder) memberExp);
}
}
} catch (CoreException e) {
fail(e.getMessage());
}
}
public static IProject getGeneratedProject(String genProjectName) {
IProject genProject = ResourcesPlugin.getWorkspace().getRoot().getProject(genProjectName);
if(genProject == null || !genProject.exists()) {
throw new AssertionError("Generated project not found");
}
return genProject;
}
public static String getFileContents(IFile file) throws CoreException {
InputStream inStream = file.getContents();
assertNotNull("Contents of file \"" + file.getName() + "\" are empty.", inStream);
String content = null;
Scanner s = new Scanner(inStream);
s.useDelimiter("\\Z");
content = s.hasNext() ? s.next() : "";
s.close();
return content;// == null ? null : content.replaceAll("\\s+", " ").trim();
}
public static void assertContentMatches(String filename, String generated, String expected) {
Scanner expectedScanner = new Scanner(expected);
char[] strippedGen = generated.replaceAll("\\s+", "").trim().toCharArray();
int genCharsTraversed = 0;
boolean outofchars = false;
/*
* line by line in expected
* char by char in generated
* compare char by char expected to generated until no more chars in line
* if not matching then print line expected against line generated by
* keeping track of the amount of chars traversed, then traverse the
* generated with white characters
*/
try {
int lineNumber = 1;
int lineCharBegin = 0;
for (; !outofchars && expectedScanner.hasNextLine(); ++lineNumber) {
lineCharBegin = genCharsTraversed;
String eLine = expectedScanner.nextLine();
String strippedELine = eLine.replaceAll("\\s+", "").trim();
char[] strippedExpected = strippedELine.toCharArray();
for (int i = 0; i < strippedExpected.length; i++) {
if (strippedExpected[i] != strippedGen[genCharsTraversed]) {
fail(filename + ':' + lineNumber + " expected '" + eLine.trim() + "' but found '" + rebuildStringForLineError(generated.trim(), eLine.trim(), i, genCharsTraversed, lineCharBegin) + "'");
}
genCharsTraversed++;
if (genCharsTraversed == strippedGen.length) {
outofchars = true;
}
}
}
if (expectedScanner.hasNextLine()) {
fail(filename + ':' + lineNumber + " expected '" + expectedScanner.nextLine() + "' but found end-of-file");
} else if (!outofchars && strippedGen.length > 0) {
fail(filename + ':' + lineNumber + " expected end-of-file but found '" + rebuildStringForEndOfFileError(generated.trim(), genCharsTraversed) + '\'');
}
} finally {
if (expectedScanner != null) {
expectedScanner.close();
}
}
}
private static String rebuildStringForLineError(String generatedString, String expectedLine, int beginInExpectedLine, int genCharsTraversed, int firstCharInExpLine) {
String brokenLine = "";
int lengthFromFirstDiff = expectedLine.replaceAll("\\s+", "").length() - beginInExpectedLine;
char[] generatedChars = generatedString.replaceAll("\\s+", " ").toCharArray();
int nonwhitechars = 0;
for (int i = 0; i < generatedChars.length; i++) {
if (generatedChars[i] != ' ') {
nonwhitechars++;
}
if (nonwhitechars >= firstCharInExpLine && nonwhitechars < genCharsTraversed + lengthFromFirstDiff) {
// start copying
brokenLine += generatedChars[i];
} else if (nonwhitechars == genCharsTraversed + lengthFromFirstDiff) {
// copy number of characters for the length of the expected line
if (generatedChars[i + 1] != '\0') {
brokenLine += "...";
}
break;
}
}
return brokenLine;
}
private static String rebuildStringForEndOfFileError(String generatedString, int genCharsTraversed) {
String brokenLine = "";
char[] generatedChars = generatedString.replaceAll("\\s+", " ").toCharArray();
int nonwhitechars = 0;
for (int i = 0; i < generatedChars.length; i++) {
if (generatedChars[i] != ' ') {
nonwhitechars++;
}
if (nonwhitechars > genCharsTraversed && generatedChars[i] != '\0') {
// start copying
brokenLine += generatedChars[i];
} else if (nonwhitechars == genCharsTraversed + 15 || generatedChars[i] == '\0') {
// copy only 15 chars
if (generatedChars[i + 1] != '\0') {
brokenLine += "...";
}
break;
}
}
return brokenLine;
}
}