| /******************************************************************************* |
| * Copyright (c) 2006, 2015 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.compare.tests; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import junit.framework.TestCase; |
| |
| import org.eclipse.compare.CompareConfiguration; |
| import org.eclipse.compare.ICompareFilter; |
| import org.eclipse.compare.IEditableContent; |
| import org.eclipse.compare.IStreamContentAccessor; |
| import org.eclipse.compare.ITypedElement; |
| import org.eclipse.compare.contentmergeviewer.TextMergeViewer; |
| import org.eclipse.compare.internal.ChangeCompareFilterPropertyAction; |
| import org.eclipse.compare.internal.IMergeViewerTestAdapter; |
| import org.eclipse.compare.internal.MergeViewerContentProvider; |
| import org.eclipse.compare.internal.Utilities; |
| import org.eclipse.compare.structuremergeviewer.DiffNode; |
| import org.eclipse.compare.structuremergeviewer.Differencer; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IDocumentPartitioner; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITypedRegion; |
| import org.eclipse.jface.text.Region; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.PlatformUI; |
| |
| public class TextMergeViewerTest extends TestCase { |
| |
| /** |
| * Returns a boolean value indicating whether or not the contents |
| * of the given streams are considered to be equal. Closes both input streams. |
| * @param a stream a |
| * @param b stream b |
| * @return whether the two streams contain the same contents |
| */ |
| public static boolean compareContent(InputStream a, InputStream b) { |
| int c, d; |
| if (a == null && b == null) |
| return true; |
| try { |
| if (a == null || b == null) |
| return false; |
| while ((c = a.read()) == (d = b.read()) && (c != -1 && d != -1)) { |
| //body not needed |
| } |
| return (c == -1 && d == -1); |
| } catch (IOException e) { |
| return false; |
| } finally { |
| try { |
| if (a != null) |
| a.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| try { |
| if (b != null) |
| b.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| } |
| |
| public static class TestElement implements ITypedElement { |
| public Image getImage() { |
| return null; |
| } |
| public String getName() { |
| return "test"; |
| } |
| public String getType() { |
| return UNKNOWN_TYPE; |
| } |
| } |
| |
| /** |
| * A parent test element is an {@link IEditableContent} but is not directly editable. |
| * The purpose of the parent is to be able to copy a child into the destination element. |
| */ |
| public static class ParentTestElement extends TestElement implements IEditableContent { |
| public boolean isEditable() { |
| return false; |
| } |
| public ITypedElement replace(ITypedElement child, ITypedElement other) { |
| if (child == null) { // add child |
| // clone the other and return it as the new child |
| if (other instanceof EditableTestElement) { |
| EditableTestElement ete = (EditableTestElement) other; |
| return (ITypedElement)ete.clone(); |
| } |
| } |
| if (other == null) { // delete child |
| // Return null as the new child |
| return null; |
| } |
| |
| if (other instanceof IStreamContentAccessor && child instanceof IEditableContent) { |
| IEditableContent dst= (IEditableContent) child; |
| |
| try { |
| InputStream is= ((IStreamContentAccessor)other).getContents(); |
| byte[] bytes= Utilities.readBytes(is); |
| if (bytes != null) |
| dst.setContent(bytes); |
| } catch (CoreException ex) { |
| throw new WrappedException(ex); |
| } |
| } |
| return child; |
| } |
| public void setContent(byte[] newContent) { |
| // Node is not directly editable |
| } |
| } |
| |
| public static class EditableTestElement extends TestElement implements IStreamContentAccessor, IEditableContent { |
| byte[] contents = new byte[0]; |
| public EditableTestElement(byte[] contents) { |
| this.contents = contents; |
| } |
| public String getType() { |
| return TEXT_TYPE; |
| } |
| public InputStream getContents() { |
| return new ByteArrayInputStream(contents); |
| } |
| protected Object clone() { |
| return new EditableTestElement(contents); |
| } |
| public boolean isEditable() { |
| return true; |
| } |
| public ITypedElement replace(ITypedElement dest, ITypedElement src) { |
| // Nothing to do since this node has no children |
| return null; |
| } |
| public void setContent(byte[] newContent) { |
| contents = newContent; |
| } |
| public boolean equals(Object obj) { |
| if (obj instanceof EditableTestElement) { |
| EditableTestElement other = (EditableTestElement) obj; |
| return TextMergeViewerTest.compareContent(other.getContents(), getContents()); |
| } |
| return false; |
| } |
| public Object getContentsAsString() { |
| return new String(contents); |
| } |
| } |
| |
| public static class TestMergeViewer extends TextMergeViewer { |
| public TestMergeViewer(Composite parent) { |
| super(parent, new CompareConfiguration()); |
| } |
| |
| public TestMergeViewer(Composite parent, CompareConfiguration cc) { |
| super(parent, cc); |
| } |
| |
| public void copy(boolean leftToRight) { |
| super.copy(leftToRight); |
| } |
| } |
| |
| public static class WrappedException extends RuntimeException { |
| private static final long serialVersionUID = 1L; |
| Exception exception; |
| public WrappedException(Exception exception) { |
| super(); |
| this.exception = exception; |
| } |
| public void throwException() throws Exception { |
| throw exception; |
| } |
| } |
| |
| TestMergeViewer viewer; |
| |
| public TextMergeViewerTest() { |
| super(); |
| } |
| |
| public TextMergeViewerTest(String name) { |
| super(name); |
| } |
| |
| private void runInDialog(Object input, Runnable runnable) throws Exception { |
| runInDialog(input, runnable, new CompareConfiguration()); |
| } |
| |
| private void runInDialog(Object input, Runnable runnable, |
| final CompareConfiguration cc) throws Exception { |
| Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); |
| Dialog dialog = new Dialog(shell) { |
| protected Control createDialogArea(Composite parent) { |
| Composite composite = (Composite) super.createDialogArea(parent); |
| viewer = new TestMergeViewer(composite, cc); |
| return composite; |
| } |
| }; |
| dialog.setBlockOnOpen(false); |
| dialog.open(); |
| viewer.setInput(input); |
| try { |
| runnable.run(); |
| } catch (WrappedException e) { |
| e.throwException(); |
| } |
| dialog.close(); |
| viewer = null; |
| } |
| |
| protected void saveViewerContents() { |
| try { |
| viewer.save(new NullProgressMonitor()); |
| } catch (CoreException e) { |
| throw new WrappedException(e); |
| } |
| } |
| |
| protected IDocument getDocument(boolean left) { |
| char leg = left ? MergeViewerContentProvider.LEFT_CONTRIBUTOR : MergeViewerContentProvider.RIGHT_CONTRIBUTOR; |
| IDocument document = Utilities.getDocument(leg, viewer.getInput(), true, true); |
| if (document == null) { |
| return viewer.getAdapter(IMergeViewerTestAdapter.class).getDocument(leg); |
| } |
| return document; |
| } |
| |
| public void testCopyRightToLeft() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| String copiedText = "hi there"; |
| DiffNode testNode = new DiffNode(parentNode, Differencer.CHANGE, null, new EditableTestElement("some text".getBytes()), new EditableTestElement(copiedText.getBytes())); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(false /* rightToLeft */); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(copiedText, ((EditableTestElement)testNode.getLeft()).getContentsAsString()); |
| } |
| |
| public void testCopyLeftToRight() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| String copiedText = "hi there"; |
| DiffNode testNode = new DiffNode(parentNode, Differencer.CHANGE, null, new EditableTestElement(copiedText.getBytes()), new EditableTestElement("some text".getBytes())); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(true /* leftToRight */); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(copiedText, ((EditableTestElement)testNode.getRight()).getContentsAsString()); |
| } |
| |
| public void testCopyRightToEmptyLeft() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.ADDITION, null, null, new EditableTestElement("hi there".getBytes())); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(false /* rightToLeft */); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(testNode.getRight(), testNode.getLeft()); |
| } |
| |
| public void testCopyLeftToEmptyRight() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.DELETION, null, new EditableTestElement("hi there".getBytes()), null); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(true /* leftToRight */); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(testNode.getRight(), testNode.getLeft()); |
| } |
| |
| public void testCopyEmptyLeftToRight() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.ADDITION, null, null, new EditableTestElement("hi there".getBytes())); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(true /* leftToRight */); |
| saveViewerContents(); |
| } |
| }); |
| assertNull(testNode.getLeft()); |
| assertNull(testNode.getRight()); |
| } |
| |
| public void testCopyEmptyRightToLeft() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.DELETION, null, new EditableTestElement("hi there".getBytes()), null); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(false /* rightToLeft */); |
| saveViewerContents(); |
| } |
| }); |
| assertNull(testNode.getLeft()); |
| assertNull(testNode.getRight()); |
| } |
| |
| public void testModifyLeft() throws Exception { |
| DiffNode testNode = new DiffNode(new EditableTestElement("hi there".getBytes()), null); |
| final String newText = "New text"; |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| IDocument doc = getDocument(true /* left */); |
| doc.set(newText); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(newText, ((EditableTestElement)testNode.getLeft()).getContentsAsString()); |
| } |
| |
| public void testModifyRight() throws Exception { |
| DiffNode testNode = new DiffNode(null, new EditableTestElement("hi there".getBytes())); |
| final String newText = "New text"; |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| IDocument doc = getDocument(false /* right */); |
| doc.set(newText); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(newText, ((EditableTestElement)testNode.getRight()).getContentsAsString()); |
| } |
| |
| public void testCopyEmptyRightToLeftAndModify() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.ADDITION, null, null, new EditableTestElement("hi there".getBytes())); |
| final String newText = "New text"; |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(false /* rightToLeft */); |
| IDocument doc = getDocument(true /* left */); |
| doc.set(newText); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(newText, ((EditableTestElement)testNode.getLeft()).getContentsAsString()); |
| } |
| |
| public void testCopyEmptyLeftToRightAndModify() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.DELETION, null, new EditableTestElement("hi there".getBytes()), null); |
| final String newText = "New text"; |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| viewer.copy(true /* leftToRight */); |
| IDocument doc = getDocument(false /* right */); |
| doc.set(newText); |
| saveViewerContents(); |
| } |
| }); |
| assertEquals(newText, ((EditableTestElement)testNode.getRight()).getContentsAsString()); |
| } |
| |
| public void testCompareFilter() throws Exception { |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), |
| new ParentTestElement()); |
| |
| final String leftString = "HI there"; |
| final String rightString = "hi there"; |
| final EditableTestElement leftElement = new EditableTestElement( |
| leftString.getBytes()); |
| final EditableTestElement rightElement = new EditableTestElement( |
| rightString.getBytes()); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.CHANGE, null, |
| leftElement, rightElement); |
| final CompareConfiguration cc = new CompareConfiguration(); |
| runInDialog(testNode, new Runnable() { |
| public void run() { |
| Object adapter = viewer |
| .getAdapter(IMergeViewerTestAdapter.class); |
| if (adapter instanceof IMergeViewerTestAdapter) { |
| IMergeViewerTestAdapter ta = (IMergeViewerTestAdapter) adapter; |
| assertEquals(ta.getChangesCount(), 1); |
| |
| Map filters = new HashMap(); |
| filters.put("filter.id", new ICompareFilter() { |
| public void setInput(Object input, Object ancestor, |
| Object left, Object right) { |
| assertTrue(leftElement == left); |
| assertTrue(rightElement == right); |
| } |
| |
| public IRegion[] getFilteredRegions( |
| HashMap lineComparison) { |
| Object thisLine = lineComparison.get(THIS_LINE); |
| Object thisContributor = lineComparison |
| .get(THIS_CONTRIBUTOR); |
| Object otherLine = lineComparison.get(OTHER_LINE); |
| Object otherContributor = lineComparison |
| .get(OTHER_CONTRIBUTOR); |
| |
| if (thisContributor.equals(new Character('L'))) { |
| assertEquals(thisLine, leftString); |
| assertEquals(otherContributor, new Character( |
| 'R')); |
| assertEquals(otherLine, rightString); |
| } else { |
| assertEquals(thisContributor, |
| new Character('R')); |
| assertEquals(thisLine, rightString); |
| assertEquals(otherContributor, new Character( |
| 'L')); |
| assertEquals(otherLine, leftString); |
| } |
| |
| if (thisContributor.equals(new Character('L'))) |
| return new IRegion[] { new Region(0, 1), |
| new Region(1, 1) }; |
| |
| return new IRegion[] { new Region(0, 2) }; |
| } |
| |
| public boolean isEnabledInitially() { |
| return false; |
| } |
| |
| public boolean canCacheFilteredRegions() { |
| return true; |
| } |
| |
| }); |
| |
| cc.setProperty( |
| ChangeCompareFilterPropertyAction.COMPARE_FILTERS, |
| filters); |
| assertEquals(ta.getChangesCount(), 0); |
| |
| cc.setProperty( |
| ChangeCompareFilterPropertyAction.COMPARE_FILTERS, |
| null); |
| assertEquals(ta.getChangesCount(), 1); |
| } |
| } |
| }, cc); |
| } |
| |
| |
| public void testDocumentAsTypedElement() throws Exception { |
| class DocumentAsTypedElement extends Document implements ITypedElement { |
| |
| public String getName() { |
| return "file"; |
| } |
| |
| public Image getImage() { |
| return null; |
| } |
| |
| public String getType() { |
| return ITypedElement.UNKNOWN_TYPE; |
| } |
| } |
| DiffNode parentNode = new DiffNode(new ParentTestElement(), new ParentTestElement()); |
| DocumentAsTypedElement leftDoc = new DocumentAsTypedElement(); |
| DocumentAsTypedElement rightDoc = new DocumentAsTypedElement(); |
| DiffNode testNode = new DiffNode(parentNode, Differencer.DELETION, null, leftDoc, rightDoc); |
| runInDialogWithPartioner(testNode, new Runnable() { |
| public void run() { |
| //Not needed |
| } |
| }, new CompareConfiguration()); |
| assertNotNull(leftDoc.getDocumentPartitioner()); |
| assertNotNull(rightDoc.getDocumentPartitioner()); |
| } |
| |
| |
| private void runInDialogWithPartioner(Object input, Runnable runnable, final CompareConfiguration cc) throws Exception { |
| Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); |
| Dialog dialog = new Dialog(shell) { |
| protected Control createDialogArea(Composite parent) { |
| Composite composite = (Composite) super.createDialogArea(parent); |
| viewer = new TestMergeViewerWithPartitioner(composite, cc); |
| return composite; |
| } |
| }; |
| dialog.setBlockOnOpen(false); |
| dialog.open(); |
| viewer.setInput(input); |
| try { |
| runnable.run(); |
| } catch (WrappedException e) { |
| e.throwException(); |
| } |
| dialog.close(); |
| viewer = null; |
| } |
| |
| //This viewer is used to provide a dummy partitioner |
| public static class TestMergeViewerWithPartitioner extends TestMergeViewer { |
| public class DummyPartitioner implements IDocumentPartitioner { |
| public void connect(IDocument document) { |
| //Nothing to do |
| } |
| |
| public void disconnect() { |
| //Nothing to do |
| } |
| |
| public void documentAboutToBeChanged(DocumentEvent event) { |
| //Nothing to do |
| } |
| |
| public boolean documentChanged(DocumentEvent event) { |
| return false; |
| } |
| |
| public String[] getLegalContentTypes() { |
| return null; |
| } |
| |
| public String getContentType(int offset) { |
| return null; |
| } |
| |
| public ITypedRegion[] computePartitioning(int offset, int length) { |
| return null; |
| } |
| |
| public ITypedRegion getPartition(int offset) { |
| return null; |
| } |
| |
| } |
| public TestMergeViewerWithPartitioner(Composite parent) { |
| super(parent, new CompareConfiguration()); |
| } |
| |
| public TestMergeViewerWithPartitioner(Composite parent, CompareConfiguration cc) { |
| super(parent, cc); |
| } |
| |
| public void copy(boolean leftToRight) { |
| super.copy(leftToRight); |
| } |
| protected IDocumentPartitioner getDocumentPartitioner() { |
| return new DummyPartitioner(); |
| } |
| } |
| } |