Fix InputPointersTests

InputPointers.getTime(int) has a validity check of time values. And
the check is enabled when LatinImeLogger.sDBG is on. Such situation
may occur while unit testing. This change ensure that time values are
monotonic while unit testing.

Change-Id: I9ff2cff2bcd253de0e8206dd3be964fe565170fa
main
Tadashi G. Takaoka 2014-01-07 17:43:44 +09:00
parent 385031557b
commit e7dc5302af
2 changed files with 167 additions and 99 deletions

View File

@ -16,14 +16,16 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.utils.ResizableIntArray; import com.android.inputmethod.latin.utils.ResizableIntArray;
import android.util.Log;
// TODO: This class is not thread-safe. // TODO: This class is not thread-safe.
public final class InputPointers { public final class InputPointers {
private static final String TAG = InputPointers.class.getSimpleName(); private static final String TAG = InputPointers.class.getSimpleName();
private static final boolean DEBUG_TIME = false;
private final int mDefaultCapacity; private final int mDefaultCapacity;
private final ResizableIntArray mXCoordinates; private final ResizableIntArray mXCoordinates;
private final ResizableIntArray mYCoordinates; private final ResizableIntArray mYCoordinates;
@ -38,10 +40,29 @@ public final class InputPointers {
mTimes = new ResizableIntArray(defaultCapacity); mTimes = new ResizableIntArray(defaultCapacity);
} }
private void fillWithLastTimeUntil(final int index) {
final int fromIndex = mTimes.getLength();
// Fill the gap with the latest time.
// See {@link #getTime(int)} and {@link #isValidTimeStamps()}.
if (fromIndex <= 0) {
return;
}
final int fillLength = index - fromIndex + 1;
if (fillLength <= 0) {
return;
}
final int lastTime = mTimes.get(fromIndex - 1);
mTimes.fill(lastTime, fromIndex, fillLength);
}
// TODO: Rename this method to addPointerAt
public void addPointer(int index, int x, int y, int pointerId, int time) { public void addPointer(int index, int x, int y, int pointerId, int time) {
mXCoordinates.add(index, x); mXCoordinates.add(index, x);
mYCoordinates.add(index, y); mYCoordinates.add(index, y);
mPointerIds.add(index, pointerId); mPointerIds.add(index, pointerId);
if (LatinImeLogger.sDBG || DEBUG_TIME) {
fillWithLastTimeUntil(index);
}
mTimes.add(index, time); mTimes.add(index, time);
} }
@ -67,23 +88,6 @@ public final class InputPointers {
mTimes.copy(ip.mTimes); mTimes.copy(ip.mTimes);
} }
/**
* Append the pointers in the specified {@link InputPointers} to the end of this.
* @param src the source {@link InputPointers} to read the data from.
* @param startPos the starting index of the pointers in {@code src}.
* @param length the number of pointers to be appended.
*/
@UsedForTesting
void append(InputPointers src, int startPos, int length) {
if (length == 0) {
return;
}
mXCoordinates.append(src.mXCoordinates, startPos, length);
mYCoordinates.append(src.mYCoordinates, startPos, length);
mPointerIds.append(src.mPointerIds, startPos, length);
mTimes.append(src.mTimes, startPos, length);
}
/** /**
* Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray} * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray}
* to the end of this. * to the end of this.
@ -141,7 +145,7 @@ public final class InputPointers {
} }
public int[] getTimes() { public int[] getTimes() {
if (LatinImeLogger.sDBG) { if (LatinImeLogger.sDBG || DEBUG_TIME) {
if (!isValidTimeStamps()) { if (!isValidTimeStamps()) {
throw new RuntimeException("Time stamps are invalid."); throw new RuntimeException("Time stamps are invalid.");
} }
@ -157,10 +161,11 @@ public final class InputPointers {
private boolean isValidTimeStamps() { private boolean isValidTimeStamps() {
final int[] times = mTimes.getPrimitiveArray(); final int[] times = mTimes.getPrimitiveArray();
for (int i = 1; i < getPointerSize(); ++i) { final int size = getPointerSize();
for (int i = 1; i < size; ++i) {
if (times[i] < times[i - 1]) { if (times[i] < times[i - 1]) {
// dump // dump
for (int j = 0; j < times.length; ++j) { for (int j = 0; j < size; ++j) {
Log.d(TAG, "--- (" + j + ") " + times[j]); Log.d(TAG, "--- (" + j + ") " + times[j]);
} }
return false; return false;

View File

@ -55,14 +55,22 @@ public class InputPointersTests extends AndroidTestCase {
final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
final int limit = src.getXCoordinates().length * 2 + 10; final int limit = src.getXCoordinates().length * 2 + 10;
for (int i = 0; i < limit; i++) { for (int i = 0; i < limit; i++) {
src.addPointer(i, i * 2, i * 3, i * 4); final int x = i;
final int y = i * 2;
final int pointerId = i * 3;
final int time = i * 4;
src.addPointer(x, y, pointerId, time);
assertEquals("size after add " + i, i + 1, src.getPointerSize()); assertEquals("size after add " + i, i + 1, src.getPointerSize());
} }
for (int i = 0; i < limit; i++) { for (int i = 0; i < limit; i++) {
assertEquals("xCoordinates at " + i, i, src.getXCoordinates()[i]); final int x = i;
assertEquals("yCoordinates at " + i, i * 2, src.getYCoordinates()[i]); final int y = i * 2;
assertEquals("pointerIds at " + i, i * 3, src.getPointerIds()[i]); final int pointerId = i * 3;
assertEquals("times at " + i, i * 4, src.getTimes()[i]); final int time = i * 4;
assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
assertEquals("times at " + i, time, src.getTimes()[i]);
} }
} }
@ -70,14 +78,22 @@ public class InputPointersTests extends AndroidTestCase {
final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
final int limit = 1000, step = 100; final int limit = 1000, step = 100;
for (int i = 0; i < limit; i += step) { for (int i = 0; i < limit; i += step) {
src.addPointer(i, i, i * 2, i * 3, i * 4); final int x = i;
final int y = i * 2;
final int pointerId = i * 3;
final int time = i * 4;
src.addPointer(i, x, y, pointerId, time);
assertEquals("size after add at " + i, i + 1, src.getPointerSize()); assertEquals("size after add at " + i, i + 1, src.getPointerSize());
} }
for (int i = 0; i < limit; i += step) { for (int i = 0; i < limit; i += step) {
assertEquals("xCoordinates at " + i, i, src.getXCoordinates()[i]); final int x = i;
assertEquals("yCoordinates at " + i, i * 2, src.getYCoordinates()[i]); final int y = i * 2;
assertEquals("pointerIds at " + i, i * 3, src.getPointerIds()[i]); final int pointerId = i * 3;
assertEquals("times at " + i, i * 4, src.getTimes()[i]); final int time = i * 4;
assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
assertEquals("times at " + i, time, src.getTimes()[i]);
} }
} }
@ -85,7 +101,11 @@ public class InputPointersTests extends AndroidTestCase {
final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
final int limit = src.getXCoordinates().length * 2 + 10; final int limit = src.getXCoordinates().length * 2 + 10;
for (int i = 0; i < limit; i++) { for (int i = 0; i < limit; i++) {
src.addPointer(i, i * 2, i * 3, i * 4); final int x = i;
final int y = i * 2;
final int pointerId = i * 3;
final int time = i * 4;
src.addPointer(x, y, pointerId, time);
} }
final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
dst.set(src); dst.set(src);
@ -100,7 +120,11 @@ public class InputPointersTests extends AndroidTestCase {
final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
final int limit = 100; final int limit = 100;
for (int i = 0; i < limit; i++) { for (int i = 0; i < limit; i++) {
src.addPointer(i, i * 2, i * 3, i * 4); final int x = i;
final int y = i * 2;
final int pointerId = i * 3;
final int time = i * 4;
src.addPointer(x, y, pointerId, time);
} }
final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
dst.copy(src); dst.copy(src);
@ -121,106 +145,135 @@ public class InputPointersTests extends AndroidTestCase {
} }
public void testAppend() { public void testAppend() {
final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final int dstLength = 50;
final int srcLen = 100;
for (int i = 0; i < srcLen; i++) {
src.addPointer(i, i * 2, i * 3, i * 4);
}
final int dstLen = 50;
final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
for (int i = 0; i < dstLen; i++) { for (int i = 0; i < dstLength; i++) {
final int value = -i - 1; final int x = i * 4;
dst.addPointer(value * 4, value * 3, value * 2, value); final int y = i * 3;
final int pointerId = i * 2;
final int time = i;
dst.addPointer(x, y, pointerId, time);
} }
final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY); final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
dstCopy.copy(dst); dstCopy.copy(dst);
dst.append(src, 0, 0); final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
assertEquals("size after append zero", dstLen, dst.getPointerSize()); final ResizableIntArray srcYCoords = new ResizableIntArray(DEFAULT_CAPACITY);
assertIntArrayEquals("xCoordinates after append zero", final ResizableIntArray srcPointerIds = new ResizableIntArray(DEFAULT_CAPACITY);
dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
assertIntArrayEquals("yCoordinates after append zero", final int srcLength = 100;
dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); final int srcPointerId = 10;
assertIntArrayEquals("pointerIds after append zero", for (int i = 0; i < srcLength; i++) {
dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); final int x = i;
assertIntArrayEquals("times after append zero", final int y = i * 2;
dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); // The time value must be larger than <code>dst</code>.
final int time = i * 4 + dstLength;
srcXCoords.add(x);
srcYCoords.add(y);
srcPointerIds.add(srcPointerId);
srcTimes.add(time);
}
dst.append(src, 0, srcLen); final int startPos = 0;
assertEquals("size after append", dstLen + srcLen, dst.getPointerSize()); dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
startPos, 0 /* length */);
assertEquals("size after append zero", dstLength, dst.getPointerSize());
assertIntArrayEquals("xCoordinates after append zero",
dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
assertIntArrayEquals("yCoordinates after append zero",
dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
assertIntArrayEquals("pointerIds after append zero",
dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
assertIntArrayEquals("times after append zero",
dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
startPos, srcLength);
assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
assertTrue("primitive length after append", assertTrue("primitive length after append",
dst.getPointerIds().length >= dstLen + srcLen); dst.getPointerIds().length >= dstLength + srcLength);
assertIntArrayEquals("original xCoordinates values after append", assertIntArrayEquals("original xCoordinates values after append",
dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
assertIntArrayEquals("original yCoordinates values after append", assertIntArrayEquals("original yCoordinates values after append",
dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
assertIntArrayEquals("original pointerIds values after append", assertIntArrayEquals("original pointerIds values after append",
dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
assertIntArrayEquals("original times values after append", assertIntArrayEquals("original times values after append",
dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
assertIntArrayEquals("appended xCoordinates values after append", assertIntArrayEquals("appended xCoordinates values after append",
src.getXCoordinates(), 0, dst.getXCoordinates(), dstLen, srcLen); srcXCoords.getPrimitiveArray(), startPos, dst.getXCoordinates(),
dstLength, srcLength);
assertIntArrayEquals("appended yCoordinates values after append", assertIntArrayEquals("appended yCoordinates values after append",
src.getYCoordinates(), 0, dst.getYCoordinates(), dstLen, srcLen); srcYCoords.getPrimitiveArray(), startPos, dst.getYCoordinates(),
dstLength, srcLength);
assertIntArrayEquals("appended pointerIds values after append", assertIntArrayEquals("appended pointerIds values after append",
src.getPointerIds(), 0, dst.getPointerIds(), dstLen, srcLen); srcPointerIds.getPrimitiveArray(), startPos, dst.getPointerIds(),
dstLength, srcLength);
assertIntArrayEquals("appended times values after append", assertIntArrayEquals("appended times values after append",
src.getTimes(), 0, dst.getTimes(), dstLen, srcLen); srcTimes.getPrimitiveArray(), startPos, dst.getTimes(), dstLength, srcLength);
} }
public void testAppendResizableIntArray() { public void testAppendResizableIntArray() {
final int srcLen = 100; final int dstLength = 50;
final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
for (int i = 0; i < dstLength; i++) {
final int x = i * 4;
final int y = i * 3;
final int pointerId = i * 2;
final int time = i;
dst.addPointer(x, y, pointerId, time);
}
final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
dstCopy.copy(dst);
final int srcLength = 100;
final int srcPointerId = 1; final int srcPointerId = 1;
final int[] srcPointerIds = new int[srcLen]; final int[] srcPointerIds = new int[srcLength];
Arrays.fill(srcPointerIds, srcPointerId); Arrays.fill(srcPointerIds, srcPointerId);
final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY); final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY); final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
final ResizableIntArray srcYCoords= new ResizableIntArray(DEFAULT_CAPACITY); final ResizableIntArray srcYCoords= new ResizableIntArray(DEFAULT_CAPACITY);
for (int i = 0; i < srcLen; i++) { for (int i = 0; i < srcLength; i++) {
srcTimes.add(i * 2); // The time value must be larger than <code>dst</code>.
srcXCoords.add(i * 3); final int time = i * 2 + dstLength;
srcYCoords.add(i * 4); final int x = i * 3;
final int y = i * 4;
srcTimes.add(time);
srcXCoords.add(x);
srcYCoords.add(y);
} }
final int dstLen = 50;
final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
for (int i = 0; i < dstLen; i++) {
final int value = -i - 1;
dst.addPointer(value * 4, value * 3, value * 2, value);
}
final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
dstCopy.copy(dst);
dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, 0); dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, 0);
assertEquals("size after append zero", dstLen, dst.getPointerSize()); assertEquals("size after append zero", dstLength, dst.getPointerSize());
assertIntArrayEquals("xCoordinates after append zero", assertIntArrayEquals("xCoordinates after append zero",
dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
assertIntArrayEquals("yCoordinates after append zero", assertIntArrayEquals("yCoordinates after append zero",
dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
assertIntArrayEquals("pointerIds after append zero", assertIntArrayEquals("pointerIds after append zero",
dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
assertIntArrayEquals("times after append zero", assertIntArrayEquals("times after append zero",
dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLen); dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLength);
assertEquals("size after append", dstLen + srcLen, dst.getPointerSize()); assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
assertTrue("primitive length after append", assertTrue("primitive length after append",
dst.getPointerIds().length >= dstLen + srcLen); dst.getPointerIds().length >= dstLength + srcLength);
assertIntArrayEquals("original xCoordinates values after append", assertIntArrayEquals("original xCoordinates values after append",
dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
assertIntArrayEquals("original yCoordinates values after append", assertIntArrayEquals("original yCoordinates values after append",
dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
assertIntArrayEquals("original pointerIds values after append", assertIntArrayEquals("original pointerIds values after append",
dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
assertIntArrayEquals("original times values after append", assertIntArrayEquals("original times values after append",
dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
assertIntArrayEquals("appended xCoordinates values after append", assertIntArrayEquals("appended xCoordinates values after append",
srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLen, srcLen); srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLength, srcLength);
assertIntArrayEquals("appended yCoordinates values after append", assertIntArrayEquals("appended yCoordinates values after append",
srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLen, srcLen); srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLength, srcLength);
assertIntArrayEquals("appended pointerIds values after append", assertIntArrayEquals("appended pointerIds values after append",
srcPointerIds, 0, dst.getPointerIds(), dstLen, srcLen); srcPointerIds, 0, dst.getPointerIds(), dstLength, srcLength);
assertIntArrayEquals("appended times values after append", assertIntArrayEquals("appended times values after append",
srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLen, srcLen); srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLength, srcLength);
} }
// TODO: Consolidate this method with // TODO: Consolidate this method with
@ -250,14 +303,24 @@ public class InputPointersTests extends AndroidTestCase {
final int limit = 100; final int limit = 100;
final int shiftAmount = 20; final int shiftAmount = 20;
for (int i = 0; i < limit; i++) { for (int i = 0; i < limit; i++) {
src.addPointer(i, i * 2, i * 3, i * 4); final int x = i;
final int y = i * 2;
final int pointerId = i * 3;
final int time = i * 4;
src.addPointer(x, y, pointerId, time);
} }
src.shift(shiftAmount); src.shift(shiftAmount);
assertEquals("length after shift", src.getPointerSize(), limit - shiftAmount);
for (int i = 0; i < limit - shiftAmount; ++i) { for (int i = 0; i < limit - shiftAmount; ++i) {
assertEquals("xCoordinates at " + i, i + shiftAmount, src.getXCoordinates()[i]); final int oldIndex = i + shiftAmount;
assertEquals("yCoordinates at " + i, (i + shiftAmount) * 2, src.getYCoordinates()[i]); final int x = oldIndex;
assertEquals("pointerIds at " + i, (i + shiftAmount) * 3, src.getPointerIds()[i]); final int y = oldIndex * 2;
assertEquals("times at " + i, (i + shiftAmount) * 4, src.getTimes()[i]); final int pointerId = oldIndex * 3;
final int time = oldIndex * 4;
assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
assertEquals("times at " + i, time, src.getTimes()[i]);
} }
} }
} }