// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.collide.shared.ot; import static com.google.collide.dto.DocOpComponent.Type.DELETE; import static com.google.collide.dto.DocOpComponent.Type.INSERT; import static com.google.collide.dto.DocOpComponent.Type.RETAIN; import static com.google.collide.dto.DocOpComponent.Type.RETAIN_LINE; import com.google.collide.dto.DocOp; import com.google.collide.dto.DocOpComponent; import com.google.collide.dto.DocOpComponent.Delete; import com.google.collide.dto.DocOpComponent.Insert; import com.google.collide.dto.DocOpComponent.Retain; import com.google.collide.dto.DocOpComponent.RetainLine; import com.google.collide.dto.server.ServerDocOpFactory; import com.google.collide.dto.shared.DocOpFactory; import com.google.collide.shared.Pair; import com.google.collide.shared.document.TextChange; import com.google.collide.shared.ot.Composer.ComposeException; import org.junit.Assert; /** * Utility methods for testing document operations. * */ public class DocOpTestUtils extends Assert { public static void assertDocOpEquals(DocOp a, DocOp b) { try { assertSize(a.getComponents().size(), b); for (int i = 0; i < a.getComponents().size(); i++) { assertDocOpComponentEquals(a.getComponents().get(i), b.getComponents().get(i)); } } catch (AssertionError e) { AssertionError newE = new AssertionError("DocOps not equal:\n" + DocOpUtils.toString(a, false) + "\n" + DocOpUtils.toString(b, false)); newE.initCause(e); throw newE; } } public static void assertDocOpComponentEquals(DocOpComponent a, DocOpComponent b) { assertEquals("DocOpComponents are not equal", a.getType(), b.getType()); switch (a.getType()) { case INSERT: assertEquals(((Insert) a).getText(), ((Insert) b).getText()); break; case DELETE: assertEquals(((Delete) a).getText(), ((Delete) b).getText()); break; case RETAIN: assertEquals(((Retain) a).getCount(), ((Retain) b).getCount()); assertEquals(((Retain) a).hasTrailingNewline(), ((Retain) b).hasTrailingNewline()); break; case RETAIN_LINE: assertEquals(((RetainLine) a).getLineCount(), ((RetainLine) b).getLineCount()); break; default: assert false : "Fix test"; } } public static void assertDelete(String expectedDeleteText, DocOp op, int index) { DocOpComponent component = op.getComponents().get(index); assertEquals(DELETE, component.getType()); assertEquals(expectedDeleteText, ((Delete) component).getText()); } public static void assertInsert(String expectedInsertText, DocOp op, int index) { DocOpComponent component = op.getComponents().get(index); assertEquals(INSERT, component.getType()); assertEquals(expectedInsertText, ((Insert) component).getText()); } public static void assertRetain(int expectedRetainCount, boolean expectedHasTrailingNewline, DocOp op, int index) { DocOpComponent component = op.getComponents().get(index); assertEquals(RETAIN, component.getType()); Retain retain = (Retain) component; assertEquals(expectedRetainCount, retain.getCount()); assertEquals(expectedHasTrailingNewline, retain.hasTrailingNewline()); } public static void assertRetainLine(int expectedRetainLineCount, DocOp op, int index) { DocOpComponent component = op.getComponents().get(index); assertEquals(RETAIN_LINE, component.getType()); RetainLine retainLine = (RetainLine) component; assertEquals(expectedRetainLineCount, retainLine.getLineCount()); } public static void assertSize(int expectedComponentsSize, DocOp op) { assertEquals("DocOp sizes aren't equal", expectedComponentsSize, op.getComponents().size()); } public static void assertCompose(DocOp expected, DocOp a, DocOp b) { try { assertDocOpEquals(expected, compose(a, b)); } catch (ComposeException e) { throw new AssertionError(e); } } public static void assertComposeFails(DocOp a, DocOp b) { try { compose(a, b); throw new AssertionError("Compose should have failed"); } catch (Composer.ComposeException e) { } } /** * @see #assertCompose(DocOp, DocOp, DocOp) */ public static DocOp compose(DocOp a, DocOp b) throws ComposeException { Pair<DocOp, DocOp> composedDocOps = composeWithBothStartingStates(ServerDocOpFactory.INSTANCE, a, b); assertDocOpEquals(composedDocOps.first, composedDocOps.second); return composedDocOps.first; } public static DocOp asDocOp(TextChange textChange) { return DocOpUtils.createFromTextChange(ServerDocOpFactory.INSTANCE, textChange); } public static Pair<DocOp, DocOp> composeWithBothStartingStates(DocOpFactory factory, DocOp a, DocOp b) throws ComposeException { ComposeException e1 = null; DocOp composedDocOp1 = null; try { composedDocOp1 = Composer.composeWithStartState(factory, a, b, false); } catch (ComposeException e) { e1 = e; } ComposeException e2 = null; DocOp composedDocOp2 = null; try { composedDocOp2 = Composer.composeWithStartState(factory, a, b, true); } catch (ComposeException e) { e2 = e; } if ((e1 == null) != (e2 == null)) { throw new IllegalArgumentException( "One way of composition had an exception, the other didn't", e1 != null ? e1 : e2); } else if (e1 != null /* which means e2 != null too */) { throw e1; } return Pair.of(composedDocOp1, composedDocOp2); } }