blob: 425d9f519eac0e98d3c8e33e858b1ccdf4c53a90 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
import com.intellij.util.text.CharArrayUtil;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.api.Invocation;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.action.CustomAction;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Denis Zhdanov
* @since 12/01/2010
*/
public class CacheUpdateEventsStorageTest {
private CacheUpdateEventsStorage myStorage;
private Document myDocument;
private FoldingModelEx myFoldingModel;
private Editor myEditor;
private Mockery myMockery;
private String myText;
@Before
public void setUp() {
myText =
"line1\n" +
"line2\n" +
"line3\n" +
"line4\n" +
"line5\n" +
"line6\n" +
"line7";
myMockery = new JUnit4Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
myDocument = myMockery.mock(Document.class);
myFoldingModel = myMockery.mock(FoldingModelEx.class);
myEditor = myMockery.mock(Editor.class);
myMockery.checking(new Expectations() {{
allowing(myDocument).getTextLength(); will(new CustomAction("getTextLength()") {
@Override
public Object invoke(Invocation invocation) throws Throwable {
return myText.length();
}
});
allowing(myDocument).getLineNumber(with(any(int.class))); will(new CustomAction("getLineNumber()") {
@Override
public Object invoke(Invocation invocation) throws Throwable {
return getLineNumber((Integer)invocation.getParameter(0));
}
});
allowing(myDocument).getLineStartOffset(with(any(int.class))); will(new CustomAction("getLineStartOffset()") {
@Override
public Object invoke(Invocation invocation) throws Throwable {
return getLineStartOffset((Integer)invocation.getParameter(0));
}
});
allowing(myDocument).getLineEndOffset(with(any(int.class))); will(new CustomAction("getLineEndOffset()") {
@Override
public Object invoke(Invocation invocation) throws Throwable {
return getLineEndOffset((Integer)invocation.getParameter(0));
}
});
allowing(myFoldingModel).getCollapsedRegionAtOffset(with(any(int.class))); will(returnValue(null));
allowing(myEditor).getDocument(); will(returnValue(myDocument));
allowing(myEditor).getFoldingModel(); will(returnValue(myFoldingModel));
}});
myStorage = new CacheUpdateEventsStorage();
}
@After
public void checkExpectations() {
myMockery.assertIsSatisfied();
}
private int getLineNumber(int offset) {
if (offset == 0) {
return 0;
}
int line = -1;
int currentOffset = 0;
while (currentOffset < offset) {
line++;
currentOffset = CharArrayUtil.shiftForwardUntil(myText, currentOffset, "\n") + 1;
if (currentOffset == offset) {
line++;
}
}
return line;
}
private int getLineStartOffset(int line) {
if (line == 0) {
return 0;
}
int lineStartOffset = 0;
for (; line > 0; line--) {
lineStartOffset = CharArrayUtil.shiftForwardUntil(myText, lineStartOffset, "\n") + 1;
}
return lineStartOffset;
}
private int getLineEndOffset(int line) {
int lineEndOffset = -1;
for (; line >= 0; line--) {
lineEndOffset = CharArrayUtil.shiftForwardUntil(myText, lineEndOffset + 1, "\n") + 1;
}
lineEndOffset--;
return lineEndOffset;
}
@Test
public void newEventLaysBeforeSingleRegistered() {
int offset = myDocument.getLineStartOffset(2) + 2;
change(offset, "AB");
assertEquals(1, myStorage.getEvents().size());
change(1, "12");
checkOrder();
}
@Test
public void newEventLaysBetweenRegistered() {
int offset = myDocument.getLineStartOffset(5) + 2;
change(offset, "AB");
assertEquals(1, myStorage.getEvents().size());
checkOrder();
change(1, "CD");
assertEquals(2, myStorage.getEvents().size());
checkOrder();
offset = myDocument.getLineStartOffset(3) + 2;
change(offset, "EF");
assertEquals(3, myStorage.getEvents().size());
checkOrder();
}
@Test
public void mergeWithPrevious() {
change(1, "AB");
assertEquals(1, myStorage.getEvents().size());
int offset = myDocument.getLineStartOffset(1) + 2;
change(offset, "CD");
assertEquals(1, myStorage.getEvents().size());
IncrementalCacheUpdateEvent event = myStorage.getEvents().get(0);
assertEquals(0, event.getOldStartOffset());
assertEquals(myDocument.getLineEndOffset(1), event.getOldEndOffset());
}
@Test
public void mergeWithNext() {
int offset = myDocument.getLineStartOffset(1) + 2;
change(offset, "AB");
assertEquals(1, myStorage.getEvents().size());
change(1, "CD");
assertEquals(1, myStorage.getEvents().size());
IncrementalCacheUpdateEvent event = myStorage.getEvents().get(0);
assertEquals(0, event.getOldStartOffset());
assertEquals(myDocument.getLineEndOffset(1), event.getOldEndOffset());
}
@Test
public void mergePreviousAndNext() {
int offset = myDocument.getLineStartOffset(2) + 2;
change(offset, "AB");
assertEquals(1, myStorage.getEvents().size());
change(3, "CD");
assertEquals(2, myStorage.getEvents().size());
checkOrder();
offset = myDocument.getLineStartOffset(1) + 2;
change(offset, "EF");
assertEquals(1, myStorage.getEvents().size());
IncrementalCacheUpdateEvent event = myStorage.getEvents().get(0);
assertEquals(0, event.getOldStartOffset());
assertEquals(myDocument.getLineEndOffset(2), event.getOldEndOffset());
}
@Test
public void skipAddingNestedEvent() {
int offset = myDocument.getLineStartOffset(2) + 2;
change(offset, "1234567");
assertEquals(1, myStorage.getEvents().size());
IncrementalCacheUpdateEvent event = myStorage.getEvents().get(0);
change(offset + 2, "ABC");
assertEquals(1, myStorage.getEvents().size());
assertSame(event, myStorage.getEvents().get(0));
}
private void checkOrder() {
int startOffset = -1;
for (IncrementalCacheUpdateEvent event : myStorage.getEvents()) {
assertTrue(startOffset <= event.getOldStartOffset());
}
}
private void change(int offset, String newText) {
DocumentEventImpl event
= new DocumentEventImpl(myDocument, offset, myText.substring(offset, offset + newText.length()), newText, 1, false);
myStorage.add(myDocument, new IncrementalCacheUpdateEvent(event, myEditor));
}
}