blob: d274cf8049e3267b06ec8cd0ad4ed650d369f1a9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.docs.intent.client.ui.test.unit.compare;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.List;
import junit.framework.AssertionFailedError;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.mylyn.docs.intent.client.ui.test.util.AbstractIntentUITest;
import org.eclipse.mylyn.docs.intent.compare.utils.EMFCompareUtils;
import org.eclipse.mylyn.docs.intent.core.document.IntentDocument;
import org.eclipse.mylyn.docs.intent.core.document.IntentSection;
import org.eclipse.mylyn.docs.intent.core.document.IntentStructuredElement;
import org.eclipse.mylyn.docs.intent.parser.IntentParser;
import org.eclipse.mylyn.docs.intent.parser.modelingunit.ParseException;
/**
* Test ensuring that the Intent match engine works as expected.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
*/
public class IntentMatchEngineTests extends AbstractIntentUITest {
/**
* Path of the test file.
*/
private static final String INTENT_DOCUMENT_FOLDER = "data/unit/documents/editorupdates/";
/**
* All assertion failed errors (are only raised in the end to have the number of failures and not stop at
* first one).
*/
private Collection<AssertionFailedError> errors = Sets.newLinkedHashSet();
/**
* Number of tested cases.
*/
private int compareCasesNumber;
/**
* Ensures that the Intent match engine works as expected on the given test file.
*/
public void testCompareDocumentWithChapterTitles() {
doTestDiffEngine("compareTest-01.intent");
}
/**
* Ensures that the Intent match engine works as expected on the given test file.
*/
public void testCompareDocumentWithoutChapterTitles() {
doTestDiffEngine("compareTest-02.intent");
}
/**
* Ensures that all modifications that can be made on the IntentDocument located at the given model path
* are correctly detected.
*
* @param modelPath
* the path of the Intent document model (from
* org.eclipse.mylyn.docs.intent.client.ui.test/data/unit/models/documents/)
*/
protected void doTestDiffEngine(String modelPath) {
// Step 1: we load the intent document
parseIntentDocumentFromTests(INTENT_DOCUMENT_FOLDER + modelPath);
// Step 2: compare with a copy of this element
doTestCopyIsEqualToOriginal();
// Step 3 : test that adding chapters works as expected
doTestAddingChapter();
// Step 4 : test that removing chapters works as expected
doTestRemovingChapter();
// Step 5 : test that adding sections works as expected
doTestAddingSections();
// Step 5 : test that removing sections works as expected
doTestRemovingSections();
// Step 6 : display assertion errors
if (!errors.isEmpty()) {
String message = errors.size() + " comparaison failures detected on " + compareCasesNumber
+ " cases.\n First issue :" + errors.iterator().next().getMessage();
AssertionFailedError error = new AssertionFailedError(message);
error.setStackTrace(errors.iterator().next().getStackTrace());
throw error;
}
}
/**
* Ensures that no differences are detected when comparing a Document with a copy of itself.
*/
protected void doTestCopyIsEqualToOriginal() {
// Create a copy of the document
IntentStructuredElement copy = EcoreUtil.copy(getIntentDocument());
// Check that copy is equal to original
List<Diff> differences = EMFCompareUtils.compareDocuments(copy, getIntentDocument()).getDifferences();
String message = "No difference should be detected between an Intent document and its copy";
try {
assertDiffIsAsExpected(message, differences, 0);
} catch (AssertionFailedError e) {
errors.add(e);
}
}
/**
* Ensures that the creation of any Chapter in the Intent document is correctly detected.
*/
protected void doTestAddingChapter() {
// Create a copy with a new chapter
IntentDocument copy = EcoreUtil.copy(getIntentDocument());
IntentSection newChapter;
try {
newChapter = (IntentSection)new IntentParser().parse("Chapter {\n\tChapter 1\n\tChaper1\n\t");
// according to where the chapter is added, we should have the following results :
for (int position = 0; position <= getIntentDocument().getIntentContent().size(); position++) {
copy.getSubSections().add(position, newChapter);
List<Diff> differences = EMFCompareUtils.compareDocuments(copy, getIntentDocument())
.getDifferences();
String message = "One new chapter should be detected at position " + position;
try {
Diff diff = assertDiffIsAsExpected(message, differences, 2);
assertEquals(message + '\n' + getDiffAsString(differences), DifferenceKind.ADD,
diff.getKind());
// TODO migrate to emf compare2
// assertEquals(message + getDiffAsString(differences), newChapter,
// ((ModelElementChangeLeftTarget)diff).getLeftElement());
// assertEquals(message + getDiffAsString(differences), getIntentDocument(),
// ((ModelElementChangeLeftTarget)diff).getRightParent());
} catch (AssertionFailedError e) {
errors.add(e);
}
copy.getSubSections().remove(newChapter);
}
} catch (ParseException e) {
fail(e.getMessage());
}
}
/**
* Ensures that the deletion of any Chapter in the Intent document is correctly detected.
*/
protected void doTestRemovingChapter() {
// Create a copy in which a chapter is removed
IntentDocument copy = EcoreUtil.copy(getIntentDocument());
// according to where the chapter is added, we should have the following results :
for (int position = 0; position < getIntentDocument().getSubSections().size(); position++) {
IntentSection chapterToRemoveinCopy = copy.getSubSections().get(position);
copy.getIntentContent().remove(chapterToRemoveinCopy);
String message = "A Chapter deletion should be detected at " + position;
try {
List<Diff> differences = EMFCompareUtils.compareDocuments(copy, getIntentDocument())
.getDifferences();
Diff diff = assertDiffIsAsExpected(message, differences, 2);
assertEquals(message + '\n' + getDiffAsString(differences), DifferenceKind.DELETE,
diff.getKind());
// TODO migrate to emf compare2
// assertEquals(message + '\n' + getDiffAsString(differences), chapterToRemoveInOriginal,
// ((ModelElementChangeRightTarget)diff).getRightElement());
// assertEquals(message + '\n' + getDiffAsString(differences), copy,
// ((ModelElementChangeRightTarget)diff).getLeftParent());
} catch (AssertionFailedError e) {
errors.add(e);
}
copy.getSubSections().add(position, chapterToRemoveinCopy);
}
}
/**
* Ensures that the creation of any section/subsection in the Intent document is correctly detected.
*/
protected void doTestAddingSections() {
// Create a copy
IntentDocument copy = EcoreUtil.copy(getIntentDocument());
// For each chapter of the document
for (int chapterID = 0; chapterID < getIntentDocument().getSubSections().size(); chapterID++) {
doTestAddingSectionsRecursive(copy, getIntentDocument().getSubSections().get(chapterID), copy
.getSubSections().get(chapterID), 3);
}
}
/**
* Ensures that the creation of any section/subsection in the Intent document is correctly detected.
*
* @param copy
* a copy of the intent document (in which the modification should be made)
* @param container
* the container in witch the new section should be added
* @param containerCopy
* the copy of the container in witch the new section should be added
* @param containerLevel
* the global containment level
*/
private void doTestAddingSectionsRecursive(IntentDocument copy, IntentSection container,
IntentSection containerCopy, int containerLevel) {
IntentSection newSection;
try {
newSection = (IntentSection)new IntentParser().parse("Section {\n\tSection 1\n\tSection1\n\t");
// according to where the section is added, we should have the following results :
for (int sectionID = 0; sectionID <= container.getSubSections().size(); sectionID++) {
containerCopy.getIntentContent().add(sectionID, newSection);
List<Diff> differences = EMFCompareUtils.compareDocuments(copy, getIntentDocument())
.getDifferences();
String message = "One new section should be detected at position " + containerLevel + "."
+ sectionID;
try {
Diff diff = assertDiffIsAsExpected(message, differences, containerLevel);
assertEquals(message + '\n' + getDiffAsString(differences), DifferenceKind.ADD,
diff.getKind());
// TODO migrate to emf compare2
// assertEquals(message + '\n' + getDiffAsString(differences), newSection,
// ((ModelElementChangeLeftTarget)diff).getLeftElement());
// assertEquals(message + '\n' + getDiffAsString(differences), container,
// ((ModelElementChangeLeftTarget)diff).getRightParent());
} catch (AssertionFailedError e) {
errors.add(e);
}
containerCopy.getIntentContent().remove(sectionID);
// considering subsections of the current container
for (int subSectionID = 0; subSectionID < container.getSubSections().size(); subSectionID++) {
doTestAddingSectionsRecursive(copy, container.getSubSections().get(subSectionID),
containerCopy.getSubSections().get(subSectionID), containerLevel + 1);
}
}
} catch (ParseException e) {
fail(e.getMessage());
}
}
/**
* Ensures that the deletion of any section/subsection in the Intent document is correctly detected.
*/
protected void doTestRemovingSections() {
// Create a copy
IntentDocument copy = EcoreUtil.copy(getIntentDocument());
// For each chapter of the document
for (int chapterID = 0; chapterID < getIntentDocument().getSubSections().size(); chapterID++) {
doTestRemovingSectionsRecursive(copy, getIntentDocument().getSubSections().get(chapterID), copy
.getSubSections().get(chapterID), 3);
}
}
/**
* Ensures that the deletion of any section/subsection in the Intent document is correctly detected.
*
* @param copy
* a copy of the intent document (in which the modification should be made)
* @param container
* the container in witch the new section should be added
* @param containerCopy
* the copy of the container in witch the new section should be added
* @param containerLevel
* the global containment level
*/
private void doTestRemovingSectionsRecursive(IntentDocument copy, IntentSection container,
IntentSection containerCopy, int containerLevel) {
// Delete each subsection
for (int sectionID = 0; sectionID < container.getSubSections().size(); sectionID++) {
IntentSection removedSection = (IntentSection)containerCopy.getSubSections().get(sectionID);
int trueIndex = containerCopy.getIntentContent().indexOf(removedSection);
containerCopy.getIntentContent().remove(removedSection);
List<Diff> differences = EMFCompareUtils.compareDocuments(copy, getIntentDocument())
.getDifferences();
String message = "A Section deletion should be detected at position" + containerLevel + "."
+ sectionID;
try {
Diff diff = assertDiffIsAsExpected(message, differences, containerLevel);
assertEquals(message + '\n' + getDiffAsString(differences), DifferenceKind.DELETE,
diff.getKind());
// TODO migrate to emf compare2
// assertEquals(message + '\n' + getDiffAsString(differences),
// container.getIntentContent().get(trueIndex),
// ((ModelElementChangeRightTarget)diff).getRightElement());
// assertEquals(message + '\n' + getDiffAsString(differences), containerCopy,
// ((ModelElementChangeRightTarget)diff).getLeftParent());
} catch (AssertionFailedError e) {
errors.add(e);
}
containerCopy.getIntentContent().add(trueIndex, removedSection);
// considering subsections of the current container
for (int subSectionID = 0; subSectionID < container.getSubSections().size(); subSectionID++) {
doTestRemovingSectionsRecursive(copy, container.getSubSections().get(subSectionID),
containerCopy.getSubSections().get(subSectionID), containerLevel + 1);
}
}
}
/**
* Ensures that the given differences describes exactly one difference at the expected level, with no
* sub-differences.
*
* @param message
* the failure message
* @param differences
* the differences to inspect
* @param expectedLevel
* the expected level for the diff (2 for chapter, 3 for root section, 4 for subsection...).
* @return the expected diff element if correct
*/
protected Diff assertDiffIsAsExpected(String message, Collection<Diff> differences, int expectedLevel) {
compareCasesNumber++;
assertEquals(message + '\n' + getDiffAsString(differences), 1, differences.size());
// We want to have exactly one difference at the expected level
Diff childDiff = differences.iterator().next();
int currentLevel = 0;
while (childDiff != null && currentLevel < expectedLevel) {
// assertEquals(message + '\n' + getDiffAsString(differences), 1, childDiff.getSubDiffs().size());
// TODO migrate to emf compare2
currentLevel++;
// childDiff = childDiff.getSubDiffs().iterator().next();
// TODO migrate to emf compare2
}
// This difference should not have any sub difference elements
// assertEquals(message + '\n' + getDiffAsString(differences), 0, childDiff.getSubDiffs().size()); //
// TODO migrate to emf compare2
return childDiff;
}
/**
* Returns the given differences as string (to show them in assertion message).
*
* @param differences
* the dirrences to get as string
* @return the given differences as string (to show them in assertion message)
*/
protected String getDiffAsString(Collection<Diff> differences) {
String diff = "";
for (Diff element : differences) {
diff += element.toString() + '\n';
// diff += getDiffAsString(element.getSubDiffs()); // TODO migrate to emf compare2
}
return diff;
}
}