/*******************************************************************************
 * Copyright (c) 2012, 2015 Obeo 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:
 *     Obeo - initial API and implementation
 *     Philip Langer - bug 479449
 *******************************************************************************/
package org.eclipse.emf.compare.tests.conflict;

import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.size;
import static org.eclipse.emf.compare.ConflictKind.PSEUDO;
import static org.eclipse.emf.compare.ConflictKind.REAL;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.added;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToAttribute;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.addedToReference;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedAttribute;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.changedReference;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.containsConflictOfTypes;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.moved;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.movedInAttribute;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.movedInReference;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.onEObject;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.referenceValueMatch;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.removed;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromAttribute;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.removedFromReference;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;

import java.io.IOException;
import java.util.List;

import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Conflict;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.EMFCompare;
import org.eclipse.emf.compare.ResourceAttachmentChange;
import org.eclipse.emf.compare.scope.DefaultComparisonScope;
import org.eclipse.emf.compare.scope.IComparisonScope;
import org.eclipse.emf.compare.tests.conflict.data.ConflictInputData;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.junit.Test;

@SuppressWarnings("nls")
public class ConflictDetectionTest {

	/**
	 * This predicate can be used to check whether a given Diff represents the setting of a value in a
	 * single-valued reference going by {@code referenceName} on an EObject which name matches
	 * {@code qualifiedName}.
	 * <p>
	 * Note that in order for this to work, we expect the EObjects to have a "name" feature returning a String
	 * for us to compare it with the given qualified name.
	 * </p>
	 * <p>
	 * TODO this is only here to allow us to avoid changing API; should be moved to EMFComparePredicates
	 * </p>
	 * 
	 * @param qualifiedName
	 *            Qualified name of the EObject which we expect to present a ReferenceChange.
	 * @param referenceName
	 *            Name of the multi-valued reference on which we expect a change.
	 * @param addedQualifiedName
	 *            Qualified name of the EObject which we expect to have been added to this reference.
	 * @return The created predicate.
	 */
	@SuppressWarnings("unchecked")
	private static Predicate<? super Diff> setOfReference(final String qualifiedName,
			final String referenceName, final String addedQualifiedName) {
		// This is only meant for multi-valued references
		return and(ofKind(DifferenceKind.ADD), onEObject(qualifiedName),
				referenceValueMatch(referenceName, addedQualifiedName, false));
	}

	private ConflictInputData input = new ConflictInputData();

