| /******************************************************************************* |
| * Copyright (c) 2012, 2013 Tasktop Technologies 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: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.context.tests; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintStream; |
| import java.util.Arrays; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.mylyn.commons.sdk.util.CommonTestUtil; |
| import org.eclipse.mylyn.commons.sdk.util.UiTestUtil; |
| import org.eclipse.mylyn.context.core.IInteractionContext; |
| import org.eclipse.mylyn.internal.context.core.InteractionContext; |
| import org.eclipse.mylyn.internal.context.core.InteractionContextScaling; |
| import org.eclipse.mylyn.internal.context.ui.state.ContextState; |
| import org.eclipse.mylyn.internal.context.ui.state.EditorStateParticipant; |
| import org.eclipse.mylyn.internal.monitor.ui.MonitorUiPlugin; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.IEditorDescriptor; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorReference; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.XMLMemento; |
| import org.eclipse.ui.internal.WorkbenchPage; |
| import org.eclipse.ui.part.FileEditorInput; |
| |
| import junit.framework.TestCase; |
| |
| /** |
| * @author Steffen Pingel |
| */ |
| public class EditorStateParticipantTest extends TestCase { |
| |
| private final class MyEditorStateParticipant extends EditorStateParticipant { |
| // make visible |
| @Override |
| protected boolean is_3_x() { |
| return super.is_3_x(); |
| } |
| |
| @Override |
| protected void saveEditors_e_3_x(WorkbenchPage page, IMemento memento) throws Exception { |
| if (exceptionOnSave != null) { |
| throw exceptionOnSave; |
| } |
| super.saveEditors_e_3_x(page, memento); |
| } |
| |
| @Override |
| protected void saveEditors_e_8_2(IWorkbenchPage page, IMemento memento) throws Exception { |
| if (exceptionOnSave != null) { |
| throw exceptionOnSave; |
| } |
| super.saveEditors_e_8_2(page, memento); |
| } |
| |
| @Override |
| protected void saveEditors_e_4_legacy(WorkbenchPage page, IMemento memento) throws Exception { |
| if (exceptionOnSave != null) { |
| throw exceptionOnSave; |
| } |
| super.saveEditors_e_4_legacy(page, memento); |
| } |
| } |
| |
| private final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| |
| private IProject project; |
| |
| private IFile fileA; |
| |
| private IFile fileB; |
| |
| private MyEditorStateParticipant participant; |
| |
| private Exception exceptionOnSave; |
| |
| @Override |
| protected void setUp() throws Exception { |
| participant = new MyEditorStateParticipant(); |
| assertTrue(participant.isEnabled()); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| UiTestUtil.closeAllEditors(); |
| |
| if (project != null) { |
| project.delete(true, null); |
| } |
| } |
| |
| public void testSaveState() { |
| XMLMemento memento = XMLMemento.createWriteRoot("State"); |
| IInteractionContext context = new InteractionContext("id", new InteractionContextScaling()); |
| ContextState state = new ContextState(context, context.getHandleIdentifier(), memento); |
| participant.saveState(state, true); |
| assertNotNull(memento.getChild(EditorStateParticipant.MEMENTO_EDITORS)); |
| } |
| |
| public void testSaveRestore() throws Exception { |
| createFilesAndOpenEditors(); |
| |
| XMLMemento memento = XMLMemento.createWriteRoot("State"); |
| IInteractionContext context = new InteractionContext("id", new InteractionContextScaling()); |
| ContextState state = new ContextState(context, context.getHandleIdentifier(), memento); |
| participant.saveState(state, true); |
| System.err.println(toString((XMLMemento) state.getMemento(EditorStateParticipant.MEMENTO_EDITORS))); |
| participant.closeAllEditors(); |
| participant.restoreState(state); |
| assertEquals("Expected 2 editors, got: " + Arrays.asList(page.getEditorReferences()), 2, |
| page.getEditorReferences().length); |
| assertEquals(new FileEditorInput(fileB), page.getEditorReferences()[0].getEditorInput()); |
| assertEquals(new FileEditorInput(fileA), page.getEditorReferences()[1].getEditorInput()); |
| } |
| |
| public void testRestoreState_3_7() throws Exception { |
| createFiles(); |
| |
| XMLMemento memento = XMLMemento.createReadRoot(new InputStreamReader( |
| CommonTestUtil.getResource(this, "testdata/EditorStateParticipantTest/state-3.7.xml"))); |
| IInteractionContext context = new InteractionContext("id", new InteractionContextScaling()); |
| ContextState state = new ContextState(context, context.getHandleIdentifier(), memento); |
| participant.restoreState(state); |
| assertEquals("Expected 2 editors, got: " + Arrays.asList(page.getEditorReferences()), 2, |
| page.getEditorReferences().length); |
| assertEquals(new FileEditorInput(fileB), page.getEditorReferences()[0].getEditorInput()); |
| assertEquals(new FileEditorInput(fileA), page.getEditorReferences()[1].getEditorInput()); |
| assertNotNull(memento.getChild(EditorStateParticipant.MEMENTO_EDITORS)); |
| } |
| |
| public void testRestoreState_4_1() throws Exception { |
| createFiles(); |
| |
| XMLMemento memento = XMLMemento.createReadRoot(new InputStreamReader( |
| CommonTestUtil.getResource(this, "testdata/EditorStateParticipantTest/state-4.1.xml"))); |
| IInteractionContext context = new InteractionContext("id", new InteractionContextScaling()); |
| ContextState state = new ContextState(context, context.getHandleIdentifier(), memento); |
| participant.restoreState(state); |
| if (participant.is_3_x()) { |
| // 3.x doesn't have sufficient properties to restore editors persisted with 4.x |
| assertEquals("Expected 0 editors, got: " + Arrays.asList(page.getEditorReferences()), 0, |
| page.getEditorReferences().length); |
| } else { |
| assertEquals("Expected 2 editors, got: " + Arrays.asList(page.getEditorReferences()), 2, |
| page.getEditorReferences().length); |
| assertEquals(new FileEditorInput(fileB), page.getEditorReferences()[0].getEditorInput()); |
| assertEquals(new FileEditorInput(fileA), page.getEditorReferences()[1].getEditorInput()); |
| } |
| assertNotNull(memento.getChild(EditorStateParticipant.MEMENTO_EDITORS)); |
| } |
| |
| public void testRestoreStateRetainState() throws Exception { |
| waitForMylynMonitorToStart(); |
| createFiles(); |
| |
| exceptionOnSave = new RuntimeException("Injected error to cause editor save to fail"); |
| |
| XMLMemento memento = XMLMemento.createReadRoot( |
| new InputStreamReader( |
| CommonTestUtil.getResource(this, "testdata/EditorStateParticipantTest/state-3.7.xml")), |
| "UTF-8"); |
| IInteractionContext context = new InteractionContext("id", new InteractionContextScaling()); |
| ContextState state = new ContextState(context, context.getHandleIdentifier(), memento); |
| participant.restoreState(state); |
| XMLMemento memento2 = XMLMemento.createWriteRoot("State"); |
| ContextState state2 = new ContextState(context, context.getHandleIdentifier(), memento2); |
| participant.saveState(state2, true); |
| assertEquals(toString(memento), toString(memento2)); |
| } |
| |
| private void waitForMylynMonitorToStart() { |
| MonitorUiPlugin.getDefault(); |
| while (Display.getCurrent().readAndDispatch()) { |
| } |
| } |
| |
| public void testNoEditorsState() throws Exception { |
| createFiles(); |
| |
| PrintStream prevErr = System.err; |
| try { |
| IsEmptyOutputStream os = new IsEmptyOutputStream(); |
| System.setErr(new PrintStream(os)); |
| |
| XMLMemento memento = XMLMemento.createReadRoot(new InputStreamReader( |
| CommonTestUtil.getResource(this, "testdata/EditorStateParticipantTest/state-noEditors.xml"))); |
| IInteractionContext context = new InteractionContext("id", new InteractionContextScaling()); |
| ContextState state = new ContextState(context, context.getHandleIdentifier(), memento); |
| participant.restoreState(state); |
| assertTrue(os.isEmpty()); |
| assertEquals(0, page.getEditorReferences().length); |
| assertNotNull(memento.getChild(EditorStateParticipant.MEMENTO_EDITORS)); |
| } finally { |
| System.setErr(prevErr); |
| } |
| } |
| |
| private String toString(XMLMemento memento) throws IOException { |
| File workspace = ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile(); |
| OutputStream out = new ByteArrayOutputStream(); |
| OutputStreamWriter writer = new OutputStreamWriter(out); |
| memento.save(writer); |
| String s = out.toString(); |
| // when reading from disk new lines are escaped |
| s = s.replaceAll("
", "\r"); |
| s = s.replaceAll("
", "\n"); |
| // always use LF as line separator |
| s = s.replaceAll("\r\n", "\n"); |
| // resolve workspace variable |
| s = s.replaceAll("WORKSPACE", workspace.getAbsolutePath()); |
| return s; |
| } |
| |
| /** |
| * Opens an editor for "b.txt" and "a.txt". |
| */ |
| private IEditorReference[] createFilesAndOpenEditors() throws Exception { |
| createFiles(); |
| |
| IEditorInput[] inputs; |
| if (CommonTestUtil.isEclipse4()) { |
| // on 3.x openEditors() opens editors starting from the first index |
| inputs = new IEditorInput[] { new FileEditorInput(fileB), new FileEditorInput(fileA) }; |
| } else { |
| // on 3.x openEditors() opens editors starting from the last index |
| inputs = new IEditorInput[] { new FileEditorInput(fileA), new FileEditorInput(fileB) }; |
| } |
| |
| IEditorDescriptor editor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(fileA.getName()); |
| String[] ids = new String[inputs.length]; |
| Arrays.fill(ids, editor.getId()); |
| IEditorReference[] refs = page.openEditors(inputs, ids, IWorkbenchPage.MATCH_NONE); |
| // realize editors to ensure they are persisted |
| for (IEditorReference ref : refs) { |
| ref.getEditor(true); |
| } |
| assertEquals(new FileEditorInput(fileB), page.getEditorReferences()[0].getEditorInput()); |
| assertEquals(new FileEditorInput(fileA), page.getEditorReferences()[1].getEditorInput()); |
| return refs; |
| } |
| |
| private void createFiles() throws CoreException { |
| project = ResourcesPlugin.getWorkspace().getRoot().getProject(getClass().getName()); |
| project.create(null); |
| project.open(null); |
| |
| fileA = project.getProject().getFile("a.txt"); |
| fileA.create(new ByteArrayInputStream("abc".getBytes()), false, null); |
| |
| fileB = project.getProject().getFile("b.txt"); |
| fileB.create(new ByteArrayInputStream("abc".getBytes()), false, null); |
| } |
| |
| private static class IsEmptyOutputStream extends OutputStream { |
| |
| private boolean empty = true; |
| |
| @Override |
| public void write(int b) throws IOException { |
| empty = false; |
| } |
| |
| public boolean isEmpty() { |
| return empty; |
| } |
| } |
| |
| } |