/******************************************************************************* * Copyright (c) 2012 itemis AG (http://www.itemis.eu) 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 *******************************************************************************/ package org.xpect.ui.junit; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.List; import org.apache.log4j.Logger; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.IEditableContent; import org.eclipse.compare.IModificationDate; import org.eclipse.compare.IStreamContentAccessor; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.ResourceNode; import org.eclipse.compare.internal.ICompareUIConstants; import org.eclipse.compare.structuremergeviewer.DiffNode; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.junit.model.ITestCaseElement; import org.eclipse.jdt.junit.model.ITestElement.FailureTrace; import org.eclipse.swt.graphics.Image; import org.eclipse.xtext.util.Exceptions; import org.xpect.text.IReplacement; import org.xpect.text.Text; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; /** * @author Moritz Eysholdt - Initial contribution and API */ @SuppressWarnings("restriction") public class FailureCompareEditorInput extends CompareEditorInput { protected static class CompareItem implements IStreamContentAccessor, ITypedElement, IModificationDate { private String contents, name; CompareItem(String name, String contents) { this.name = name; this.contents = contents; } public InputStream getContents() throws CoreException { return new ByteArrayInputStream(contents.getBytes()); } public Image getImage() { return null; } public long getModificationDate() { return 0; } public String getName() { return name; } public String getString() { return contents; } public String getType() { return ITypedElement.TEXT_TYPE; } } protected static class EditableCompareItem extends CompareItem implements IEditableContent { private final IFile file; EditableCompareItem(String name, String contents, IFile file) { super(name, contents); this.file = file; } public boolean isEditable() { return file != null; } public ITypedElement replace(ITypedElement dest, ITypedElement src) { return null; } public void setContent(byte[] newContent) { ByteArrayInputStream inputStream = new ByteArrayInputStream(newContent); try { file.setContents(inputStream, true, true, new NullProgressMonitor()); } catch (CoreException e) { LOG.error(e); } } } private final static Logger LOG = Logger.getLogger(FailureCompareEditorInput.class); protected static CompareConfiguration createConfiguration(IFile file) { CompareConfiguration configuration = new CompareConfiguration(); configuration.setLeftEditable(true); configuration.setLeftLabel("Expected Test Result" + (file != null ? " - " + file.getName() : "")); configuration.setRightLabel("Actual Test Result"); configuration.setAncestorLabel("File on Disk"); configuration.setProperty(ICompareUIConstants.PROP_ANCESTOR_VISIBLE, Boolean.FALSE); return configuration; } private IFile file; private Collection<ITestCaseElement> testElements; public FailureCompareEditorInput(IFile file, Collection<ITestCaseElement> testElements) { super(createConfiguration(file)); Preconditions.checkNotNull(file); Preconditions.checkArgument(testElements.size() > 0); this.testElements = testElements; this.file = file; } @Override public String getTitle() { return file.getName(); } protected Object prepareInput(IProgressMonitor pm) { try { ResourceNode ancestor = new ResourceNode(file); String ancestorContent = getContent(ancestor); String leftContent, rightContent; if (testElements.size() == 1) { FailureTrace trace = testElements.iterator().next().getFailureTrace(); leftContent = trace.getExpected(); rightContent = trace.getActual(); } else { List<IReplacement> expectations = Lists.newArrayList(); List<IReplacement> actuals = Lists.newArrayList(); Text ancestorText = new Text(ancestorContent); for (ITestCaseElement t : testElements) { IReplacement expected = ancestorText.replacementTo(t.getFailureTrace().getExpected()); IReplacement actual = ancestorText.replacementTo(t.getFailureTrace().getActual()); if (expected != null) expectations.add(expected); if (actual != null) actuals.add(actual); } leftContent = ancestorText.with(expectations); rightContent = ancestorText.with(actuals); } if (!leftContent.equals(ancestorContent)) getCompareConfiguration().setProperty(ICompareUIConstants.PROP_ANCESTOR_VISIBLE, Boolean.TRUE); CompareItem left = new EditableCompareItem("Left", leftContent, file); CompareItem right = new CompareItem("Right", rightContent); return new DiffNode(null, Differencer.CHANGE | Differencer.DIRECTION_MASK, ancestor, left, right); } catch (Throwable t) { LOG.error(t.getMessage(), t); Exceptions.throwUncheckedException(t); return null; } } private String getContent(ResourceNode ancestor) { try { return new String(ancestor.getContent(), file.getCharset()); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } catch (CoreException e) { throw new RuntimeException(e); } } }