	@Test
	public void testA1UseCaseForAttribute() throws IOException {
		final Resource left = input.getA1AttributeLeft();
		final Resource origin = input.getA1AttributeOrigin();
		final Resource right = input.getA1AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", "left");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testA1UseCaseForReference() throws IOException {
		final Resource left = input.getA1ReferenceLeft();
		final Resource origin = input.getA1ReferenceOrigin();
		final Resource right = input.getA1ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We have three diffs here : an object has been deleted on the right side, its reference has been
		 * unset, and that same reference has been changed on the left to a new value. The two diffs on the
		 * right are in conflict with the only diff on the left.
		 */
		assertEquals(3, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftReferenceDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", "root.left");
		final Predicate<? super Diff> rightReferenceDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");

		final Diff leftReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftReferenceDiffDescription));
		final Diff rightReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiffDescription));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));

		assertNotNull(leftReferenceDiff);
		assertNotNull(rightReferenceDiff);
		assertNotNull(rightDeleteDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(3, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftReferenceDiff));
		assertTrue(conflictDiff.contains(rightReferenceDiff));
		assertTrue(conflictDiff.contains(rightDeleteDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testA2UseCaseForAttribute() throws IOException {
		final Resource left = input.getA2AttributeLeft();
		final Resource origin = input.getA2AttributeOrigin();
		final Resource right = input.getA2AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);
		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", null, "left");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testA2UseCaseForReference() throws IOException {
		final Resource left = input.getA2ReferenceLeft();
		final Resource origin = input.getA2ReferenceOrigin();
		final Resource right = input.getA2ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", null, "root.left");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testA3UseCaseForAttribute() throws IOException {
		final Resource left = input.getA3AttributeLeft();
		final Resource origin = input.getA3AttributeOrigin();
		final Resource right = input.getA3AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have 2 differences
		// Deleted a container on one side, unset one of its attributes on the other
		// There are no conflict on this since we do not consider pseudo conflicts between a container and its
		// sub-diffs... and we do not consider attribute changes on the same side of the container deletion as
		// standalone diffs (they're not even created as Diffs by the engine).
		assertEquals(2, differences.size());
		assertTrue(conflicts.isEmpty());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", null);
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);
	}

	@Test
	public void testA3UseCaseForReference() throws IOException {
		final Resource left = input.getA3ReferenceLeft();
		final Resource origin = input.getA3ReferenceOrigin();
		final Resource right = input.getA3ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We expect three differences here : an object has been deleted on the right, its reference has been
		 * unset, and that same reference has been unset on the left. All three diffs are in pseudo-conflict
		 * with each other.
		 */
		assertEquals(3, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftReferenceDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);
		final Predicate<? super Diff> rightReferenceDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");

		final Diff leftReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftReferenceDiffDescription));
		final Diff rightReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiffDescription));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));

		assertNotNull(leftReferenceDiff);
		assertNotNull(rightReferenceDiff);
		assertNotNull(rightDeleteDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftReferenceDiff));
		assertTrue(conflictDiff.contains(rightReferenceDiff));
		assertSame(PSEUDO, conflict.getKind());

		assertNull(rightDeleteDiff.getConflict());
	}

	@Test
	public void testB1UseCaseForAttribute() throws IOException {
		final Resource left = input.getB1AttributeLeft();
		final Resource origin = input.getB1AttributeOrigin();
		final Resource right = input.getB1AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", "left");
		final Predicate<? super Diff> rightDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", "right");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB1UseCaseForReference() throws IOException {
		final Resource left = input.getB1ReferenceLeft();
		final Resource origin = input.getB1ReferenceOrigin();
		final Resource right = input.getB1ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", "root.left");
		final Predicate<? super Diff> rightDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", "root.right");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB2UseCaseForAttribute() throws IOException {
		final Resource left = input.getB2AttributeLeft();
		final Resource origin = input.getB2AttributeOrigin();
		final Resource right = input.getB2AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", "left");
		final Predicate<? super Diff> rightDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", null);

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB2UseCaseForReference() throws IOException {
		final Resource left = input.getB2ReferenceLeft();
		final Resource origin = input.getB2ReferenceOrigin();
		final Resource right = input.getB2ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", "root.left");
		final Predicate<? super Diff> rightDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB3UseCaseForAttribute() throws IOException {
		final Resource left = input.getB3AttributeLeft();
		final Resource origin = input.getB3AttributeOrigin();
		final Resource right = input.getB3AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", null, "left");
		final Predicate<? super Diff> rightDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", null, "right");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB3UseCaseForReference() throws IOException {
		final Resource left = input.getB3ReferenceLeft();
		final Resource origin = input.getB3ReferenceOrigin();
		final Resource right = input.getB3ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", null, "root.left");
		final Predicate<? super Diff> rightDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", null, "root.right");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB3UseCaseForContainmentReference() throws IOException {
		final Resource left = input.getB3ContainmentReferenceLeft();
		final Resource origin = input.getB3ContainmentReferenceOrigin();
		final Resource right = input.getB3ContainmentReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = setOfReference("root.conflictHolder",
				"singleValueContainment", "root.conflictHolder.newleft");
		final Predicate<? super Diff> rightDiffDescription = setOfReference("root.conflictHolder",
				"singleValueContainment", "root.conflictHolder.newright");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB4UseCaseForAttribute() throws IOException {
		final Resource left = input.getB4AttributeLeft();
		final Resource origin = input.getB4AttributeOrigin();
		final Resource right = input.getB4AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", null);
		final Predicate<? super Diff> rightDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", "right");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB4UseCaseForReference() throws IOException {
		final Resource left = input.getB4ReferenceLeft();
		final Resource origin = input.getB4ReferenceOrigin();
		final Resource right = input.getB4ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);
		final Predicate<? super Diff> rightDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", "root.right");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testB5UseCaseForAttribute() throws IOException {
		final Resource left = input.getB5AttributeLeft();
		final Resource origin = input.getB5AttributeOrigin();
		final Resource right = input.getB5AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", null, "leftAndRight");
		final Predicate<? super Diff> rightDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", null, "leftAndRight");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testB5UseCaseForReference() throws IOException {
		final Resource left = input.getB5ReferenceLeft();
		final Resource origin = input.getB5ReferenceOrigin();
		final Resource right = input.getB5ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", null, "root.leftAndRight");
		final Predicate<? super Diff> rightDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", null, "root.leftAndRight");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testB6UseCaseForAttribute() throws IOException {
		final Resource left = input.getB6AttributeLeft();
		final Resource origin = input.getB6AttributeOrigin();
		final Resource right = input.getB6AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", null);
		final Predicate<? super Diff> rightDiffDescription = changedAttribute("root.conflictHolder",
				"singleValuedAttribute", "origin", null);

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testB6UseCaseForReference() throws IOException {
		final Resource left = input.getB6ReferenceLeft();
		final Resource origin = input.getB6ReferenceOrigin();
		final Resource right = input.getB6ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);
		final Predicate<? super Diff> rightDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", "root.origin", null);

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testC1UseCaseForAttribute() throws IOException {
		final Resource left = input.getC1AttributeLeft();
		final Resource origin = input.getC1AttributeOrigin();
		final Resource right = input.getC1AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = addedToAttribute("root.conflictHolder",
				"multiValuedAttribute", "left1");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testC1UseCaseForReference() throws IOException {
		final Resource left = input.getC1ReferenceLeft();
		final Resource origin = input.getC1ReferenceOrigin();
		final Resource right = input.getC1ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We should have 5 differences here. An element has been deleted from the right side, all three of
		 * its reference's values have been deleted, and finally a value has been added into that same
		 * reference on the left side. The addition of a value into the reference conflicts with the removal
		 * of the container from the right. The three other diffs do not conflict.
		 */
		assertEquals(5, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftReferenceDiffDescription = addedToReference("root.conflictHolder",
				"multiValuedReference", "root.left1");
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");
		final Predicate<? super Diff> rightReferenceDiff1Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightReferenceDiff2Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin2");
		final Predicate<? super Diff> rightReferenceDiff3Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin3");

		final Diff leftReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftReferenceDiffDescription));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));
		final Diff rightReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff1Description));
		final Diff rightReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff2Description));
		final Diff rightReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff3Description));

		assertNotNull(leftReferenceDiff);
		assertNotNull(rightDeleteDiff);
		assertNotNull(rightReferenceDiff1);
		assertNotNull(rightReferenceDiff2);
		assertNotNull(rightReferenceDiff3);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftReferenceDiff));
		assertTrue(conflictDiff.contains(rightDeleteDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testC2UseCaseForAttribute() throws IOException {
		final Resource left = input.getC2AttributeLeft();
		final Resource origin = input.getC2AttributeOrigin();
		final Resource right = input.getC2AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertTrue(conflicts.isEmpty());

		final Predicate<? super Diff> leftDiffDescription = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);
	}

	@Test
	public void testC2UseCaseForReference() throws IOException {
		final Resource left = input.getC2ReferenceLeft();
		final Resource origin = input.getC2ReferenceOrigin();
		final Resource right = input.getC2ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We should have 5 differences here. An element has been deleted from the right side, all three of
		 * its reference's values have been deleted, and finally a value has been removed from that same
		 * reference on the left side. The deletion of a value into the left reference conflicts with the
		 * removal of the container from the right. It is also in pseudo-conflict with the deletion of this
		 * same value on the right.
		 */
		assertEquals(5, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftReferenceDiffDescription = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");
		final Predicate<? super Diff> rightReferenceDiff1Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightReferenceDiff2Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin2");
		final Predicate<? super Diff> rightReferenceDiff3Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin3");

		final Diff leftReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftReferenceDiffDescription));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));
		final Diff rightReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff1Description));
		final Diff rightReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff2Description));
		final Diff rightReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff3Description));

		assertNotNull(leftReferenceDiff);
		assertNotNull(rightDeleteDiff);
		assertNotNull(rightReferenceDiff1);
		assertNotNull(rightReferenceDiff2);
		assertNotNull(rightReferenceDiff3);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftReferenceDiff));
		assertTrue(conflictDiff.contains(rightReferenceDiff1));
		assertSame(PSEUDO, conflict.getKind());

		assertNull(rightDeleteDiff.getConflict());
	}

	@Test
	public void testC3UseCaseForAttribute() throws IOException {
		final Resource left = input.getC3AttributeLeft();
		final Resource origin = input.getC3AttributeOrigin();
		final Resource right = input.getC3AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = addedToAttribute("root.conflictHolder",
				"multiValuedAttribute", "left1");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testC3UseCaseForReference() throws IOException {
		final Resource left = input.getC3ReferenceLeft();
		final Resource origin = input.getC3ReferenceOrigin();
		final Resource right = input.getC3ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftReferenceDiffDescription = addedToReference("root.conflictHolder",
				"multiValuedReference", "root.left1");
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");

		final Diff leftReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftReferenceDiffDescription));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));

		assertNotNull(leftReferenceDiff);
		assertNotNull(rightDeleteDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftReferenceDiff));
		assertTrue(conflictDiff.contains(rightDeleteDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testC4UseCaseForAttribute() throws IOException {
		final Resource left = input.getC4AttributeLeft();
		final Resource origin = input.getC4AttributeOrigin();
		final Resource right = input.getC4AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We expect 4 differences here. On the right side, an element has been deleted. On the left side, all
		 * three values of one of this element's features have been removed. We do not consider this as a
		 * conflict.
		 */
		assertEquals(4, differences.size());
		assertTrue(conflicts.isEmpty());

		final Predicate<? super Diff> leftAttributeDiff1Description = removedFromAttribute(
				"root.conflictHolder", "multiValuedAttribute", "origin1");
		final Predicate<? super Diff> leftAttributeDiff2Description = removedFromAttribute(
				"root.conflictHolder", "multiValuedAttribute", "origin2");
		final Predicate<? super Diff> leftAttributeDiff3Description = removedFromAttribute(
				"root.conflictHolder", "multiValuedAttribute", "origin3");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftAttributeDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftAttributeDiff1Description));
		final Diff leftAttributeDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftAttributeDiff2Description));
		final Diff leftAttributeDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftAttributeDiff3Description));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftAttributeDiff1);
		assertNotNull(leftAttributeDiff2);
		assertNotNull(leftAttributeDiff3);
		assertNotNull(rightDiff);
	}

	@Test
	public void testC4UseCaseForReference() throws IOException {
		final Resource left = input.getC4ReferenceLeft();
		final Resource origin = input.getC4ReferenceOrigin();
		final Resource right = input.getC4ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We expect 7 differences here. On the right, an element has been deleted. All three values of this
		 * element's reference have been removed. On the left, we've also removed all three values of that
		 * same reference.
		 */
		/*
		 * The element deletion is a standalone diffs, but all of the diffs under it are in pseudo-conflict
		 * two-by-two.
		 */
		assertEquals(7, differences.size());
		assertEquals(3, conflicts.size());

		final Predicate<? super Diff> referenceDiff1Description = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");
		final Predicate<? super Diff> referenceDiff2Description = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin2");
		final Predicate<? super Diff> referenceDiff3Description = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin3");
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");

		final Diff leftReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), referenceDiff1Description));
		final Diff leftReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), referenceDiff2Description));
		final Diff leftReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), referenceDiff3Description));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));
		final Diff rightReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), referenceDiff1Description));
		final Diff rightReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), referenceDiff2Description));
		final Diff rightReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), referenceDiff3Description));

		assertNotNull(leftReferenceDiff1);
		assertNotNull(leftReferenceDiff2);
		assertNotNull(leftReferenceDiff3);
		assertNotNull(rightDeleteDiff);
		assertNotNull(rightReferenceDiff1);
		assertNotNull(rightReferenceDiff2);
		assertNotNull(rightReferenceDiff3);

		// We're expecting three conflicts with 2 differences each

		final Conflict conflict1 = leftReferenceDiff1.getConflict();
		assertNotNull(conflict1);
		assertEquals(2, conflict1.getDifferences().size());
		assertTrue(conflict1.getDifferences().contains(leftReferenceDiff1));
		assertTrue(conflict1.getDifferences().contains(rightReferenceDiff1));
		assertSame(PSEUDO, conflict1.getKind());

		final Conflict conflict2 = leftReferenceDiff2.getConflict();
		assertNotNull(conflict2);
		assertEquals(2, conflict2.getDifferences().size());
		assertTrue(conflict2.getDifferences().contains(leftReferenceDiff2));
		assertTrue(conflict2.getDifferences().contains(rightReferenceDiff2));
		assertSame(PSEUDO, conflict2.getKind());

		final Conflict conflict3 = leftReferenceDiff3.getConflict();
		assertNotNull(conflict3);
		assertEquals(2, conflict3.getDifferences().size());
		assertTrue(conflict3.getDifferences().contains(leftReferenceDiff3));
		assertTrue(conflict3.getDifferences().contains(rightReferenceDiff3));
		assertSame(PSEUDO, conflict3.getKind());

		assertNull(rightDeleteDiff.getConflict());
	}

	@Test
	public void testC5UseCaseForAttribute() throws IOException {
		final Resource left = input.getC5AttributeLeft();
		final Resource origin = input.getC5AttributeOrigin();
		final Resource right = input.getC5AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = movedInAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");
		final Predicate<? super Diff> rightDiffDescription = removed("root.conflictHolder");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testC5UseCaseForReference() throws IOException {
		final Resource left = input.getC5ReferenceLeft();
		final Resource origin = input.getC5ReferenceOrigin();
		final Resource right = input.getC5ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We expect five differences here. An element has been deleted from the right side, all three values
		 * of its reference have been deleted too. In the left, we've moved one of these values to another
		 * index. The MOVE conflicts with both the container deletion and the value's removal.
		 */
		assertEquals(5, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftReferenceDiffDescription = movedInReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightDeleteDiffDescription = removed("root.conflictHolder");
		final Predicate<? super Diff> rightReferenceDiff1Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightReferenceDiff2Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin2");
		final Predicate<? super Diff> rightReferenceDiff3Description = removedFromReference(
				"root.conflictHolder", "multiValuedReference", "root.origin2");

		final Diff leftReferenceDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftReferenceDiffDescription));
		final Diff rightDeleteDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDeleteDiffDescription));
		final Diff rightReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff1Description));
		final Diff rightReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff2Description));
		final Diff rightReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightReferenceDiff3Description));

		assertNotNull(leftReferenceDiff);
		assertNotNull(rightDeleteDiff);
		assertNotNull(rightReferenceDiff1);
		assertNotNull(rightReferenceDiff2);
		assertNotNull(rightReferenceDiff3);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(3, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftReferenceDiff));
		assertTrue(conflictDiff.contains(rightDeleteDiff));
		assertTrue(conflictDiff.contains(rightReferenceDiff1));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD1UseCaseForAttribute() throws IOException {
		final Resource left = input.getD1AttributeLeft();
		final Resource origin = input.getD1AttributeOrigin();
		final Resource right = input.getD1AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");
		final Predicate<? super Diff> rightDiffDescription = movedInAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD1UseCaseForReference() throws IOException {
		final Resource left = input.getD1ReferenceLeft();
		final Resource origin = input.getD1ReferenceOrigin();
		final Resource right = input.getD1ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightDiffDescription = movedInReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD2UseCaseForAttribute() throws IOException {
		final Resource left = input.getD2AttributeLeft();
		final Resource origin = input.getD2AttributeOrigin();
		final Resource right = input.getD2AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = movedInAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");
		final Predicate<? super Diff> rightDiffDescription = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD2UseCaseForReference() throws IOException {
		final Resource left = input.getD2ReferenceLeft();
		final Resource origin = input.getD2ReferenceOrigin();
		final Resource right = input.getD2ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = movedInReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightDiffDescription = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD3UseCaseForAttribute() throws IOException {
		final Resource left = input.getD3AttributeLeft();
		final Resource origin = input.getD3AttributeOrigin();
		final Resource right = input.getD3AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = movedInAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");
		final Predicate<? super Diff> rightDiffDescription = movedInAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD3UseCaseForReference() throws IOException {
		final Resource left = input.getD3ReferenceLeft();
		final Resource origin = input.getD3ReferenceOrigin();
		final Resource right = input.getD3ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = movedInReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");
		final Predicate<? super Diff> rightDiffDescription = movedInReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testD4UseCaseForAttribute() throws IOException {
		final Resource left = input.getD4AttributeLeft();
		final Resource origin = input.getD4AttributeOrigin();
		final Resource right = input.getD4AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We expect 6 differences here. On both right and left, we've emptied an attribute from its 3 values.
		 * This should give use 3 pseudo-conflict, each removal conflicting with its other side.
		 */
		assertEquals(6, differences.size());
		assertEquals(3, conflicts.size());

		final Predicate<? super Diff> AttributeDiff1Description = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");
		final Predicate<? super Diff> AttributeDiff2Description = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin2");
		final Predicate<? super Diff> AttributeDiff3Description = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin3");

		final Diff leftAttributeDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), AttributeDiff1Description));
		final Diff leftAttributeDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), AttributeDiff2Description));
		final Diff leftAttributeDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), AttributeDiff3Description));

		final Diff rightAttributeDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), AttributeDiff1Description));
		final Diff rightAttributeDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), AttributeDiff2Description));
		final Diff rightAttributeDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), AttributeDiff3Description));

		assertNotNull(leftAttributeDiff1);
		assertNotNull(leftAttributeDiff2);
		assertNotNull(leftAttributeDiff3);
		assertNotNull(rightAttributeDiff1);
		assertNotNull(rightAttributeDiff2);
		assertNotNull(rightAttributeDiff3);

		// We know we have three conflicts
		final Conflict conflict1 = conflicts.get(0);

		final List<Diff> conflictDiffs1 = conflict1.getDifferences();
		assertEquals(2, conflictDiffs1.size());
		assertTrue(conflictDiffs1.contains(leftAttributeDiff1));
		assertTrue(conflictDiffs1.contains(rightAttributeDiff1));
		assertSame(PSEUDO, conflict1.getKind());

		final Conflict conflict2 = conflicts.get(1);

		final List<Diff> conflictDiffs2 = conflict2.getDifferences();
		assertEquals(2, conflictDiffs2.size());
		assertTrue(conflictDiffs2.contains(leftAttributeDiff2));
		assertTrue(conflictDiffs2.contains(rightAttributeDiff2));
		assertSame(PSEUDO, conflict2.getKind());

		final Conflict conflict3 = conflicts.get(2);

		final List<Diff> conflictDiffs3 = conflict3.getDifferences();
		assertEquals(2, conflictDiffs3.size());
		assertTrue(conflictDiffs3.contains(leftAttributeDiff3));
		assertTrue(conflictDiffs3.contains(rightAttributeDiff3));
		assertSame(PSEUDO, conflict3.getKind());
	}

	@Test
	public void testD4UseCaseForReference() throws IOException {
		final Resource left = input.getD4ReferenceLeft();
		final Resource origin = input.getD4ReferenceOrigin();
		final Resource right = input.getD4ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * We expect 6 differences here. On both right and left, we've emptied a reference from its 3 values.
		 * This should give use 3 pseudo-conflict, each removal conflicting with its other side.
		 */
		assertEquals(6, differences.size());
		assertEquals(3, conflicts.size());

		final Predicate<? super Diff> referenceDiff1Description = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");
		final Predicate<? super Diff> referenceDiff2Description = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin2");
		final Predicate<? super Diff> referenceDiff3Description = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin3");

		final Diff leftReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), referenceDiff1Description));
		final Diff leftReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), referenceDiff2Description));
		final Diff leftReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), referenceDiff3Description));

		final Diff rightReferenceDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), referenceDiff1Description));
		final Diff rightReferenceDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), referenceDiff2Description));
		final Diff rightReferenceDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), referenceDiff3Description));

		assertNotNull(leftReferenceDiff1);
		assertNotNull(leftReferenceDiff2);
		assertNotNull(leftReferenceDiff3);
		assertNotNull(rightReferenceDiff1);
		assertNotNull(rightReferenceDiff2);
		assertNotNull(rightReferenceDiff3);

		// We know we have three conflicts
		final Conflict conflict1 = conflicts.get(0);

		final List<Diff> conflictDiffs1 = conflict1.getDifferences();
		assertEquals(2, conflictDiffs1.size());
		assertTrue(conflictDiffs1.contains(leftReferenceDiff1));
		assertTrue(conflictDiffs1.contains(rightReferenceDiff1));
		assertSame(PSEUDO, conflict1.getKind());

		final Conflict conflict2 = conflicts.get(1);

		final List<Diff> conflictDiffs2 = conflict2.getDifferences();
		assertEquals(2, conflictDiffs2.size());
		assertTrue(conflictDiffs2.contains(leftReferenceDiff2));
		assertTrue(conflictDiffs2.contains(rightReferenceDiff2));
		assertSame(PSEUDO, conflict2.getKind());

		final Conflict conflict3 = conflicts.get(2);

		final List<Diff> conflictDiffs3 = conflict3.getDifferences();
		assertEquals(2, conflictDiffs3.size());
		assertTrue(conflictDiffs3.contains(leftReferenceDiff3));
		assertTrue(conflictDiffs3.contains(rightReferenceDiff3));
		assertSame(PSEUDO, conflict3.getKind());
	}

	@Test
	public void testD5UseCaseForAttribute() throws IOException {
		final Resource left = input.getD5AttributeLeft();
		final Resource origin = input.getD5AttributeOrigin();
		final Resource right = input.getD5AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> diffDescription = removedFromAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), diffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), diffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testD5UseCaseForReference() throws IOException {
		final Resource left = input.getD5ReferenceLeft();
		final Resource origin = input.getD5ReferenceOrigin();
		final Resource right = input.getD5ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> diffDescription = removedFromReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), diffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), diffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testD6UseCaseForAttribute() throws IOException {
		final Resource left = input.getD6AttributeLeft();
		final Resource origin = input.getD6AttributeOrigin();
		final Resource right = input.getD6AttributeRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> diffDescription = movedInAttribute("root.conflictHolder",
				"multiValuedAttribute", "origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), diffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), diffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testD6UseCaseForReference() throws IOException {
		final Resource left = input.getD6ReferenceLeft();
		final Resource origin = input.getD6ReferenceOrigin();
		final Resource right = input.getD6ReferenceRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> diffDescription = movedInReference("root.conflictHolder",
				"multiValuedReference", "root.origin1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), diffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), diffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(PSEUDO, conflict.getKind());
	}

	@Test
	public void testE1UseCase() throws IOException {
		final Resource left = input.getE1Left();
		final Resource origin = input.getE1Origin();
		final Resource right = input.getE1Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = changedReference("root.conflictHolder",
				"singleValuedReference", null, "root.origin");
		final Predicate<? super Diff> rightDiffDescription = removed("root.origin");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testE2UseCase() throws IOException {
		final Resource left = input.getE2Left();
		final Resource origin = input.getE2Origin();
		final Resource right = input.getE2Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = addedToReference("root.conflictHolder",
				"multiValuedReference", "root.origin");
		final Predicate<? super Diff> rightDiffDescription = removed("root.origin");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testE3UseCase() throws IOException {
		final Resource left = input.getE3Left();
		final Resource origin = input.getE3Origin();
		final Resource right = input.getE3Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(3, differences.size());
		assertEquals(1, conflicts.size());
	}

	@Test
	public void testFUseCase() throws IOException {
		final Resource left = input.getFLeft();
		final Resource origin = input.getFOrigin();
		final Resource right = input.getFRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = moved("root.conflictHolder.origin",
				"containmentRef2");
		final Predicate<? super Diff> rightDiffDescription = moved("root.conflictHolder.origin",
				"containmentRef3");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testGUseCase() throws IOException {
		final Resource left = input.getGLeft();
		final Resource origin = input.getGOrigin();
		final Resource right = input.getGRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = moved("root.leftContainer.conflictNode",
				"containmentRef1");
		final Predicate<? super Diff> rightDiffDescription = moved("root.rightContainer.conflictNode",
				"containmentRef1");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testH1UseCase() throws IOException {
		final Resource left = input.getH1Left();
		final Resource origin = input.getH1Origin();
		final Resource right = input.getH1Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = moved("root.left.conflictNode",
				"singleValueContainment");
		final Predicate<? super Diff> rightDiffDescription = removed("root.left");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testH2UseCase() throws IOException {
		final Resource left = input.getH2Left();
		final Resource origin = input.getH2Origin();
		final Resource right = input.getH2Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		// We should have no less and no more than 2 differences, composing a single conflict
		assertEquals(2, differences.size());
		assertEquals(1, conflicts.size());

		final Predicate<? super Diff> leftDiffDescription = moved("root.leftContainer.conflictNode",
				"containmentRef1");
		final Predicate<? super Diff> rightDiffDescription = removed("root.leftContainer");

		final Diff leftDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiffDescription));
		final Diff rightDiff = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiffDescription));

		assertNotNull(leftDiff);
		assertNotNull(rightDiff);

		// We know there's only one conflict
		final Conflict conflict = conflicts.get(0);

		final List<Diff> conflictDiff = conflict.getDifferences();
		assertEquals(2, conflictDiff.size());
		assertTrue(conflictDiff.contains(leftDiff));
		assertTrue(conflictDiff.contains(rightDiff));
		assertSame(REAL, conflict.getKind());
	}

	@Test
	public void testIUseCase() throws IOException {
		final Resource left = input.getILeft();
		final Resource origin = input.getIOrigin();
		final Resource right = input.getIRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(5, differences.size());
		assertEquals(1, conflicts.size());

		Conflict soleConflict = conflicts.get(0);
		assertSame(PSEUDO, soleConflict.getKind());
	}

	@Test
	public void testJUseCase() throws IOException {
		final Resource left = input.getJLeft();
		final Resource origin = input.getJOrigin();
		final Resource right = input.getJRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(5, differences.size());
		assertEquals(2, conflicts.size());

		for (Conflict conflict : conflicts) {
			assertSame(PSEUDO, conflict.getKind());
			assertEquals(2, conflict.getDifferences().size());
		}
	}

	@Test
	public void testK1UseCase() throws IOException {
		final Resource left = input.getK1Left();
		final Resource origin = input.getK1Origin();
		final Resource right = input.getK1Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(6, differences.size());
		assertEquals(2, conflicts.size());

		Iterable<Conflict> realConflicts = filter(conflicts, containsConflictOfTypes(REAL));
		Iterable<Conflict> pseudoConflicts = filter(conflicts, containsConflictOfTypes(PSEUDO));

		assertEquals(1, size(realConflicts));
		assertEquals(1, size(pseudoConflicts));
	}

	@Test
	public void testK2UseCase() throws IOException {
		final Resource left = input.getK2Left();
		final Resource origin = input.getK2Origin();
		final Resource right = input.getK2Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(8, differences.size());
		assertEquals(3, conflicts.size());

		Iterable<Conflict> realConflicts = filter(conflicts, containsConflictOfTypes(REAL));
		Iterable<Conflict> pseudoConflicts = filter(conflicts, containsConflictOfTypes(PSEUDO));

		assertEquals(1, size(realConflicts));
		assertEquals(2, size(pseudoConflicts));
	}

	@Test
	public void testK3UseCase() throws IOException {
		final Resource left = input.getK3Left();
		final Resource origin = input.getK3Origin();
		final Resource right = input.getK3Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(6, differences.size());
		assertEquals(3, conflicts.size());

		Iterable<Conflict> realConflicts = filter(conflicts, containsConflictOfTypes(REAL));
		Iterable<Conflict> pseudoConflicts = filter(conflicts, containsConflictOfTypes(PSEUDO));

		assertEquals(1, size(realConflicts));
		assertEquals(2, size(pseudoConflicts));
	}

	@Test
	public void testK4UseCase() throws IOException {
		final Resource left = input.getK4Left();
		final Resource origin = input.getK4Origin();
		final Resource right = input.getK4Right();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(4, differences.size());
		assertEquals(2, conflicts.size());

		assertEquals(PSEUDO, conflicts.get(0).getKind());
		assertEquals(REAL, conflicts.get(1).getKind());

	}

	@Test
	public void testComplexUseCase() throws IOException {
		final Resource left = input.getComplexLeft();
		final Resource origin = input.getComplexOrigin();
		final Resource right = input.getComplexRight();

		final IComparisonScope scope = new DefaultComparisonScope(left, right, origin);
		final Comparison comparison = EMFCompare.builder().build().compare(scope);

		final List<Diff> differences = comparison.getDifferences();
		final List<Conflict> conflicts = comparison.getConflicts();

		/*
		 * This use case features 12 distinct differences of all types, adding up to 4 real conflict and 1
		 * pseudo conflicts.
		 */
		// 1 - Left : Node8 added
		// 2 - Left : Node9 added
		// 3 - Left : Node1 moved
		// 4 - Left : Node0 added
		// 5 - Left : Node5 removed
		// 6 - Left : Node6 removed
		// 7 - Left : Node7 removed

		// 8 - Right : Node6 moved
		// 9 - Right : Node9 added
		// 10 - Right : Node0 added
		// 11 - Right : Node1 moved
		// 12 - Right : Node5 removed

		// Real conflict : 6 and 8 (Moving and deleting the same value)
		// Real conflict : 2 and 9 (Adding the same value at different indices)
		// Real conflict : 4 and 10 (Adding the same value at different indices)
		// Real conflict : 3 and 11 (Moving the same value to different indices)

		// Pseudo conflict : 5 and 12 (Removing the same value on both sides)

		assertEquals(12, differences.size());
		assertEquals(5, conflicts.size());

		final Predicate<? super Diff> leftDiff1Description = added("Root.Node8");
		final Predicate<? super Diff> leftDiff2Description = added("Root.Node9");
		final Predicate<? super Diff> leftDiff3Description = moved("Root.Node1", "containmentRef1");
		final Predicate<? super Diff> leftDiff4Description = added("Root.Node0");
		final Predicate<? super Diff> leftDiff5Description = removed("Root.Node5");
		final Predicate<? super Diff> leftDiff6Description = removed("Root.Node6");
		final Predicate<? super Diff> leftDiff7Description = removed("Root.Node7");

		final Predicate<? super Diff> rightDiff8Description = moved("Root.Node6", "containmentRef1");
		final Predicate<? super Diff> rightDiff9Description = added("Root.Node9");
		final Predicate<? super Diff> rightDiff10Description = added("Root.Node0");
		final Predicate<? super Diff> rightDiff11Description = moved("Root.Node1", "containmentRef1");
		final Predicate<? super Diff> rightDiff12Description = removed("Root.Node5");

		final Diff leftDiff1 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff1Description));
		final Diff leftDiff2 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff2Description));
		final Diff leftDiff3 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff3Description));
		final Diff leftDiff4 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff4Description));
		final Diff leftDiff5 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff5Description));
		final Diff leftDiff6 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff6Description));
		final Diff leftDiff7 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.LEFT), leftDiff7Description));

		final Diff rightDiff8 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiff8Description));
		final Diff rightDiff9 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiff9Description));
		final Diff rightDiff10 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiff10Description));
		final Diff rightDiff11 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiff11Description));
		final Diff rightDiff12 = Iterators.find(differences.iterator(),
				and(fromSide(DifferenceSource.RIGHT), rightDiff12Description));

		assertNotNull(leftDiff1);
		assertNotNull(leftDiff2);
		assertNotNull(leftDiff3);
		assertNotNull(leftDiff4);
		assertNotNull(leftDiff5);
		assertNotNull(leftDiff6);
		assertNotNull(leftDiff7);

		assertNotNull(rightDiff8);
		assertNotNull(rightDiff9);
		assertNotNull(rightDiff10);
		assertNotNull(rightDiff11);
		assertNotNull(rightDiff12);

		// We know there are 5 conflicts here
		for (Conflict conflict : conflicts) {
			final List<Diff> conflictDiffs = conflict.getDifferences();
			assertEquals(2, conflictDiffs.size());
			if (conflictDiffs.contains(leftDiff6)) {
				assertTrue(conflictDiffs.contains(rightDiff8));
				assertSame(REAL, conflict.getKind());
			} else if (conflictDiffs.contains(leftDiff2)) {
				assertTrue(conflictDiffs.contains(rightDiff9));
				assertSame(REAL, conflict.getKind());
			} else if (conflictDiffs.contains(leftDiff4)) {
				assertTrue(conflictDiffs.contains(rightDiff10));
				assertSame(REAL, conflict.getKind());
			} else if (conflictDiffs.contains(leftDiff3)) {
				assertTrue(conflictDiffs.contains(rightDiff11));
				assertSame(REAL, conflict.getKind());
			} else if (conflictDiffs.contains(leftDiff5)) {
				assertTrue(conflictDiffs.contains(rightDiff12));
				assertSame(PSEUDO, conflict.getKind());
			} else {
				fail("unexpected conflict");
			}
		}
	}

	/**
	 * Make sure that and RAC:DELETE is not in conflict with a change on its EObject if this EObject had an
	 * eContainer in the ancestor (i.e. when there is a ReferenceChange:DLETE of a containment reference to
	 * conflict with)
	 */
	@Test
	public void testDanglingRACTest() throws Exception {
		ResourceSet rsAncestor = input.getRACDanglingConflictAncestorModel();
		ResourceSet rsLeft = input.getRACDanglingConflictLeftModel();
		ResourceSet rsRight = input.getRACDanglingConflictRightModel();

		IComparisonScope scope = new DefaultComparisonScope(rsLeft, rsRight, rsAncestor);
		Comparison comparison = EMFCompare.builder().build().compare(scope);

		List<Diff> differences = comparison.getDifferences();
		List<Conflict> conflicts = comparison.getConflicts();

		assertEquals(5, differences.size());
		assertEquals(2, conflicts.size());
		assertEquals(4, size(filter(differences, hasConflict(REAL))));
		Iterable<Diff> nonConflictingDiffs = filter(differences, not(hasConflict(REAL, PSEUDO)));
		assertEquals(1, size(nonConflictingDiffs));
		Diff nonConflictingDiff = nonConflictingDiffs.iterator().next();
		assertTrue(nonConflictingDiff instanceof ResourceAttachmentChange);
		assertEquals(DifferenceSource.RIGHT, nonConflictingDiff.getSource());
		assertTrue(
				((ResourceAttachmentChange)nonConflictingDiff).getResourceURI().endsWith("fragment.nodes"));
	}
}
