/*******************************************************************************
* Copyright (c) 2006, 2014 Wind River Systems, Inc. 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:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.internal.tests;
import java.util.Random;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.cdt.internal.core.PositionTracker;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
public class PositionTrackerTests extends TestCase {
public static Test suite() {
return new TestSuite(PositionTrackerTests.class);
}
public void testInitialFailures() {
int[][] moves = {
{46, -18, 95, -76, 98, -89, 10, -10, 85, -80, 16, 6, 5, -3,
22, -8, 29, -20, 86, -62, 34, -21, 63, -41, 9, 10, 18, -7},
{0, 2, 1,-4},
{4,-1, 0, 2, 0,-5},
{0, 1, 2, 1, 0,-5},
{0, 1, 2,-3, 1,-4},
{4, 3, 3,-2, 0,-1},
{4,-1, 3, 1, 2,-1},
{0, 1, 2, 8, 1,-8, 0,-10},
{4,-1, 2, 1, 4, 1, 0,-1, 0,-5},
};
int[] buffer = new int[100];
for (int i = 0; i < moves.length; i++) {
testMove(buffer, moves[i]);
}
}
public void testRotations() {
int[][] moves = { { 0, 1, 2, 1, 4, 1, 6, 1, 8, 1, 10, 1, 12, 1, 14, 1, 16, 1, 18, 1, 20, 1, 22, 1, 24, 1 }, {
15, 1, 14, 1, 13, 1, 12, 1, 11, 1, 10, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 1, 4, 1, 3, 1 }, {
0, 1, 10, 1, 2, 1, 20, 1, 4, 1, 20, 1, 6, 1, 20, 1, 8, 1, 20, 1, 10, 1, 20, 1, 12, 1 }, };
int[] buffer = new int[30];
for (int i = 0; i < moves.length; i++) {
assertTrue(testMove(buffer, moves[i]).depth() <= 5);
}
}
public void testDepth4() {
fullTest(5, 4);
}
public void testRandomDepth5() {
randomTest(20, 5, 5, 1000);
}
public void testRandomDepth10() {
randomTest(50, 10, 10, 1000);
}
public void testRandomDepth15() {
randomTest(100, 15, 15, 1000);
}
public void testRandomDepth20() {
randomTest(100, 15, 20, 1000);
}
public void testRetireDepth2() {
randomRetireTest(100, 10, 25, 2, 1000);
}
public void testRetireDepth5() {
randomRetireTest(100, 10, 10, 5, 1000);
}
public void testRetireDepth10() {
randomRetireTest(100, 10, 5, 10, 1000);
}
public static void fullTest(int len, int depth) {
// init buffer
int[] buffer = new int[len];
int[] move = new int[2 * depth];
for (int i = 0; i < move.length; i++) {
move[i] = -1;
}
while (nextMove(move, len)) {
testMove(buffer, move);
}
}
public static void randomTest(int buflen, int changelen, int depth, int count) {
// init buffer
Random rand = new Random();
int[] buffer = new int[buflen];
int[] move = new int[2 * depth];
for (int j = 0; j < count; j++) {
for (int i = 0; i < move.length; i += 2) {
move[i] = rand.nextInt(buflen);
move[i + 1] = rand.nextInt(2 * changelen) - changelen;
}
testMove(buffer, move);
}
}
public static void randomRetireTest(int buflen, int changelen, int depth, int trackerDepth, int count) {
// init buffer
Random rand = new Random();
int[] buffer = new int[buflen];
int[] move = new int[2 * depth];
for (int j = 0; j < count; j++) {
for (int i = 0; i < buffer.length; i++) {
buffer[i] = i;
}
PositionTracker t0 = null;
PositionTracker previous = null;
for (int t = 0; t < trackerDepth; t++) {
for (int i = 0; i < move.length; i += 2) {
move[i] = rand.nextInt(buflen);
move[i + 1] = rand.nextInt(2 * changelen) - changelen;
}
PositionTracker tracker = new PositionTracker();
if (previous != null) {
previous.retire(tracker);
}
doMove(buffer, move, tracker);
if (t0 == null) {
t0 = tracker;
}
previous = tracker;
}
check(t0, buffer);
}
}
static PositionTracker testMove(int[] buffer, int[] move) {
try {
return __testMove(buffer, move);
} catch (RuntimeException e) {
System.out.println("Error on move: "); //$NON-NLS-1$
for (int i = 0; i < move.length; i++) {
System.out.print(move[i] + ", "); //$NON-NLS-1$
}
System.out.println();
throw e;
} catch (Error e) {
System.out.println("Error on move: "); //$NON-NLS-1$
for (int i = 0; i < move.length; i++) {
System.out.print(move[i] + ", "); //$NON-NLS-1$
}
System.out.println();
throw e;
}
}
static PositionTracker __testMove(int[] buffer, int[] move) {
PositionTracker tracker = new PositionTracker();
for (int i = 0; i < buffer.length; i++) {
buffer[i] = i;
}
doMove(buffer, move, tracker);
check(tracker, buffer);
return tracker;
}
static void doMove(int[] buffer, int[] move, PositionTracker tracker) {
for (int i = 0; i < move.length; i += 2) {
int m1 = move[i];
int m2 = move[i + 1];
if (m1 == -1) {
break;
}
if (m2 > 0) {
tracker.insert(m1, m2);
for (int j = 0; j < buffer.length; j++) {
if (buffer[j] >= m1) {
buffer[j] += m2;
}
}
} else {
tracker.delete(m1, -m2);
int m3 = m1 - m2;
for (int j = 0; j < buffer.length; j++) {
if (buffer[j] >= m1) {
if (buffer[j] < m3) {
buffer[j] = -1;
} else {
buffer[j] += m2;
}
}
}
}
}
}
private static void check(PositionTracker tracker, int[] buffer) {
int lasti2 = -1;
for (int i = 0; i < buffer.length; i++) {
int i2 = buffer[i];
if (i2 >= 0) {
int i22 = tracker.currentOffset(i);
assertEquals(i22, i2);
assertTrue(lasti2 < i22);
lasti2 = i22;
assertEquals(i, tracker.historicOffset(i2));
}
}
}
private static boolean nextMove(int[] move, int bufLen) {
for (int i = 0; i < move.length; i += 2) {
int m1 = move[i];
if (m1 < 0) {
move[i] = 0;
move[i + 1] = -bufLen;
return true;
}
int m2 = ++move[i + 1];
if (m2 <= bufLen - m1) {
return true;
}
if (m1 < bufLen - 1) {
move[i]++;
move[i + 1] = -bufLen + m1 + 1;
return true;
}
move[i] = 0;
move[i + 1] = -bufLen;
}
return false;
}
public void testInsertion() {
PositionTracker pt= new PositionTracker();
pt.insert(1,1);
checkInsert11(pt);
}
private void checkInsert11(PositionTracker pt) {
// chars
doubleCheck(pt, 0, 0);
backwdCheck(pt, 1, 1);
doubleCheck(pt, 1, 2);
doubleCheck(pt, 2, 3);
// ranges
doubleRangeCheck(pt, new Region(0,2), new Region(0,3));
backwdRangeCheck(pt, new Region(0,1), new Region(0,2));
doubleRangeCheck(pt, new Region(0,1), new Region(0,1));
backwdRangeCheck(pt, new Region(1,0), new Region(1,1));
backwdRangeCheck(pt, new Region(1,0), new Region(1,0));
doubleRangeCheck(pt, new Region(1,1), new Region(2,1));
doubleRangeCheck(pt, new Region(1,0), new Region(2,0));
}
public void testDeletion() {
PositionTracker pt= new PositionTracker();
pt.delete(1,1);
checkDelete11(pt);
}
private void checkDelete11(PositionTracker pt) {
doubleCheck(pt, 0, 0);
fwdCheck (pt, 1, 1);
doubleCheck(pt, 2, 1);
doubleCheck(pt, 3, 2);
// ranges
doubleRangeCheck(pt, new Region(0,3), new Region(0,2));
fwdRangeCheck (pt, new Region(0,2), new Region(0,1));
doubleRangeCheck(pt, new Region(0,1), new Region(0,1));
fwdRangeCheck (pt, new Region(1,1), new Region(1,0));
fwdRangeCheck (pt, new Region(1,0), new Region(1,0));
doubleRangeCheck(pt, new Region(2,1), new Region(1,1));
doubleRangeCheck(pt, new Region(2,0), new Region(1,0));
}
public void testReplace() {
PositionTracker pt= new PositionTracker();
pt.delete(1,1);
pt.insert(1,1);
doubleCheck(pt, 0, 0);
doubleCheck(pt, 1, 1);
doubleCheck(pt, 2, 2);
doubleCheck(pt, 3, 3);
pt.clear();
pt.insert(1,1);
pt.delete(1,1);
doubleCheck(pt, 0, 0);
doubleCheck(pt, 1, 1);
doubleCheck(pt, 2, 2);
doubleCheck(pt, 3, 3);
pt.clear();
pt.delete(0,2);
pt.insert(0,1);
checkDelete11(pt);
pt.clear();
pt.insert(1,1);
pt.delete(1,2);
checkDelete11(pt);
pt.clear();
pt.insert(1,2);
pt.delete(1,1);
checkInsert11(pt);
pt.clear();
pt.delete(1,1);
pt.insert(1,2);
checkInsert11(pt);
}
private void doubleCheck(PositionTracker pt, int orig, int mapped) {
fwdCheck(pt, orig, mapped);
backwdCheck(pt, orig, mapped);
}
private void fwdCheck(PositionTracker pt, int orig, int mapped) {
assertEquals(mapped, pt.currentOffset(orig));
}
private void backwdCheck(PositionTracker pt, int orig, int mapped) {
assertEquals(orig, pt.historicOffset(mapped));
}
private void doubleRangeCheck(PositionTracker pt, IRegion orig, IRegion mapped) {
fwdRangeCheck(pt, orig, mapped);
backwdRangeCheck(pt, orig, mapped);
}
private void fwdRangeCheck(PositionTracker pt, IRegion orig, IRegion mapped) {
assertEquals(mapped, pt.historicToActual(orig));
}
private void backwdRangeCheck(PositionTracker pt, IRegion orig, IRegion mapped) {
assertEquals(orig, pt.actualToHistoric(mapped));
}
}