AI 147450: CTS: add test cases for database.AbstractCursorTest, AbstractWindowedCursor, CursorJoiner, CursorWindow, DatabaseUtils, MatrixCursor and MergeCursor
Automated import of CL 147450
diff --git a/tests/tests/database/src/android/database/cts/AbstractCursorTest.java b/tests/tests/database/src/android/database/cts/AbstractCursorTest.java
new file mode 100644
index 0000000..8e0c2b9
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/AbstractCursorTest.java
@@ -0,0 +1,855 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.database.AbstractCursor;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.CursorIndexOutOfBoundsException;
+import android.database.CursorWindow;
+import android.database.DataSetObserver;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.os.Bundle;
+import android.test.InstrumentationTestCase;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * Test {@link AbstractCursor}.
+ */
+@TestTargetClass(AbstractCursor.class)
+public class AbstractCursorTest extends InstrumentationTestCase {
+ private static final int POSITION0 = 0;
+ private static final int POSITION1 = 1;
+ private static final int ROW_MAX = 10;
+ private static final int DATA_COUNT = 10;
+ private static final String[] COLUMN_NAMES1 = new String[] {
+ "_id", // 0
+ "number" // 1
+ };
+ private static final String[] COLUMN_NAMES = new String[] { "name", "number", "profit" };
+ private TestAbstractCursor mTestAbstractCursor;
+ private Object mLockObj = new Object();
+
+ private SQLiteDatabase mDatabase;
+ private File mDatabaseFile;
+ private AbstractCursor mDatabaseCursor;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ setupDatabase();
+ ArrayList<ArrayList> list = createTestList(ROW_MAX, COLUMN_NAMES.length);
+ mTestAbstractCursor = new TestAbstractCursor(COLUMN_NAMES, list);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "AbstractCursor",
+ args = {}
+ )
+ public void testConstructor() {
+ TestAbstractCursor abstractCursor = new TestAbstractCursor();
+ assertEquals(-1, abstractCursor.getPosition());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getBlob",
+ args = {int.class}
+ )
+ public void testGetBlob() {
+ try {
+ mTestAbstractCursor.getBlob(0);
+ fail("getBlob should throws a UnsupportedOperationException here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "registerDataSetObserver",
+ args = {android.database.DataSetObserver.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "unregisterDataSetObserver",
+ args = {android.database.DataSetObserver.class}
+ )
+ })
+ public void testRegisterDataSetObserver() {
+ MockDataSetObserver datasetObserver = new MockDataSetObserver();
+
+ try {
+ mDatabaseCursor.unregisterDataSetObserver(datasetObserver);
+ fail("Can't unregister DataSetObserver before it is registered.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ mDatabaseCursor.registerDataSetObserver(datasetObserver);
+
+ try {
+ mDatabaseCursor.registerDataSetObserver(datasetObserver);
+ fail("Can't register DataSetObserver twice before unregister it.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ mDatabaseCursor.unregisterDataSetObserver(datasetObserver);
+ mDatabaseCursor.registerDataSetObserver(datasetObserver);
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "registerContentObserver",
+ args = {android.database.ContentObserver.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "unregisterContentObserver",
+ args = {android.database.ContentObserver.class}
+ )
+ })
+ public void testRegisterContentObserver() {
+ MockContentObserver contentObserver = new MockContentObserver();
+
+ try {
+ mDatabaseCursor.unregisterContentObserver(contentObserver);
+ fail("Can't unregister ContentObserver before it is registered.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ mDatabaseCursor.registerContentObserver(contentObserver);
+
+ try {
+ mDatabaseCursor.registerContentObserver(contentObserver);
+ fail("Can't register DataSetObserver twice before unregister it.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ mDatabaseCursor.unregisterContentObserver(contentObserver);
+ mDatabaseCursor.registerContentObserver(contentObserver);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setNotificationUri",
+ args = {android.content.ContentResolver.class, android.net.Uri.class}
+ )
+ public void testSetNotificationUri() {
+ String MOCK_URI = "content://abstractrcursortest/testtable";
+ mDatabaseCursor.setNotificationUri(getInstrumentation().getContext().getContentResolver(),
+ Uri.parse(MOCK_URI));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "respond",
+ args = {android.os.Bundle.class}
+ )
+ public void testRespond() {
+ Bundle b = new Bundle();
+ Bundle bundle = mDatabaseCursor.respond(b);
+ assertSame(Bundle.EMPTY, bundle);
+
+ bundle = mDatabaseCursor.respond(null);
+ assertSame(Bundle.EMPTY, bundle);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "requery",
+ args = {}
+ )
+ public void testRequery() {
+ MockDataSetObserver mock = new MockDataSetObserver();
+ mDatabaseCursor.registerDataSetObserver(mock);
+ assertFalse(mock.hadCalledOnChanged());
+ mDatabaseCursor.requery();
+ assertTrue(mock.hadCalledOnChanged());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test onChange().Subclasses must call this method when they finish committing" +
+ " updates to notify all observers.",
+ method = "onChange",
+ args = {boolean.class}
+ )
+ public void testOnChange() throws InterruptedException {
+ MockContentObserver mock = new MockContentObserver();
+ mTestAbstractCursor.registerContentObserver(mock);
+ assertFalse(mock.hadCalledOnChange());
+ mTestAbstractCursor.onChange(true);
+ synchronized(mLockObj) {
+ if ( !mock.hadCalledOnChange() ) {
+ mLockObj.wait(5000);
+ }
+ }
+ assertTrue(mock.hadCalledOnChange());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "onMove",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "moveToFirst",
+ args = {}
+ )
+ })
+ public void testOnMove() {
+ mTestAbstractCursor.resetOnMoveRet();
+ assertFalse(mTestAbstractCursor.getOnMoveRet());
+ mTestAbstractCursor.moveToFirst();
+ mTestAbstractCursor.moveToPosition(5);
+ assertTrue(mTestAbstractCursor.getOnMoveRet());
+ assertEquals(0, mTestAbstractCursor.getOldPos());
+ assertEquals(5, mTestAbstractCursor.getNewPos());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "moveToPrevious",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "moveToPosition",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getPosition",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "moveToNext",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isFirst",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "moveToLast",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isLast",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isBeforeFirst",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isAfterLast",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "moveToFirst",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "move",
+ args = {int.class}
+ )
+ })
+ public void testMoveToPrevious() {
+ // Test moveToFirst, isFirst, moveToNext, getPosition
+ assertTrue(mDatabaseCursor.moveToFirst());
+ assertTrue(mDatabaseCursor.isFirst());
+ assertEquals(0, mDatabaseCursor.getPosition());
+ assertTrue(mDatabaseCursor.moveToNext());
+ assertEquals(1, mDatabaseCursor.getPosition());
+ assertFalse(mDatabaseCursor.isFirst());
+ assertTrue(mDatabaseCursor.moveToNext());
+ assertEquals(2, mDatabaseCursor.getPosition());
+
+ // invoke moveToPosition with a number larger than row count.
+ assertFalse(mDatabaseCursor.moveToPosition(30000));
+ assertEquals(mDatabaseCursor.getCount(), mDatabaseCursor.getPosition());
+
+ assertFalse(mDatabaseCursor.moveToPosition(-1));
+ assertEquals(-1, mDatabaseCursor.getPosition());
+ assertTrue(mDatabaseCursor.isBeforeFirst());
+
+ mDatabaseCursor.moveToPosition(5);
+ assertEquals(5, mDatabaseCursor.getPosition());
+
+ // Test moveToPrevious
+ assertTrue(mDatabaseCursor.moveToPrevious());
+ assertEquals(4, mDatabaseCursor.getPosition());
+ assertTrue(mDatabaseCursor.moveToPrevious());
+ assertEquals(3, mDatabaseCursor.getPosition());
+ assertTrue(mDatabaseCursor.moveToPrevious());
+ assertEquals(2, mDatabaseCursor.getPosition());
+
+ // Test moveToLast, isLast, moveToPrevius, isAfterLast.
+ assertFalse(mDatabaseCursor.isLast());
+ assertTrue(mDatabaseCursor.moveToLast());
+ assertTrue(mDatabaseCursor.isLast());
+ assertFalse(mDatabaseCursor.isAfterLast());
+
+ assertFalse(mDatabaseCursor.moveToNext());
+ assertTrue(mDatabaseCursor.isAfterLast());
+ assertFalse(mDatabaseCursor.moveToNext());
+ assertTrue(mDatabaseCursor.isAfterLast());
+ assertFalse(mDatabaseCursor.isLast());
+ assertTrue(mDatabaseCursor.moveToPrevious());
+ assertTrue(mDatabaseCursor.isLast());
+ assertTrue(mDatabaseCursor.moveToPrevious());
+ assertFalse(mDatabaseCursor.isLast());
+
+ // Test move(int).
+ mDatabaseCursor.moveToFirst();
+ assertEquals(0, mDatabaseCursor.getPosition());
+ assertFalse(mDatabaseCursor.move(-1));
+ assertEquals(-1, mDatabaseCursor.getPosition());
+ assertTrue(mDatabaseCursor.move(1));
+ assertEquals(0, mDatabaseCursor.getPosition());
+
+ assertTrue(mDatabaseCursor.move(5));
+ assertEquals(5, mDatabaseCursor.getPosition());
+ assertTrue(mDatabaseCursor.move(-1));
+ assertEquals(4, mDatabaseCursor.getPosition());
+
+ mDatabaseCursor.moveToLast();
+ assertTrue(mDatabaseCursor.isLast());
+ assertFalse(mDatabaseCursor.isAfterLast());
+ assertFalse(mDatabaseCursor.move(1));
+ assertFalse(mDatabaseCursor.isLast());
+ assertTrue(mDatabaseCursor.isAfterLast());
+ assertTrue(mDatabaseCursor.move(-1));
+ assertTrue(mDatabaseCursor.isLast());
+ assertFalse(mDatabaseCursor.isAfterLast());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isClosed",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "close",
+ args = {}
+ )
+ })
+ public void testIsClosed() {
+ assertFalse(mDatabaseCursor.isClosed());
+ mDatabaseCursor.close();
+ assertTrue(mDatabaseCursor.isClosed());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getWindow",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "fillWindow",
+ args = {int.class, android.database.CursorWindow.class}
+ )
+ })
+ public void testGetWindow() {
+ assertNull(mDatabaseCursor.getWindow());
+ CursorWindow window = new CursorWindow(false);
+ assertEquals(0, window.getNumRows());
+ // fill window from position 0
+ mDatabaseCursor.fillWindow(0, window);
+
+ assertNotNull(mDatabaseCursor.getWindow());
+ assertEquals(mDatabaseCursor.getCount(), window.getNumRows());
+
+ while (mDatabaseCursor.moveToNext()) {
+ assertEquals(mDatabaseCursor.getInt(POSITION1),
+ window.getInt(mDatabaseCursor.getPosition(), POSITION1));
+ }
+ window.clear();
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test getWantsAllOnMoveCalls(), it always returns false.",
+ method = "getWantsAllOnMoveCalls",
+ args = {}
+ )
+ public void testGetWantsAllOnMoveCalls() {
+ assertFalse(mDatabaseCursor.getWantsAllOnMoveCalls());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isFieldUpdated",
+ args = {int.class}
+ )
+ @ToBeFixed(bug = "1569265", explanation = "All other updating-related methods are 'hide' and "
+ + "'deprecated.")
+ public void testIsFieldUpdated() {
+ mTestAbstractCursor.moveToFirst();
+ assertFalse(mTestAbstractCursor.isFieldUpdated(0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getUpdatedField",
+ args = {int.class}
+ )
+ @ToBeFixed(bug = "1569265", explanation = "All other updating-related methods are 'hide' and "
+ + "'deprecated.")
+ public void testGetUpdatedField() {
+ mTestAbstractCursor.moveToFirst();
+ try {
+ assertEquals("hello", mTestAbstractCursor.getUpdatedField(0));
+ fail("getUpdatedField should throws a NullPointerException here.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getExtras",
+ args = {}
+ )
+ public void testGetExtras() {
+ assertSame(Bundle.EMPTY, mDatabaseCursor.getExtras());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getCount",
+ args = {}
+ )
+ public void testGetCount() {
+ assertEquals(DATA_COUNT, mDatabaseCursor.getCount());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnNames",
+ args = {}
+ )
+ public void testGetColumnNames() {
+ String[] names = mDatabaseCursor.getColumnNames();
+ assertEquals(COLUMN_NAMES1.length, names.length);
+
+ for (int i = 0; i < COLUMN_NAMES1.length; i++) {
+ assertEquals(COLUMN_NAMES1[i], names[i]);
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnName",
+ args = {int.class}
+ )
+ public void testGetColumnName() {
+ assertEquals(COLUMN_NAMES1[0], mDatabaseCursor.getColumnName(0));
+ assertEquals(COLUMN_NAMES1[1], mDatabaseCursor.getColumnName(1));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnIndexOrThrow",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnIndex",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testGetColumnIndexOrThrow() {
+ final String COLUMN_FAKE = "fake_name";
+ assertEquals(POSITION0, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION0]));
+ assertEquals(POSITION1, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION1]));
+ assertEquals(POSITION0, mDatabaseCursor.getColumnIndexOrThrow(COLUMN_NAMES1[POSITION0]));
+ assertEquals(POSITION1, mDatabaseCursor.getColumnIndexOrThrow(COLUMN_NAMES1[POSITION1]));
+
+ assertEquals(0, mDatabaseCursor.getColumnIndexOrThrow(COLUMN_FAKE));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnIndex.",
+ args = {java.lang.String.class}
+ )
+ public void testGetColumnIndex() {
+ assertEquals(POSITION0, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION0]));
+ assertEquals(POSITION1, mDatabaseCursor.getColumnIndex(COLUMN_NAMES1[POSITION1]));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnCount",
+ args = {}
+ )
+ public void testGetColumnCount() {
+ assertEquals(COLUMN_NAMES1.length, mDatabaseCursor.getColumnCount());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "deactivateInternal",
+ args = {}
+ )
+ public void testDeactivateInternal() {
+ MockDataSetObserver mock = new MockDataSetObserver();
+ mDatabaseCursor.registerDataSetObserver(mock);
+ assertFalse(mock.hadCalledOnInvalid());
+ mDatabaseCursor.deactivateInternal();
+ assertTrue(mock.hadCalledOnInvalid());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "deactivate",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "registerDataSetObserver",
+ args = {android.database.DataSetObserver.class}
+ )
+ })
+ public void testDeactivate() {
+ MockDataSetObserver mock = new MockDataSetObserver();
+ mDatabaseCursor.registerDataSetObserver(mock);
+ assertFalse(mock.hadCalledOnInvalid());
+ mDatabaseCursor.deactivate();
+ assertTrue(mock.hadCalledOnInvalid());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "copyStringToBuffer",
+ args = {int.class, android.database.CharArrayBuffer.class}
+ )
+ public void testCopyStringToBuffer() {
+ CharArrayBuffer ca = new CharArrayBuffer(1000);
+ mTestAbstractCursor.moveToFirst();
+ mTestAbstractCursor.copyStringToBuffer(0, ca);
+ CursorWindow window = new CursorWindow(false);
+ mTestAbstractCursor.fillWindow(0, window);
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(window.getString(0, 0));
+ String str = ((TestAbstractCursor)mTestAbstractCursor).getString(0);
+ assertEquals(str.length(), ca.sizeCopied);
+ assertEquals(sb.toString(), new String(ca.data, 0, ca.sizeCopied));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "checkPosition",
+ args = {}
+ )
+ public void testCheckPosition() {
+ // Test with position = -1.
+ try {
+ mTestAbstractCursor.checkPosition();
+ fail("copyStringToBuffer() should throws CursorIndexOutOfBoundsException here.");
+ } catch (CursorIndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // Test with position = count.
+ assertTrue(mTestAbstractCursor.moveToPosition(mTestAbstractCursor.getCount() - 1));
+ mTestAbstractCursor.checkPosition();
+
+ try {
+ assertFalse(mTestAbstractCursor.moveToPosition(mTestAbstractCursor.getCount()));
+ assertEquals(mTestAbstractCursor.getCount(), mTestAbstractCursor.getPosition());
+ mTestAbstractCursor.checkPosition();
+ fail("copyStringToBuffer() should throws CursorIndexOutOfBoundsException here.");
+ } catch (CursorIndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ArrayList<ArrayList> createTestList(int rows, int cols) {
+ ArrayList<ArrayList> list = new ArrayList<ArrayList>();
+ Random ran = new Random();
+
+ for (int i = 0; i < rows; i++) {
+ ArrayList<Integer> col = new ArrayList<Integer>();
+ list.add(col);
+
+ for (int j = 0; j < cols; j++) {
+ // generate random number
+ Integer r = ran.nextInt();
+ col.add(r);
+ }
+ }
+
+ return list;
+ }
+
+ private void setupDatabase() {
+ mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db");
+ if (mDatabaseFile.exists()) {
+ mDatabaseFile.delete();
+ }
+ mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+ assertNotNull(mDatabaseFile);
+ mDatabase.execSQL("CREATE TABLE test1 (_id INTEGER PRIMARY KEY, number TEXT);");
+ generateData();
+ mDatabaseCursor = (AbstractCursor) mDatabase.query("test1", null, null, null, null, null,
+ null);
+ }
+
+ private void generateData() {
+ for ( int i = 0; i < DATA_COUNT; i++) {
+ mDatabase.execSQL("INSERT INTO test1 (number) VALUES ('" + i + "');");
+ }
+ }
+
+ private class TestAbstractCursor extends AbstractCursor {
+ private boolean mOnMoveReturnValue;
+ private int mOldPosition;
+ private int mNewPosition;
+ private String[] mColumnNames;
+ private ArrayList<Object>[] mRows;
+ private boolean mHadCalledOnChange = false;
+
+ public TestAbstractCursor() {
+ super();
+ }
+ @SuppressWarnings("unchecked")
+ public TestAbstractCursor(String[] columnNames, ArrayList<ArrayList> rows) {
+ int colCount = columnNames.length;
+ boolean foundID = false;
+ mRowIdColumnIndex = 0;
+
+ // Add an _id column if not in columnNames
+ for (int i = 0; i < colCount; ++i) {
+ if (columnNames[i].compareToIgnoreCase("_id") == 0) {
+ mColumnNames = columnNames;
+ foundID = true;
+ break;
+ }
+ }
+
+ if (!foundID) {
+ mColumnNames = new String[colCount + 1];
+ System.arraycopy(columnNames, 0, mColumnNames, 0, columnNames.length);
+ mColumnNames[colCount] = "_id";
+ }
+
+ int rowCount = rows.size();
+ mRows = new ArrayList[rowCount];
+
+ for (int i = 0; i < rowCount; ++i) {
+ mRows[i] = rows.get(i);
+
+ if (!foundID) {
+ mRows[i].add(Long.valueOf(i));
+ }
+ }
+ }
+
+ public boolean getOnMoveRet() {
+ return mOnMoveReturnValue;
+ }
+
+ public void resetOnMoveRet() {
+ mOnMoveReturnValue = false;
+ }
+
+ public int getOldPos() {
+ return mOldPosition;
+ }
+
+ public int getNewPos() {
+ return mNewPosition;
+ }
+
+ @Override
+ public boolean onMove(int oldPosition, int newPosition) {
+ mOnMoveReturnValue = super.onMove(oldPosition, newPosition);
+ mOldPosition = oldPosition;
+ mNewPosition = newPosition;
+ return mOnMoveReturnValue;
+ }
+
+ @Override
+ public int getCount() {
+ return mRows.length;
+ }
+
+ @Override
+ public boolean deleteRow() {
+ return false;
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return mColumnNames;
+ }
+
+ @Override
+ public String getString(int columnIndex) {
+ Object cell = mRows[mPos].get(columnIndex);
+ return (cell == null) ? null : cell.toString();
+ }
+
+ @Override
+ public short getShort(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.shortValue();
+ }
+
+ @Override
+ public int getInt(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.intValue();
+ }
+
+ @Override
+ public long getLong(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.longValue();
+ }
+
+ @Override
+ public float getFloat(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.floatValue();
+ }
+
+ @Override
+ public double getDouble(int columnIndex) {
+ Number num = (Number) mRows[mPos].get(columnIndex);
+ return num.doubleValue();
+ }
+
+ @Override
+ public boolean isNull(int column) {
+ return false;
+ }
+
+ public boolean hadCalledOnChange() {
+ return mHadCalledOnChange;
+ }
+
+ // the following are protected methods
+ protected void checkPosition() {
+ super.checkPosition();
+ }
+
+ protected Object getUpdatedField(int columnIndex) {
+ return super.getUpdatedField(columnIndex);
+ }
+
+ protected boolean isFieldUpdated(int columnIndex) {
+ return super.isFieldUpdated(columnIndex);
+ }
+
+ protected void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ mHadCalledOnChange = true;
+ }
+ }
+
+ private class MockContentObserver extends ContentObserver {
+ public boolean mHadCalledOnChange;
+
+ public MockContentObserver() {
+ super(null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ mHadCalledOnChange = true;
+ synchronized(mLockObj) {
+ mLockObj.notify();
+ }
+ }
+
+ @Override
+ public boolean deliverSelfNotifications() {
+ return true;
+ }
+
+ public boolean hadCalledOnChange() {
+ return mHadCalledOnChange;
+ }
+ }
+
+ private class MockDataSetObserver extends DataSetObserver {
+ private boolean mHadCalledOnChanged;
+ private boolean mHadCalledOnInvalid;
+
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ mHadCalledOnChanged = true;
+ }
+
+ @Override
+ public void onInvalidated() {
+ super.onInvalidated();
+ mHadCalledOnInvalid = true;
+ }
+
+ public boolean hadCalledOnChanged() {
+ return mHadCalledOnChanged;
+ }
+
+ public boolean hadCalledOnInvalid() {
+ return mHadCalledOnInvalid;
+ }
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/AbstractWindowedCursorTest.java b/tests/tests/database/src/android/database/cts/AbstractWindowedCursorTest.java
new file mode 100644
index 0000000..bcce519
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/AbstractWindowedCursorTest.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import java.util.Arrays;
+
+import android.database.AbstractWindowedCursor;
+import android.database.CharArrayBuffer;
+import android.database.CursorIndexOutOfBoundsException;
+import android.database.CursorWindow;
+import android.database.StaleDataException;
+import android.test.InstrumentationTestCase;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+
+@TestTargetClass(AbstractWindowedCursor.class)
+public class AbstractWindowedCursorTest extends InstrumentationTestCase {
+ private static final String TEST_STRING = "TESTSTRING";
+ private static final int COLUMN_INDEX0 = 0;
+ private static final int COLUMN_INDEX1 = 1;
+ private static final int ROW_INDEX0 = 0;
+ private static final int TEST_COLUMN_COUNT = 7;
+ private MockAbstractWindowedCursor mCursor;
+ private CursorWindow mWindow;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mCursor = new MockAbstractWindowedCursor();
+ mWindow = new CursorWindow(false);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isNull",
+ args = {int.class}
+ )
+ public void testIsNull() {
+ mCursor.setWindow(mWindow);
+
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ mCursor.moveToFirst();
+ assertTrue(mCursor.isNull(COLUMN_INDEX0));
+ assertTrue(mWindow.allocRow());
+
+ String str = "abcdefg";
+ assertTrue(mWindow.putString(str, ROW_INDEX0, COLUMN_INDEX0));
+ assertFalse(mCursor.isNull(COLUMN_INDEX0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isBlob",
+ args = {int.class}
+ )
+ public void testIsBlob() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ mCursor.moveToFirst();
+ assertFalse(mCursor.isBlob(COLUMN_INDEX0));
+
+ String str = "abcdefg";
+ assertTrue(mWindow.putString(str, ROW_INDEX0, COLUMN_INDEX0));
+ assertTrue(mWindow.putBlob(new byte[10], ROW_INDEX0, COLUMN_INDEX1));
+ assertTrue(mCursor.isBlob(COLUMN_INDEX1));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "hasWindow",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setWindow",
+ args = {android.database.CursorWindow.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getWindow",
+ args = {}
+ )
+ })
+ public void testHasWindow() {
+ assertFalse(mCursor.hasWindow());
+ assertNull(mCursor.getWindow());
+
+ mCursor.setWindow(mWindow);
+ assertTrue(mCursor.hasWindow());
+ assertSame(mWindow, mCursor.getWindow());
+
+ mCursor.setWindow(null);
+ assertFalse(mCursor.hasWindow());
+ assertNull(mCursor.getWindow());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getString",
+ args = {int.class}
+ )
+ public void testGetString() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ mCursor.moveToFirst();
+ String str = "abcdefg";
+ assertTrue(mWindow.putString(str, ROW_INDEX0, COLUMN_INDEX0));
+ assertEquals(str, mCursor.getString(COLUMN_INDEX0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getShort",
+ args = {int.class}
+ )
+ public void testGetShort() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ mCursor.moveToFirst();
+ short shortNumber = 10;
+ assertTrue(mWindow.putLong((long) shortNumber, ROW_INDEX0, COLUMN_INDEX0));
+ assertEquals(shortNumber, mCursor.getShort(COLUMN_INDEX0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getLong",
+ args = {int.class}
+ )
+ public void testGetLong() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ mCursor.moveToFirst();
+ long longNumber = 10;
+ assertTrue(mWindow.putLong(longNumber, ROW_INDEX0, COLUMN_INDEX0));
+ assertEquals(longNumber, mCursor.getLong(COLUMN_INDEX0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getInt",
+ args = {int.class}
+ )
+ public void testGetInt() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ mCursor.moveToFirst();
+ int intNumber = 10;
+ assertTrue(mWindow.putLong((long) intNumber, ROW_INDEX0, COLUMN_INDEX0));
+ assertEquals(intNumber, mCursor.getInt(COLUMN_INDEX0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getFloat",
+ args = {int.class}
+ )
+ public void testGetFloat() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ mCursor.moveToFirst();
+ float f1oatNumber = 1.26f;
+ assertTrue(mWindow.putDouble((double) f1oatNumber, ROW_INDEX0, COLUMN_INDEX0));
+ assertEquals(f1oatNumber, mCursor.getFloat(COLUMN_INDEX0));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getDouble",
+ args = {int.class}
+ )
+ public void testGetDouble() {
+ mCursor.setWindow(mWindow);
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+
+ double db1 = 1.26;
+ assertTrue(mWindow.putDouble(db1, ROW_INDEX0, COLUMN_INDEX0));
+
+ double db2 = mWindow.getDouble(ROW_INDEX0, COLUMN_INDEX0);
+ assertEquals(db1, db2);
+
+ mCursor.moveToFirst();
+ double cd = mCursor.getDouble(COLUMN_INDEX0);
+ assertEquals(db1, cd);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getBlob",
+ args = {int.class}
+ )
+ public void testGetBlob() {
+ byte TEST_VALUE = 3;
+ byte BLOB_SIZE = 100;
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+ assertTrue(mWindow.putString("", ROW_INDEX0, COLUMN_INDEX0));
+
+ byte[] blob = new byte[BLOB_SIZE];
+ Arrays.fill(blob, TEST_VALUE);
+ assertTrue(mWindow.putBlob(blob, ROW_INDEX0, COLUMN_INDEX1));
+
+ mCursor.setWindow(mWindow);
+ mCursor.moveToFirst();
+
+ byte[] targetBuffer = mCursor.getBlob(COLUMN_INDEX1);
+ assertEquals(BLOB_SIZE, targetBuffer.length);
+ assertTrue(Arrays.equals(blob, targetBuffer));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "copyStringToBuffer",
+ args = {int.class, android.database.CharArrayBuffer.class}
+ )
+ public void testCopyStringToBuffer() {
+ assertTrue(mWindow.setNumColumns(TEST_COLUMN_COUNT));
+ assertTrue(mWindow.allocRow());
+ assertTrue(mWindow.putString(TEST_STRING, ROW_INDEX0, COLUMN_INDEX0));
+ assertTrue(mWindow.putString("", ROW_INDEX0, COLUMN_INDEX1));
+
+ mCursor.setWindow(mWindow);
+ mCursor.moveToFirst();
+
+ CharArrayBuffer charArrayBuffer = new CharArrayBuffer(TEST_STRING.length());
+
+ mCursor.copyStringToBuffer(COLUMN_INDEX0, charArrayBuffer);
+ assertEquals(TEST_STRING.length(), charArrayBuffer.sizeCopied);
+ assertTrue(Arrays.equals(TEST_STRING.toCharArray(), charArrayBuffer.data));
+
+ Arrays.fill(charArrayBuffer.data, '\0');
+ mCursor.copyStringToBuffer(COLUMN_INDEX1, charArrayBuffer);
+ assertEquals(0, charArrayBuffer.sizeCopied);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "checkPosition",
+ args = {}
+ )
+ public void testCheckPosition() {
+ try {
+ mCursor.checkPosition();
+ fail("testCheckPosition failed");
+ } catch (CursorIndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ assertTrue(mCursor.moveToPosition(mCursor.getCount() - 1));
+ mCursor.checkPosition();
+ fail("testCheckPosition failed");
+ } catch (StaleDataException e) {
+ // expected
+ }
+
+ assertTrue(mCursor.moveToPosition(mCursor.getCount() - 1));
+ mCursor.setWindow(mWindow);
+ mCursor.checkPosition();
+ }
+
+ private class MockAbstractWindowedCursor extends AbstractWindowedCursor {
+
+ public MockAbstractWindowedCursor() {
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return new String[] {
+ "col1", "col2", "col3"
+ };
+ }
+
+ @Override
+ public int getCount() {
+ return 1;
+ }
+
+ @Override
+ protected void checkPosition() {
+ super.checkPosition();
+ }
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/CursorJoinerTest.java b/tests/tests/database/src/android/database/cts/CursorJoinerTest.java
new file mode 100644
index 0000000..b76c23b
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/CursorJoinerTest.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.database.Cursor;
+import android.database.CursorJoiner;
+import android.database.CursorJoiner.Result;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+
+@TestTargetClass(android.database.CursorJoiner.class)
+public class CursorJoinerTest extends AndroidTestCase {
+
+ private static final int TEST_ITEM_COUNT = 10;
+ private static final int DEFAULT_TABLE1_VALUE_BEGINS = 1;
+ private static final int DEFAULT_TABLE2_VALUE_BEGINS = 11;
+ private static final int EQUAL_START = 18;
+ // Every table has 7 unique numbers, and 3 other numbers they all have.
+ private static final int UNIQUE_COUNT = 7;
+ private static final int MAX_VALUE = 20;
+ private static final int EQUAL_VALUE_COUNT = MAX_VALUE - EQUAL_START + 1;
+ private static final String TABLE_NAME_1 = "test1";
+ private static final String TABLE_NAME_2 = "test2";
+ private static final String TABLE1_COLUMNS = " number TEXT";
+ private static final String TABLE2_COLUMNS = " number TEXT, int_number INTEGER";
+
+ private SQLiteDatabase mDatabase;
+ private File mDatabaseFile;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setupDatabase();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDatabase.close();
+ mDatabaseFile.delete();
+ super.tearDown();
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "CursorJoiner",
+ args = {android.database.Cursor.class, java.lang.String[].class,
+ android.database.Cursor.class, java.lang.String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "iterator",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "it always throws UnsupportedOperationException.",
+ method = "remove",
+ args = {}
+ )
+ })
+ public void testCursorJoinerAndIterator() {
+ Cursor cursor1 = getCursor(TABLE_NAME_1, null, null);
+ Cursor cursor2 = getCursor(TABLE_NAME_2, null, null);
+ // Test with different length ColumenNAmes
+ try {
+ new CursorJoiner(cursor1, cursor1.getColumnNames(), cursor2, cursor2.getColumnNames());
+ fail("CursorJoiner's constructor should throws IllegalArgumentException here.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ closeCursor(cursor1);
+ closeCursor(cursor2);
+
+ String[] columnNames = new String[] { "number" };
+ cursor1 = getCursor(TABLE_NAME_1, null, columnNames);
+ cursor2 = getCursor(TABLE_NAME_2, null, columnNames);
+
+ CursorJoiner cursorJoiner = new CursorJoiner(cursor1, cursor1.getColumnNames(), cursor2,
+ cursor2.getColumnNames());
+
+ // Test remove()
+ try {
+ cursorJoiner.remove();
+ fail("remove() should throws UnsupportedOperationException here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ assertEquals(TEST_ITEM_COUNT, cursor1.getCount());
+ assertEquals(TEST_ITEM_COUNT, cursor2.getCount());
+
+ // Test iterator
+ for (CursorJoiner.Result joinResult : cursorJoiner) {
+ switch (joinResult) {
+ case LEFT:
+ // Add the values into table test1 which table test1 possess and table test2 don't.
+ assertTrue(cursor1.getString(0).compareTo(cursor2.getString(0)) < 0);
+ addValueIntoTable(TABLE_NAME_2, cursor1.getString(0));
+ break;
+ case RIGHT:
+ // Add the values into table test2 which table test2 possess and table test1 don't.
+ assertTrue(cursor1.getString(0).compareTo(cursor2.getString(0)) > 0);
+ addValueIntoTable(TABLE_NAME_1, cursor2.getString(0));
+ break;
+ case BOTH:
+ // Delete the values table test1 and test2 both possess.
+ assertEquals(cursor1.getString(0), cursor2.getString(0));
+ deleteValueFromTable(TABLE_NAME_1, cursor1.getString(0));
+ deleteValueFromTable(TABLE_NAME_2, cursor2.getString(0));
+ break;
+ }
+ }
+ cursor1.requery();
+ cursor2.requery();
+
+ // Finally, two tables's number columns have the same contents
+ assertEquals(UNIQUE_COUNT * 2, cursor1.getCount());
+ assertEquals(UNIQUE_COUNT * 2, cursor2.getCount());
+
+ // For every table, merged with the other one's unique numbers, and deleted the originally
+ // mutual same numbers(EQUAL_START~MAX_VALUE);
+ cursor1.moveToFirst();
+ cursor2.moveToFirst();
+ for (int i = 0; i < UNIQUE_COUNT; i++) {
+ assertEquals(getOrderNumberString(DEFAULT_TABLE1_VALUE_BEGINS + i, MAX_VALUE),
+ cursor1.getString(0));
+ assertEquals(cursor1.getString(0), cursor2.getString(0));
+ cursor1.moveToNext();
+ cursor2.moveToNext();
+ }
+ closeCursor(cursor2);
+ closeCursor(cursor1);
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Fisrt UNIQUE_COUNT 'next' operations, the joiner controls cursor1 to move;" +
+ " and the second UNIQUE_COUNT 'next' ops, the joiner controlscursor2" +
+ " to move, the last EQUAL_VALUE_COUNT 'next' ops, the joiner control" +
+ " bothcursor1 and cursor2 to move.",
+ method = "next",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "hasNext",
+ args = {}
+ )
+ })
+ public void testNext() {
+ String[] columnNames = new String[] { "number" };
+ Cursor cursor1 = getCursor(TABLE_NAME_1, null, columnNames);
+ Cursor cursor2 = getCursor(TABLE_NAME_2, null, columnNames);
+
+ // For cursor1 , values are '01'~'07' and 'EQUAL_START'~'MAX_VALUE'
+ assertEquals(TEST_ITEM_COUNT, cursor1.getCount());
+ // For cursor2 , values are '11'~'17' and 'EQUAL_START'~'MAX_VALUE'
+ assertEquals(TEST_ITEM_COUNT, cursor2.getCount());
+ CursorJoiner cursorJoiner = new CursorJoiner(cursor1, cursor1.getColumnNames(), cursor2,
+ cursor2.getColumnNames());
+ for (int i = 0; i < UNIQUE_COUNT; i++) {
+ // For cursor1, value 1~7 result value as LEFT to cursor2 value '11'
+ assertTrue(cursorJoiner.hasNext());
+ assertEquals(Result.LEFT, cursorJoiner.next());
+ assertEquals(getOrderNumberString(DEFAULT_TABLE1_VALUE_BEGINS + i, MAX_VALUE), cursor1
+ .getString(0));
+ assertEquals(getOrderNumberString(DEFAULT_TABLE2_VALUE_BEGINS, MAX_VALUE), cursor2
+ .getString(0));
+ }
+ for (int i = 0; i < UNIQUE_COUNT; i++) {
+ // For cursor2, value 11~17 result a value as LEFT to cursor1 value '18'
+ assertTrue(cursorJoiner.hasNext());
+ assertEquals(Result.RIGHT, cursorJoiner.next());
+ assertEquals(getOrderNumberString(EQUAL_START, MAX_VALUE), cursor1.getString(0));
+ assertEquals(getOrderNumberString(DEFAULT_TABLE2_VALUE_BEGINS + i, MAX_VALUE), cursor2
+ .getString(0));
+ }
+ for (int i = 0; i < EQUAL_VALUE_COUNT; i++) {
+ // For cursor1 and cursor2, value 18~20 result a value as BOTH
+ assertTrue(cursorJoiner.hasNext());
+ assertEquals(Result.BOTH, cursorJoiner.next());
+ assertEquals(getOrderNumberString(EQUAL_START + i, MAX_VALUE), cursor1.getString(0));
+ assertEquals(getOrderNumberString(EQUAL_START + i, MAX_VALUE), cursor2.getString(0));
+ }
+ closeCursor(cursor1);
+ closeCursor(cursor2);
+ }
+
+ /**
+ * This function accepts integer maxValue to determine max length of number.
+ * Return a converted decimal number string of input integer parameter 'value',
+ * according to the max length, '0' will be placeholder(s).
+ * For example: if max length is 2, 1 -> '01', 10 -> '10'.
+ * @param value
+ * @param maxValue
+ * @return
+ */
+ private String getOrderNumberString(int value, int maxValue) {
+ // Convert decimal number as string, '0' as placeholder
+ int maxLength = Integer.toString(maxValue).length();
+ int basicLength = Integer.toString(value).length();
+ String placeHolders = "";
+ for (int i = 0; i < (maxLength - basicLength); i++) {
+ placeHolders += "0";
+ }
+ return placeHolders + Integer.toString(value);
+ }
+
+ private void initializeTables() {
+ // Add 1 to 7 into Table1
+ addValuesIntoTable(TABLE_NAME_1, DEFAULT_TABLE1_VALUE_BEGINS,
+ DEFAULT_TABLE1_VALUE_BEGINS + UNIQUE_COUNT - 1);
+ // Add 18 to 20 into Table1
+ addValuesIntoTable(TABLE_NAME_1, DEFAULT_TABLE2_VALUE_BEGINS + UNIQUE_COUNT, MAX_VALUE);
+ // Add 11 to 17 into Table2
+ addValuesIntoTable(TABLE_NAME_2, DEFAULT_TABLE2_VALUE_BEGINS,
+ DEFAULT_TABLE2_VALUE_BEGINS + UNIQUE_COUNT - 1);
+ // Add 18 to 20 into Table2
+ addValuesIntoTable(TABLE_NAME_2, DEFAULT_TABLE2_VALUE_BEGINS + UNIQUE_COUNT, MAX_VALUE);
+ }
+
+ private void setupDatabase() {
+ mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db");
+ if (mDatabaseFile.exists()) {
+ mDatabaseFile.delete();
+ }
+ mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+ assertNotNull(mDatabaseFile);
+ createTable(TABLE_NAME_1, TABLE1_COLUMNS);
+ createTable(TABLE_NAME_2, TABLE2_COLUMNS);
+ initializeTables();
+ }
+
+ private void closeCursor(Cursor cursor) {
+ if (null != cursor) {
+ cursor.close();
+ cursor = null;
+ }
+ }
+
+ private void createTable(String tableName, String columnNames) {
+ String sql = "Create TABLE " + tableName + " (_id INTEGER PRIMARY KEY, " + columnNames
+ + " );";
+ mDatabase.execSQL(sql);
+ }
+
+ private void addValuesIntoTable(String tableName, int start, int end) {
+ for (int i = start; i <= end; i++) {
+ mDatabase.execSQL("INSERT INTO " + tableName + "(number) VALUES ('"
+ + getOrderNumberString(i, MAX_VALUE) + "');");
+ }
+ }
+
+ private void addValueIntoTable(String tableName, String value) {
+ mDatabase.execSQL("INSERT INTO " + tableName + "(number) VALUES ('" + value + "');");
+ }
+
+ private void deleteValueFromTable(String tableName, String value) {
+ mDatabase.execSQL("DELETE FROM " + tableName + " WHERE number = '" + value + "';");
+ }
+
+ private Cursor getCursor(String tableName, String selection, String[] columnNames) {
+ return mDatabase.query(tableName, columnNames, selection, null, null, null, "number");
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/CursorWindowTest.java b/tests/tests/database/src/android/database/cts/CursorWindowTest.java
new file mode 100644
index 0000000..eff2db8
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/CursorWindowTest.java
@@ -0,0 +1,696 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import com.android.internal.database.ArrayListCursor;
+import com.google.android.collect.Lists;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.database.AbstractCursor;
+import android.database.CharArrayBuffer;
+import android.database.CursorWindow;
+import android.database.sqlite.SQLiteException;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Random;
+
+@TestTargetClass(android.database.CursorWindow.class)
+public class CursorWindowTest extends AndroidTestCase {
+
+ private static final String TEST_STRING = "Test String";
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "clear",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "setStartPosition",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "putString",
+ args = {java.lang.String.class, int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "putNull",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "setNumColumns",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "freeLastRow",
+ args = {}
+ )
+ })
+ public void testWriteCursorToWindow() throws Exception {
+ // create cursor
+ String[] colNames = new String[]{"name", "number", "profit"};
+ int colsize = colNames.length;
+ ArrayList<ArrayList> list = createTestList(10, colsize);
+ AbstractCursor cursor = new ArrayListCursor(colNames, list);
+
+ // fill window
+ CursorWindow window = new CursorWindow(false);
+ cursor.fillWindow(0, window);
+
+ // read from cursor window
+ for (int i = 0; i < list.size(); i++) {
+ ArrayList col = list.get(i);
+ for (int j = 0; j < colsize; j++) {
+ String s = window.getString(i, j);
+ int r2 = (Integer) col.get(j);
+ int r1 = Integer.parseInt(s);
+ assertEquals(r2, r1);
+ }
+ }
+
+ // test cursor window handle startpos != 0
+ window.clear();
+ cursor.fillWindow(1, window);
+ // read from cursor from window
+ for (int i = 1; i < list.size(); i++) {
+ ArrayList col = list.get(i);
+ for (int j = 0; j < colsize; j++) {
+ String s = window.getString(i, j);
+ int r2 = (Integer) col.get(j);
+ int r1 = Integer.parseInt(s);
+ assertEquals(r2, r1);
+ }
+ }
+
+ // Clear the window and make sure it's empty
+ window.clear();
+ assertEquals(0, window.getNumRows());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "putNull",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getString",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getBlob",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getDouble",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getLong",
+ args = {int.class, int.class}
+ )
+ })
+ public void testNull() {
+ CursorWindow window = getOneByOneWindow();
+
+ // Put in a null value and read it back as various types
+ assertTrue(window.putNull(0, 0));
+ assertNull(window.getString(0, 0));
+ assertEquals(0, window.getLong(0, 0));
+ assertEquals(0.0, window.getDouble(0, 0));
+ assertNull(window.getBlob(0, 0));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "putString",
+ args = {java.lang.String.class, int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getString",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getLong",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "This is a test from unittest of CursorWindowTest.",
+ method = "getDouble",
+ args = {int.class, int.class}
+ )
+ })
+ public void testEmptyString() {
+ CursorWindow window = getOneByOneWindow();
+
+ // put size 0 string and read it back as various types
+ assertTrue(window.putString("", 0, 0));
+ assertEquals("", window.getString(0, 0));
+ assertEquals(0, window.getLong(0, 0));
+ assertEquals(0.0, window.getDouble(0, 0));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "CursorWindow",
+ args = {boolean.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getStartPosition",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "newFromParcel",
+ args = {android.os.Parcel.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "writeToParcel",
+ args = {android.os.Parcel.class, int.class}
+ )
+ })
+ @ToBeFixed(bug = " ", explanation = "Can't create a remote binder for newFromParcel here.")
+ public void testConstructors() {
+ int TEST_NUMBER = 5;
+ CursorWindow cursorWindow;
+
+ // Test constructor with 'true' input, and getStartPosition should return 0
+ cursorWindow = new CursorWindow(true);
+ assertEquals(0, cursorWindow.getStartPosition());
+
+ // Test constructor with 'false' input
+ cursorWindow = new CursorWindow(false);
+ assertEquals(0, cursorWindow.getStartPosition());
+
+ // Test newFromParcel
+ Parcel parcel = Parcel.obtain();
+ try {
+ cursorWindow = CursorWindow.newFromParcel(parcel);
+ fail("Can't accept a local binder.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ cursorWindow = new CursorWindow(true);
+ cursorWindow.setStartPosition(TEST_NUMBER);
+ cursorWindow.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ assertNotNull(parcel.readStrongBinder());
+ assertEquals(TEST_NUMBER, parcel.readInt());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setNumColumns",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getNumRows",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "allocRow",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "freeLastRow",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "close",
+ args = {}
+ )
+ })
+ public void testDataStructureOperations() {
+ CursorWindow cursorWindow = new CursorWindow(true);
+
+ // Test with normal values
+ assertTrue(cursorWindow.setNumColumns(0));
+ // If the column has been set to zero, can't put String.
+ assertFalse(cursorWindow.putString(TEST_STRING, 0, 0));
+
+ // Test allocRow().
+ assertTrue(cursorWindow.allocRow());
+ assertEquals(1, cursorWindow.getNumRows());
+ assertTrue(cursorWindow.allocRow());
+ assertEquals(2, cursorWindow.getNumRows());
+ // Though allocate a row, but the column number is still 0, so can't putString.
+ assertFalse(cursorWindow.putString(TEST_STRING, 0, 0));
+
+ // Test freeLstRow
+ cursorWindow.freeLastRow();
+ assertEquals(1, cursorWindow.getNumRows());
+ cursorWindow.freeLastRow();
+ assertEquals(0, cursorWindow.getNumRows());
+
+ cursorWindow = new CursorWindow(true);
+ assertTrue(cursorWindow.setNumColumns(6));
+ assertTrue(cursorWindow.allocRow());
+ // Column number set to negative number, so now can put values.
+ assertTrue(cursorWindow.putString(TEST_STRING, 0, 0));
+ assertEquals(TEST_STRING, cursorWindow.getString(0, 0));
+
+ // Test with negative value
+ assertFalse(cursorWindow.setNumColumns(-1));
+
+ // Test with reference limitation
+ cursorWindow.releaseReference();
+ try {
+ cursorWindow.setNumColumns(5);
+ fail("setNumColumns() should throws IllegalStateException here.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ // Test close(), close will also minus references, that will lead acquireReference()
+ // related operation failed.
+ cursorWindow.close();
+ try {
+ cursorWindow.acquireReference();
+ fail("setNumColumns() should throws IllegalStateException here.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "putString",
+ args = {java.lang.String.class, int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "putNull",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "putLong",
+ args = {long.class, int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "putDouble",
+ args = {double.class, int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "putBlob",
+ args = {byte[].class, int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getString",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getShort",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getLong",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getInt",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getFloat",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getDouble",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getBlob",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isNull",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isBlob",
+ args = {int.class, int.class}
+ )
+ })
+ public void testAccessDataValues() {
+ final long NUMBER_LONG_INTEGER = (long) 0xaabbccddffL;
+ final long NUMBER_INTEGER = (int) NUMBER_LONG_INTEGER;
+ final long NUMBER_SHORT = (short) NUMBER_INTEGER;
+ final float NUMBER_FLOAT_SCIENCE = 7.332952E11f;
+ final double NUMBER_DOUBLE_SCIENCE = 7.33295205887E11;
+ final String NUMBER_FLOAT_SCIENCE_STRING = "7.332952E11";
+ final String NUMBER_DOUBLE_SCIENCE_STRING = "7.33295205887E11";
+ final String NUMBER_FLOAT_SCIENCE_STRING2 = "7.33295e+11";
+
+ byte[] originalBlob = new byte[Byte.MAX_VALUE];
+ for (int i = 0; i < Byte.MAX_VALUE; i++) {
+ originalBlob[i] = (byte) i;
+ }
+
+ CursorWindow cursorWindow = new CursorWindow(true);
+ cursorWindow.setNumColumns(5);
+ cursorWindow.allocRow();
+
+ // Test putString, getString, getLong, getInt, isBlob
+ assertTrue(cursorWindow.putString(Long.toString(NUMBER_LONG_INTEGER), 0, 0));
+ assertEquals(Long.toString(NUMBER_LONG_INTEGER), cursorWindow.getString(0, 0));
+ assertEquals(NUMBER_LONG_INTEGER, cursorWindow.getLong(0, 0));
+ assertEquals(NUMBER_INTEGER, cursorWindow.getInt(0, 0));
+ assertEquals(NUMBER_SHORT, cursorWindow.getShort(0, 0));
+ // Converting of Float, there would be some little precision differences. So just compare
+ // first 6 digits.
+ assertEquals(NUMBER_FLOAT_SCIENCE_STRING.substring(0, 6), Float.toString(
+ cursorWindow.getFloat(0, 0)).substring(0, 6));
+ assertEquals(NUMBER_DOUBLE_SCIENCE_STRING, Double.toString(cursorWindow.getDouble(0, 0)));
+ assertFalse(cursorWindow.isNull(0, 0));
+ assertFalse(cursorWindow.isBlob(0, 0));
+
+ // Test null String
+ assertTrue(cursorWindow.putString("", 0, 0));
+ assertEquals("", cursorWindow.getString(0, 0));
+ assertEquals(0, cursorWindow.getLong(0, 0));
+ assertEquals(0, cursorWindow.getInt(0, 0));
+ assertEquals(0, cursorWindow.getShort(0, 0));
+ assertEquals(0.0, cursorWindow.getDouble(0, 0));
+ assertEquals(0.0f, cursorWindow.getFloat(0, 0), 0.00000001f);
+ assertFalse(cursorWindow.isNull(0, 0));
+ assertFalse(cursorWindow.isBlob(0, 0));
+
+ // Test putNull, getString, getLong, getDouble, getBlob, getInd, getShort, getFloat,
+ // isBlob.
+ assertTrue(cursorWindow.putNull(0, 1));
+ assertNull(cursorWindow.getString(0, 1));
+ assertEquals(0, cursorWindow.getLong(0, 1));
+ assertEquals(0, cursorWindow.getInt(0, 1));
+ assertEquals(0, cursorWindow.getShort(0, 1));
+ assertEquals(0.0, cursorWindow.getDouble(0, 1));
+ assertEquals(0.0f, cursorWindow.getFloat(0, 1), 0.00000001f);
+ assertNull(cursorWindow.getBlob(0, 1));
+ assertTrue(cursorWindow.isNull(0, 1));
+ // If the field is null, isBlob will return true.
+ assertTrue(cursorWindow.isBlob(0, 1));
+
+ // Test putLong, getLong, getInt, getString , getShort, getFloat, getDouble, isBlob.
+ assertTrue(cursorWindow.putLong(NUMBER_LONG_INTEGER, 0, 2));
+ assertEquals(NUMBER_LONG_INTEGER, cursorWindow.getLong(0, 2));
+ assertEquals(NUMBER_INTEGER, cursorWindow.getInt(0, 2));
+ assertEquals(Long.toString(NUMBER_LONG_INTEGER), cursorWindow.getString(0, 2));
+ assertEquals(NUMBER_SHORT, cursorWindow.getShort(0, 2));
+ assertEquals(NUMBER_FLOAT_SCIENCE, cursorWindow.getFloat(0, 2), 0.00000001f);
+ assertEquals(NUMBER_DOUBLE_SCIENCE, cursorWindow.getDouble(0, 2), 0.00000001);
+ try {
+ cursorWindow.getBlob(0, 2);
+ fail("Can't get Blob from a Integer value.");
+ } catch (SQLiteException e) {
+ // expected
+ }
+ assertFalse(cursorWindow.isNull(0, 2));
+ assertFalse(cursorWindow.isBlob(0, 2));
+
+ // Test putDouble
+ assertTrue(cursorWindow.putDouble(NUMBER_DOUBLE_SCIENCE, 0, 3));
+ assertEquals(NUMBER_LONG_INTEGER, cursorWindow.getLong(0, 3));
+ assertEquals(NUMBER_INTEGER, cursorWindow.getInt(0, 3));
+ // Converting from Double to String, there would be some little precision differences. So
+ // Just compare first 6 digits.
+ assertEquals(NUMBER_FLOAT_SCIENCE_STRING2.substring(0, 6), cursorWindow.getString(0, 3)
+ .substring(0, 6));
+ assertEquals(NUMBER_SHORT, cursorWindow.getShort(0, 3));
+ assertEquals(NUMBER_FLOAT_SCIENCE, cursorWindow.getFloat(0, 3), 0.00000001f);
+ assertEquals(NUMBER_DOUBLE_SCIENCE, cursorWindow.getDouble(0, 3), 0.00000001);
+ try {
+ cursorWindow.getBlob(0, 3);
+ fail("Can't get Blob from a Double value.");
+ } catch (SQLiteException e) {
+ // expected
+ }
+ assertFalse(cursorWindow.isNull(0, 3));
+ assertFalse(cursorWindow.isBlob(0, 3));
+
+ // Test putBlob
+ assertTrue(cursorWindow.putBlob(originalBlob, 0, 4));
+ byte[] targetBlob = cursorWindow.getBlob(0, 4);
+ assertTrue(Arrays.equals(originalBlob, targetBlob));
+ assertFalse(cursorWindow.isNull(0, 4));
+ // Test isBlob
+ assertTrue(cursorWindow.isBlob(0, 4));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "copyStringToBuffer",
+ args = {int.class, int.class, android.database.CharArrayBuffer.class}
+ )
+ public void testCopyStringToBuffer() {
+ int DEFAULT_ARRAY_LENGTH = 64;
+ String baseString = "0123456789";
+ String expectedString = "";
+ // Create a 60 characters string.
+ for (int i = 0; i < 6; i++) {
+ expectedString += baseString;
+ }
+ CharArrayBuffer charArrayBuffer = new CharArrayBuffer(null);
+ CursorWindow cursorWindow = new CursorWindow(true);
+ cursorWindow.setNumColumns(2);
+ cursorWindow.allocRow();
+
+ assertEquals(null, charArrayBuffer.data);
+ cursorWindow.putString(expectedString, 0, 0);
+ cursorWindow.copyStringToBuffer(0, 0, charArrayBuffer);
+ assertNotNull(charArrayBuffer.data);
+ // By default, if the field's string is shorter than 64, array will be allocated as 64.
+ assertEquals(DEFAULT_ARRAY_LENGTH, charArrayBuffer.data.length);
+ assertEquals(expectedString,
+ new String(charArrayBuffer.data, 0, charArrayBuffer.sizeCopied));
+
+ // Test in case of string is longer than 64,
+ expectedString += baseString;
+ charArrayBuffer = new CharArrayBuffer(null);
+ cursorWindow.putString(expectedString, 0, 1);
+ cursorWindow.copyStringToBuffer(0, 1, charArrayBuffer);
+ assertNotNull(charArrayBuffer.data);
+ // If the string is longer than 64, array will be allocated as needed(longer than 64).
+ assertEquals(expectedString,
+ new String(charArrayBuffer.data, 0, charArrayBuffer.sizeCopied));
+ assertEquals(70, expectedString.length());
+ assertEquals(expectedString.length(), charArrayBuffer.data.length);
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "setStartPosition",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getStartPosition",
+ args = {}
+ )
+ })
+ public void testAccessStartPosition() {
+ final int TEST_POSITION_1 = 0;
+ final int TEST_POSITION_2 = 3;
+
+ CursorWindow cursorWindow = new CursorWindow(true);
+ fillCursorTestContents(cursorWindow, 5);
+
+ // Test setStartPosition
+ assertEquals(TEST_POSITION_1, cursorWindow.getStartPosition());
+ assertEquals(3, cursorWindow.getInt(3, 0));
+ assertEquals(TEST_STRING + "3", cursorWindow.getString(3, 1));
+ assertEquals(4, cursorWindow.getInt(4, 0));
+ assertEquals(TEST_STRING + "4", cursorWindow.getString(4, 1));
+ cursorWindow.setStartPosition(TEST_POSITION_2);
+
+ assertEquals(TEST_POSITION_2, cursorWindow.getStartPosition());
+
+ assertEquals(0, cursorWindow.getInt(3, 0));
+ assertEquals(TEST_STRING + "0", cursorWindow.getString(3, 1));
+ assertEquals(1, cursorWindow.getInt(4, 0));
+ assertEquals(TEST_STRING + "1", cursorWindow.getString(4, 1));
+ try {
+ cursorWindow.getBlob(0, 0);
+ fail("Row number is smaller than startPosition, will cause a IllegalStateException.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "clear",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "onAllReferencesReleased",
+ args = {}
+ )
+ })
+ public void testClearAndOnAllReferencesReleased() {
+ MockCursorWindow cursorWindow = new MockCursorWindow(true);
+
+ assertEquals(0, cursorWindow.getNumRows());
+ fillCursorTestContents(cursorWindow, 10);
+ assertEquals(10, cursorWindow.getNumRows());
+ assertEquals(0, cursorWindow.getStartPosition());
+ cursorWindow.setStartPosition(5);
+ assertEquals(5, cursorWindow.getStartPosition());
+
+ // Test clear(). a complete calling process of cursorWindow has a perfect acquiring and
+ // releasing pair, so the references number will be equal at the begin and the end.
+ assertFalse(cursorWindow.hasReleasedAllReferences());
+ cursorWindow.clear();
+ assertEquals(0, cursorWindow.getNumRows());
+ assertEquals(0, cursorWindow.getStartPosition());
+ assertFalse(cursorWindow.hasReleasedAllReferences());
+
+ // Test onAllReferencesReleased.
+ // By default, cursorWindow's reference is 1, when it reachs 0, onAllReferencesReleased
+ // be invoked.
+ cursorWindow = new MockCursorWindow(true);
+ cursorWindow.releaseReference();
+ assertTrue(cursorWindow.hasReleasedAllReferences());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "describeContents",
+ args = {}
+ )
+ public void testDescribeContents() {
+ CursorWindow cursorWindow = new CursorWindow(true);
+ assertEquals(0, cursorWindow.describeContents());
+ }
+
+ private class MockCursorWindow extends CursorWindow {
+ private boolean mHasReleasedAllReferences = false;
+
+ public MockCursorWindow(boolean localWindow) {
+ super(localWindow);
+ }
+
+ @Override
+ protected void onAllReferencesReleased() {
+ super.onAllReferencesReleased();
+ mHasReleasedAllReferences = true;
+ }
+
+ public boolean hasReleasedAllReferences() {
+ return mHasReleasedAllReferences;
+ }
+
+ public void resetStatus() {
+ mHasReleasedAllReferences = false;
+ }
+ }
+
+ private void fillCursorTestContents(CursorWindow cursorWindow, int length) {
+ cursorWindow.clear();
+ cursorWindow.setStartPosition(0);
+ cursorWindow.setNumColumns(2);
+ for (int i = 0; i < length; i++) {
+ cursorWindow.allocRow();
+ cursorWindow.putLong(i, i, 0);
+ cursorWindow.putString(TEST_STRING + i, i, 1);
+ }
+ }
+
+ private static ArrayList<ArrayList> createTestList(int rows, int cols) {
+ ArrayList<ArrayList> list = Lists.newArrayList();
+ Random generator = new Random();
+
+ for (int i = 0; i < rows; i++) {
+ ArrayList<Integer> col = Lists.newArrayList();
+ list.add(col);
+ for (int j = 0; j < cols; j++) {
+ // generate random number
+ Integer r = generator.nextInt();
+ col.add(r);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * The method comes from unit_test CursorWindowTest.
+ */
+ private CursorWindow getOneByOneWindow() {
+ CursorWindow window = new CursorWindow(false);
+ assertTrue(window.setNumColumns(1));
+ assertTrue(window.allocRow());
+ return window;
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java b/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
new file mode 100644
index 0000000..ad89d5f
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.DatabaseUtils.InsertHelper;
+import android.database.sqlite.SQLiteAbortException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDoneException;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteStatement;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+
+@TestTargetClass(android.database.DatabaseUtils.class)
+public class DatabaseUtilsTest extends AndroidTestCase {
+ private SQLiteDatabase mDatabase;
+ private File mDatabaseFile;
+ private static final String[] TEST_PROJECTION = new String[] {
+ "_id", // 0
+ "name", // 1
+ "age", // 2
+ "address" // 3
+ };
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db");
+ if (mDatabaseFile.exists()) {
+ mDatabaseFile.delete();
+ }
+ mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+ assertNotNull(mDatabase);
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, " +
+ "name TEXT, age INTEGER, address TEXT);");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDatabase.close();
+ mDatabaseFile.delete();
+ super.tearDown();
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "appendEscapedSQLString",
+ args = {java.lang.StringBuilder.class, java.lang.String.class}
+ )
+ public void testAppendEscapedSQLString() {
+ String expected = "name='Mike'";
+ StringBuilder sb = new StringBuilder("name=");
+ DatabaseUtils.appendEscapedSQLString(sb, "Mike");
+ assertEquals(expected, sb.toString());
+
+ expected = "'name=''Mike'''";
+ sb = new StringBuilder();
+ DatabaseUtils.appendEscapedSQLString(sb, "name='Mike'");
+ assertEquals(expected, sb.toString());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "sqlEscapeString",
+ args = {java.lang.String.class}
+ )
+ public void testSqlEscapeString() {
+ String expected = "'Jack'";
+ assertEquals(expected, DatabaseUtils.sqlEscapeString("Jack"));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "appendValueToSql",
+ args = {java.lang.StringBuilder.class, java.lang.Object.class}
+ )
+ public void testAppendValueToSql() {
+ String expected = "address='LA'";
+ StringBuilder sb = new StringBuilder("address=");
+ DatabaseUtils.appendValueToSql(sb, "LA");
+ assertEquals(expected, sb.toString());
+
+ expected = "address=NULL";
+ sb = new StringBuilder("address=");
+ DatabaseUtils.appendValueToSql(sb, null);
+ assertEquals(expected, sb.toString());
+
+ expected = "flag=1";
+ sb = new StringBuilder("flag=");
+ DatabaseUtils.appendValueToSql(sb, true);
+ assertEquals(expected, sb.toString());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "bindObjectToProgram",
+ args = {android.database.sqlite.SQLiteProgram.class, int.class, java.lang.Object.class}
+ )
+ public void testBindObjectToProgram() {
+ String name = "Mike";
+ int age = 21;
+ String address = "LA";
+
+ // at the beginning, there are no records in the database.
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+ assertEquals(0, cursor.getCount());
+
+ String sql = "INSERT INTO test (name, age, address) VALUES (?, ?, ?);";
+ SQLiteStatement statement = mDatabase.compileStatement(sql);
+ DatabaseUtils.bindObjectToProgram(statement, 1, name);
+ DatabaseUtils.bindObjectToProgram(statement, 2, age);
+ DatabaseUtils.bindObjectToProgram(statement, 3, address);
+ statement.execute();
+ statement.close();
+
+ cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertEquals(name, cursor.getString(1));
+ assertEquals(age, cursor.getInt(2));
+ assertEquals(address, cursor.getString(3));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "createDbFromSqlStatements",
+ args = {android.content.Context.class, java.lang.String.class, int.class,
+ java.lang.String.class}
+ )
+ public void testCreateDbFromSqlStatements() {
+ String dbName = "ExampleName";
+ String sqls = "CREATE TABLE test (_id INTEGER PRIMARY KEY, name TEXT);\n"
+ + "INSERT INTO test (name) VALUES ('Mike');\n";
+ DatabaseUtils.createDbFromSqlStatements(getContext(), dbName, 1, sqls);
+
+ SQLiteDatabase db = getContext().openOrCreateDatabase(dbName, 0, null);
+ final String[] PROJECTION = new String[] {
+ "_id", // 0
+ "name" // 1
+ };
+ Cursor cursor = db.query("test", PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertEquals("Mike", cursor.getString(1));
+ getContext().deleteDatabase(dbName);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorDoubleToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class, java.lang.String.class}
+ )
+ public void testCursorDoubleToContentValues() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+
+ ContentValues contentValues = new ContentValues();
+ String key = "key";
+ cursor.moveToFirst();
+ DatabaseUtils.cursorDoubleToContentValues(cursor, "age", contentValues, key);
+ assertEquals(20.0, contentValues.getAsDouble(key));
+
+ DatabaseUtils.cursorDoubleToContentValues(cursor, "Error Field Name", contentValues, key);
+ assertNull(contentValues.getAsDouble(key));
+
+ DatabaseUtils.cursorDoubleToContentValues(cursor, "name", contentValues, key);
+ assertEquals(0.0, contentValues.getAsDouble(key));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorDoubleToCursorValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class}
+ )
+ @ToBeFixed(bug = "1586458", explanation = "It's probably a typo.")
+ public void testCursorDoubleToCursorValues() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+
+ ContentValues contentValues = new ContentValues();
+ cursor.moveToFirst();
+ DatabaseUtils.cursorDoubleToCursorValues(cursor, "age", contentValues);
+ assertEquals(20.0, contentValues.getAsDouble("age"));
+
+ DatabaseUtils.cursorDoubleToCursorValues(cursor, "Error Field Name", contentValues);
+ assertNull(contentValues.getAsDouble("Error Field Name"));
+
+ DatabaseUtils.cursorDoubleToCursorValues(cursor, "name", contentValues);
+ assertEquals(0.0, contentValues.getAsDouble("name"));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorIntToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorIntToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class, java.lang.String.class}
+ )
+ })
+ public void testCursorIntToContentValues() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+
+ ContentValues contentValues = new ContentValues();
+ String key = "key";
+ cursor.moveToFirst();
+ DatabaseUtils.cursorIntToContentValues(cursor, "age", contentValues, key);
+ assertEquals(Integer.valueOf(20), contentValues.getAsInteger(key));
+
+ DatabaseUtils.cursorIntToContentValues(cursor, "Error Field Name", contentValues, key);
+ assertNull(contentValues.getAsInteger(key));
+
+ DatabaseUtils.cursorIntToContentValues(cursor, "name", contentValues, key);
+ assertEquals(Integer.valueOf(0), contentValues.getAsInteger(key));
+
+ contentValues = new ContentValues();
+ DatabaseUtils.cursorIntToContentValues(cursor, "age", contentValues);
+ assertEquals(Integer.valueOf(20), contentValues.getAsInteger("age"));
+
+ DatabaseUtils.cursorIntToContentValues(cursor, "Error Field Name", contentValues);
+ assertNull(contentValues.getAsInteger("Error Field Name"));
+
+ DatabaseUtils.cursorIntToContentValues(cursor, "name", contentValues);
+ assertEquals(Integer.valueOf(0), contentValues.getAsInteger("name"));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorLongToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorLongToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class, java.lang.String.class}
+ )
+ })
+ public void testcursorLongToContentValues() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+
+ ContentValues contentValues = new ContentValues();
+ String key = "key";
+ cursor.moveToNext();
+ DatabaseUtils.cursorLongToContentValues(cursor, "age", contentValues, key);
+ assertEquals(Long.valueOf(20), contentValues.getAsLong(key));
+
+ DatabaseUtils.cursorLongToContentValues(cursor, "Error Field Name", contentValues, key);
+ assertNull(contentValues.getAsLong(key));
+
+ DatabaseUtils.cursorLongToContentValues(cursor, "name", contentValues, key);
+ assertEquals(Long.valueOf(0), contentValues.getAsLong(key));
+
+ contentValues = new ContentValues();
+ DatabaseUtils.cursorLongToContentValues(cursor, "age", contentValues);
+ assertEquals(Long.valueOf(20), contentValues.getAsLong("age"));
+
+ DatabaseUtils.cursorLongToContentValues(cursor, "Error Field Name", contentValues);
+ assertNull(contentValues.getAsLong("Error Field Name"));
+
+ DatabaseUtils.cursorLongToContentValues(cursor, "name", contentValues);
+ assertEquals(Long.valueOf(0), contentValues.getAsLong("name"));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorRowToContentValues",
+ args = {android.database.Cursor.class, android.content.ContentValues.class}
+ )
+ public void testCursorRowToContentValues() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+
+ ContentValues contentValues = new ContentValues();
+ cursor.moveToNext();
+ DatabaseUtils.cursorRowToContentValues(cursor, contentValues);
+ assertEquals("Mike", (String) contentValues.get("name"));
+ assertEquals("20", (String) contentValues.get("age"));
+ assertEquals("LA", (String) contentValues.get("address"));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorStringToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorStringToContentValues",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.content.ContentValues.class, java.lang.String.class}
+ )
+ })
+ public void testCursorStringToContentValues() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+
+ ContentValues contentValues = new ContentValues();
+ String key = "key";
+ cursor.moveToNext();
+ DatabaseUtils.cursorStringToContentValues(cursor, "age", contentValues, key);
+ assertEquals("20", (String) contentValues.get(key));
+
+ try {
+ DatabaseUtils.cursorStringToContentValues(cursor, "Error Field Name",
+ contentValues, key);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ DatabaseUtils.cursorStringToContentValues(cursor, "name", contentValues, key);
+ assertEquals("Mike", contentValues.get(key));
+
+ contentValues = new ContentValues();
+ DatabaseUtils.cursorStringToContentValues(cursor, "age", contentValues);
+ assertEquals("20", contentValues.get("age"));
+
+ try {
+ DatabaseUtils.cursorStringToContentValues(cursor, "Error Field Name", contentValues);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ DatabaseUtils.cursorStringToContentValues(cursor, "name", contentValues);
+ assertEquals("Mike", contentValues.get("name"));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "cursorStringToInsertHelper",
+ args = {android.database.Cursor.class, java.lang.String.class,
+ android.database.DatabaseUtils.InsertHelper.class, int.class}
+ )
+ public void testCursorStringToInsertHelper() {
+ // create a new table.
+ mDatabase.execSQL("CREATE TABLE test_copy (_id INTEGER PRIMARY KEY, " +
+ "name TEXT, age INTEGER, address TEXT);");
+
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test_copy", TEST_PROJECTION, null, null, null, null, null);
+ assertEquals(0, cursor.getCount());
+
+ InsertHelper insertHelper = new InsertHelper(mDatabase, "test_copy");
+ int indexName = insertHelper.getColumnIndex("name");
+ int indexAge = insertHelper.getColumnIndex("age");
+ int indexAddress = insertHelper.getColumnIndex("address");
+
+ cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ cursor.moveToNext();
+ insertHelper.prepareForInsert();
+ DatabaseUtils.cursorStringToInsertHelper(cursor, "name", insertHelper, indexName);
+ DatabaseUtils.cursorStringToInsertHelper(cursor, "age", insertHelper, indexAge);
+ DatabaseUtils.cursorStringToInsertHelper(cursor, "address", insertHelper, indexAddress);
+ insertHelper.execute();
+
+ cursor = mDatabase.query("test_copy", TEST_PROJECTION, null, null, null, null, null);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("Mike", cursor.getString(1));
+ assertEquals(20, cursor.getInt(2));
+ assertEquals("LA", cursor.getString(3));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCurrentRow",
+ args = {android.database.Cursor.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCurrentRow",
+ args = {android.database.Cursor.class, java.io.PrintStream.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCurrentRow",
+ args = {android.database.Cursor.class, java.lang.StringBuilder.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCurrentRowToString",
+ args = {android.database.Cursor.class}
+ )
+ })
+ public void testDumpCurrentRow() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+ cursor.moveToNext();
+ String expected = "0 {\n _id=1\n name=Mike\n age=20\n address=LA\n}\n";
+
+ DatabaseUtils.dumpCurrentRow(cursor);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ PrintStream os = new PrintStream(bos);
+ DatabaseUtils.dumpCurrentRow(cursor, os);
+ os.flush();
+ os.close();
+ assertEquals(expected, bos.toString());
+
+ StringBuilder sb = new StringBuilder();
+ DatabaseUtils.dumpCurrentRow(cursor, sb);
+ assertEquals(expected, sb.toString());
+
+ assertEquals(expected, DatabaseUtils.dumpCurrentRowToString(cursor));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCursor",
+ args = {android.database.Cursor.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCursor",
+ args = {android.database.Cursor.class, java.io.PrintStream.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCursor",
+ args = {android.database.Cursor.class, java.lang.StringBuilder.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "dumpCursorToString",
+ args = {android.database.Cursor.class}
+ )
+ })
+ public void testDumpCursor() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Jack', '30', 'London');");
+ Cursor cursor = mDatabase.query("test", TEST_PROJECTION, null, null, null, null, null);
+ assertNotNull(cursor);
+ int pos = cursor.getPosition();
+ String expected = ">>>>> Dumping cursor " + cursor + "\n" +
+ "0 {\n" +
+ " _id=1\n" +
+ " name=Mike\n" +
+ " age=20\n" +
+ " address=LA\n" +
+ "}\n" +
+ "1 {\n" +
+ " _id=2\n" +
+ " name=Jack\n" +
+ " age=30\n" +
+ " address=London\n" +
+ "}\n" +
+ "<<<<<\n";
+
+ DatabaseUtils.dumpCursor(cursor);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ PrintStream os = new PrintStream(bos);
+ DatabaseUtils.dumpCursor(cursor, os);
+ os.flush();
+ os.close();
+ assertEquals(pos, cursor.getPosition()); // dumpCursor should not change status of cursor
+ assertEquals(expected, bos.toString());
+
+ StringBuilder sb = new StringBuilder();
+ DatabaseUtils.dumpCursor(cursor, sb);
+ assertEquals(pos, cursor.getPosition()); // dumpCursor should not change status of cursor
+ assertEquals(expected, sb.toString());
+
+ assertEquals(expected, DatabaseUtils.dumpCursorToString(cursor));
+ assertEquals(pos, cursor.getPosition()); // dumpCursor should not change status of cursor
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getCollationKey",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getHexCollationKey",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testCollationKey() {
+ String key1 = DatabaseUtils.getCollationKey("abc");
+ String key2 = DatabaseUtils.getCollationKey("ABC");
+ String key3 = DatabaseUtils.getCollationKey("bcd");
+
+ assertTrue(key1.equals(key2));
+ assertFalse(key1.equals(key3));
+
+ key1 = DatabaseUtils.getHexCollationKey("abc");
+ key2 = DatabaseUtils.getHexCollationKey("ABC");
+ key3 = DatabaseUtils.getHexCollationKey("bcd");
+
+ assertTrue(key1.equals(key2));
+ assertFalse(key1.equals(key3));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "longForQuery",
+ args = {android.database.sqlite.SQLiteDatabase.class, java.lang.String.class,
+ java.lang.String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "longForQuery",
+ args = {android.database.sqlite.SQLiteStatement.class, java.lang.String[].class}
+ )
+ })
+ public void testLongForQuery() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+
+ String query = "SELECT age FROM test";
+ assertEquals(20, DatabaseUtils.longForQuery(mDatabase, query, null));
+
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Jack', '35', 'London');");
+ query = "SELECT age FROM test WHERE name = ?";
+ String[] args = new String[] { "Jack" };
+ assertEquals(35, DatabaseUtils.longForQuery(mDatabase, query, args));
+ args = new String[] { "No such name" };
+ try {
+ DatabaseUtils.longForQuery(mDatabase, query, args);
+ fail("should throw SQLiteDoneException");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+
+ query = "SELECT count(*) FROM test;";
+ SQLiteStatement statement = mDatabase.compileStatement(query);
+ assertEquals(2, DatabaseUtils.longForQuery(statement, null));
+
+ query = "SELECT age FROM test WHERE address = ?;";
+ statement = mDatabase.compileStatement(query);
+ args = new String[] { "London" };
+ assertEquals(35, DatabaseUtils.longForQuery(statement, args));
+
+ args = new String[] { "No such address" };
+ try {
+ DatabaseUtils.longForQuery(statement, args);
+ fail("should throw SQLiteDoneException");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+ statement.close();
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "queryNumEntries",
+ args = {android.database.sqlite.SQLiteDatabase.class, java.lang.String.class}
+ )
+ public void testQueryNumEntries() {
+ assertEquals(0, DatabaseUtils.queryNumEntries(mDatabase, "test"));
+
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ assertEquals(1, DatabaseUtils.queryNumEntries(mDatabase, "test"));
+
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+ assertEquals(2, DatabaseUtils.queryNumEntries(mDatabase, "test"));
+
+ try {
+ DatabaseUtils.queryNumEntries(mDatabase, "NoSuchTable");
+ fail("should throw SQLiteException.");
+ } catch (SQLiteException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "readExceptionFromParcel",
+ args = {android.os.Parcel.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "writeExceptionToParcel",
+ args = {android.os.Parcel.class, java.lang.Exception.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "readExceptionWithFileNotFoundExceptionFromParcel",
+ args = {android.os.Parcel.class}
+ )
+ })
+ public void testExceptionFromParcel() {
+ Parcel parcel = Parcel.obtain();
+ DatabaseUtils.writeExceptionToParcel(parcel, new IllegalArgumentException());
+ parcel.setDataPosition(0);
+ try {
+ DatabaseUtils.readExceptionFromParcel(parcel);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ parcel = Parcel.obtain();
+ DatabaseUtils.writeExceptionToParcel(parcel, new SQLiteAbortException());
+ parcel.setDataPosition(0);
+ try {
+ DatabaseUtils.readExceptionFromParcel(parcel);
+ fail("should throw SQLiteAbortException.");
+ } catch (SQLiteAbortException e) {
+ // expected
+ }
+
+ parcel = Parcel.obtain();
+ DatabaseUtils.writeExceptionToParcel(parcel, new FileNotFoundException());
+ parcel.setDataPosition(0);
+ try {
+ DatabaseUtils.readExceptionFromParcel(parcel);
+ fail("should throw RuntimeException.");
+ } catch (RuntimeException e) {
+ // expected
+ }
+
+ parcel = Parcel.obtain();
+ DatabaseUtils.writeExceptionToParcel(parcel, new FileNotFoundException());
+ parcel.setDataPosition(0);
+ try {
+ DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(parcel);
+ fail("should throw FileNotFoundException.");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "stringForQuery",
+ args = {android.database.sqlite.SQLiteDatabase.class, java.lang.String.class,
+ java.lang.String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "stringForQuery",
+ args = {android.database.sqlite.SQLiteStatement.class, java.lang.String[].class}
+ )
+ })
+ public void testStringForQuery() {
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Mike', '20', 'LA');");
+
+ String query = "SELECT name FROM test";
+ assertEquals("Mike", DatabaseUtils.stringForQuery(mDatabase, query, null));
+
+ mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Jack', '35', 'London');");
+ query = "SELECT name FROM test WHERE address = ?";
+ String[] args = new String[] { "London" };
+ assertEquals("Jack", DatabaseUtils.stringForQuery(mDatabase, query, args));
+ args = new String[] { "No such address" };
+ try {
+ DatabaseUtils.stringForQuery(mDatabase, query, args);
+ fail("should throw SQLiteDoneException");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+
+ query = "SELECT name FROM test WHERE age = ?;";
+ SQLiteStatement statement = mDatabase.compileStatement(query);
+ args = new String[] { "20" };
+ assertEquals("Mike", DatabaseUtils.stringForQuery(statement, args));
+
+ args = new String[] { "1000" }; // NO people can be older than this.
+ try {
+ DatabaseUtils.stringForQuery(statement, args);
+ fail("should throw SQLiteDoneException");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+ statement.close();
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/MatrixCursorTest.java b/tests/tests/database/src/android/database/cts/MatrixCursorTest.java
new file mode 100644
index 0000000..ce5861e
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/MatrixCursorTest.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.database.CursorIndexOutOfBoundsException;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(MatrixCursor.class)
+public class MatrixCursorTest extends TestCase {
+ private static final String COLUMN0_NAME = "column0";
+
+ private static final String COLUMN1_NAME = "column1";
+
+ private static final String COLUMN2_NAME = "column2";
+
+ private static final int COLUMN0_INDEX = 0;
+
+ private static final int COLUMN1_INDEX = 1;
+
+ private static final int COLUMN2_INDEX = 2;
+
+ private MatrixCursor mMatrixCursor;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mMatrixCursor = new MatrixCursor(new String[] { COLUMN0_NAME, COLUMN1_NAME, COLUMN2_NAME });
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "MatrixCursor",
+ args = {java.lang.String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "MatrixCursor",
+ args = {java.lang.String[].class, int.class}
+ )
+ })
+ public void testMatrixCursor() {
+ new MatrixCursor(new String[0]);
+
+ new MatrixCursor(new String[] { COLUMN0_NAME }, 10);
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "newRow",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isNull",
+ args = {int.class}
+ )
+ })
+ public void testNewRow() {
+ assertEquals(0, mMatrixCursor.getCount());
+ RowBuilder builder = mMatrixCursor.newRow();
+ assertNotNull(builder);
+ assertEquals(1, mMatrixCursor.getCount());
+ mMatrixCursor.moveToFirst();
+ assertTrue(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertTrue(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertTrue(mMatrixCursor.isNull(COLUMN2_INDEX));
+
+ builder.add(Integer.MIN_VALUE);
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertEquals(Integer.MIN_VALUE, mMatrixCursor.getInt(COLUMN0_INDEX));
+ assertTrue(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertTrue(mMatrixCursor.isNull(COLUMN2_INDEX));
+
+ builder.add(0);
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertEquals(Integer.MIN_VALUE, mMatrixCursor.getInt(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertEquals(0, mMatrixCursor.getInt(COLUMN1_INDEX));
+ assertTrue(mMatrixCursor.isNull(COLUMN2_INDEX));
+
+ builder.add(Integer.MAX_VALUE);
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertEquals(Integer.MIN_VALUE, mMatrixCursor.getInt(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertEquals(0, mMatrixCursor.getInt(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+ assertEquals(Integer.MAX_VALUE, mMatrixCursor.getInt(COLUMN2_INDEX));
+
+ try {
+ builder.add(1);
+ fail("Should throw CursorIndexOutOfBoundsException when adding too many values");
+ } catch (CursorIndexOutOfBoundsException e) {
+ // expected
+ }
+
+ assertNotNull(mMatrixCursor.newRow());
+ assertEquals(2, mMatrixCursor.getCount());
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "addRow",
+ args = {java.lang.Object[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "addRow",
+ args = {java.lang.Iterable.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getCount",
+ args = {}
+ )
+ })
+ public void testAddRow() {
+ assertEquals(0, mMatrixCursor.getCount());
+
+ mMatrixCursor.addRow(new Long[] { Long.MIN_VALUE, 0l, Long.MAX_VALUE });
+ assertEquals(1, mMatrixCursor.getCount());
+ mMatrixCursor.moveToLast();
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertEquals(Long.MIN_VALUE, mMatrixCursor.getLong(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertEquals(0, mMatrixCursor.getLong(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+ assertEquals(Long.MAX_VALUE, mMatrixCursor.getLong(COLUMN2_INDEX));
+
+ try {
+ mMatrixCursor.addRow(new Long[2]);
+ fail("Should throw IllegalArgumentException if values does not have the same length "
+ + "as the columns");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ mMatrixCursor.addRow(new Long[4]);
+ fail("Should throw IllegalArgumentException if values does not have the same length "
+ + "as the columns");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ ArrayList<String> values = new ArrayList<String>();
+ values.add("value0");
+ values.add("value1");
+ try {
+ mMatrixCursor.addRow(values);
+ fail("Should throw IllegalArgumentException if values does not have the same length "
+ + "as the columns");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ values.add("value2");
+ mMatrixCursor.addRow(values);
+ assertEquals(2, mMatrixCursor.getCount());
+ mMatrixCursor.moveToLast();
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertEquals("value0", mMatrixCursor.getString(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertEquals("value1", mMatrixCursor.getString(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+ assertEquals("value2", mMatrixCursor.getString(COLUMN2_INDEX));
+
+ values.add("value3");
+ try {
+ mMatrixCursor.addRow(values);
+ fail("Should throw IllegalArgumentException if values does not have the same length "
+ + "as the columns");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnNames",
+ args = {}
+ )
+ public void testGetColumnNames() {
+ String[] names = mMatrixCursor.getColumnNames();
+ assertEquals(3, names.length);
+ assertEquals(COLUMN0_NAME, names[0]);
+ assertEquals(COLUMN1_NAME, names[1]);
+ assertEquals(COLUMN2_NAME, names[2]);
+
+ // the following methods from super class will call {@link MatrixCursor#getColumnNames()}
+ assertEquals(COLUMN0_INDEX, mMatrixCursor.getColumnIndex(COLUMN0_NAME));
+ assertEquals(COLUMN1_INDEX, mMatrixCursor.getColumnIndex(COLUMN1_NAME));
+ assertEquals(COLUMN2_INDEX, mMatrixCursor.getColumnIndex(COLUMN2_NAME));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getString",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getShort",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getInt",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getLong",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getFloat",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getDouble",
+ args = {int.class}
+ )
+ })
+ public void testGetters() {
+ mMatrixCursor.addRow(new Short[] { Short.MIN_VALUE, 0, Short.MAX_VALUE });
+ mMatrixCursor.moveToLast();
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+
+ // numbers can be converted to each other and strings
+ assertEquals(Short.MIN_VALUE, mMatrixCursor.getShort(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getShort(COLUMN1_INDEX));
+ assertEquals(Short.MAX_VALUE, mMatrixCursor.getShort(COLUMN2_INDEX));
+
+ assertEquals(Short.MIN_VALUE, mMatrixCursor.getInt(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getInt(COLUMN1_INDEX));
+ assertEquals(Short.MAX_VALUE, mMatrixCursor.getInt(COLUMN2_INDEX));
+
+ assertEquals(Short.MIN_VALUE, mMatrixCursor.getLong(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getLong(COLUMN1_INDEX));
+ assertEquals(Short.MAX_VALUE, mMatrixCursor.getLong(COLUMN2_INDEX));
+
+ assertEquals(-32768f, mMatrixCursor.getFloat(COLUMN0_INDEX), 0.0f);
+ assertEquals(0f, mMatrixCursor.getFloat(COLUMN1_INDEX), 0.0f);
+ assertEquals(32767f, mMatrixCursor.getFloat(COLUMN2_INDEX), 0.0f);
+
+ assertEquals(-32768d, mMatrixCursor.getDouble(COLUMN0_INDEX), 0.0d);
+ assertEquals(0d, mMatrixCursor.getDouble(COLUMN1_INDEX), 0.0d);
+ assertEquals(32767d, mMatrixCursor.getDouble(COLUMN2_INDEX), 0.0d);
+
+ assertEquals("-32768", mMatrixCursor.getString(COLUMN0_INDEX));
+ assertEquals("0", mMatrixCursor.getString(COLUMN1_INDEX));
+ assertEquals("32767", mMatrixCursor.getString(COLUMN2_INDEX));
+
+ mMatrixCursor.addRow(new Double[] { Double.MIN_VALUE, 0d, Double.MAX_VALUE });
+ mMatrixCursor.moveToLast();
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+
+ // numbers can be converted to each other but loose accuracy
+ assertEquals(0, mMatrixCursor.getShort(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getShort(COLUMN1_INDEX));
+ assertEquals(-1, mMatrixCursor.getShort(COLUMN2_INDEX));
+
+ assertEquals(0, mMatrixCursor.getInt(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getInt(COLUMN1_INDEX));
+ assertEquals(Integer.MAX_VALUE, mMatrixCursor.getInt(COLUMN2_INDEX));
+
+ assertEquals(0, mMatrixCursor.getLong(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getLong(COLUMN1_INDEX));
+ assertEquals(Long.MAX_VALUE, mMatrixCursor.getLong(COLUMN2_INDEX));
+
+ assertEquals(0.0f, mMatrixCursor.getFloat(COLUMN0_INDEX), 0.0f);
+ assertEquals(0f, mMatrixCursor.getFloat(COLUMN1_INDEX), 0.0f);
+ assertEquals(Float.POSITIVE_INFINITY, mMatrixCursor.getFloat(COLUMN2_INDEX), 0.0f);
+
+ assertEquals(Double.MIN_VALUE, mMatrixCursor.getDouble(COLUMN0_INDEX), 0.0d);
+ assertEquals(0d, mMatrixCursor.getDouble(COLUMN1_INDEX), 0.0d);
+ assertEquals(Double.MAX_VALUE, mMatrixCursor.getDouble(COLUMN2_INDEX), 0.0d);
+
+ assertEquals(Double.toString(Double.MIN_VALUE), mMatrixCursor.getString(COLUMN0_INDEX));
+ assertEquals(Double.toString(0d), mMatrixCursor.getString(COLUMN1_INDEX));
+ assertEquals(Double.toString(Double.MAX_VALUE), mMatrixCursor.getString(COLUMN2_INDEX));
+
+ mMatrixCursor.addRow(new String[] { "-1", "0", "1" });
+ mMatrixCursor.moveToLast();
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+ // strings can be converted to numbers
+ assertEquals(-1, mMatrixCursor.getShort(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getShort(COLUMN1_INDEX));
+ assertEquals(1, mMatrixCursor.getShort(COLUMN2_INDEX));
+
+ assertEquals(-1, mMatrixCursor.getInt(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getInt(COLUMN1_INDEX));
+ assertEquals(1, mMatrixCursor.getInt(COLUMN2_INDEX));
+
+ assertEquals(-1, mMatrixCursor.getLong(COLUMN0_INDEX));
+ assertEquals(0, mMatrixCursor.getLong(COLUMN1_INDEX));
+ assertEquals(1, mMatrixCursor.getLong(COLUMN2_INDEX));
+
+ assertEquals(-1f, mMatrixCursor.getFloat(COLUMN0_INDEX), 0.0f);
+ assertEquals(0f, mMatrixCursor.getFloat(COLUMN1_INDEX), 0.0f);
+ assertEquals(1f, mMatrixCursor.getFloat(COLUMN2_INDEX), 0.0f);
+
+ assertEquals(-1d, mMatrixCursor.getDouble(COLUMN0_INDEX), 0.0d);
+ assertEquals(0f, mMatrixCursor.getDouble(COLUMN1_INDEX), 0.0d);
+ assertEquals(1d, mMatrixCursor.getDouble(COLUMN2_INDEX), 0.0d);
+
+ assertEquals("-1", mMatrixCursor.getString(COLUMN0_INDEX));
+ assertEquals("0", mMatrixCursor.getString(COLUMN1_INDEX));
+ assertEquals("1", mMatrixCursor.getString(COLUMN2_INDEX));
+
+ mMatrixCursor.addRow(new String[] { "1.0E2", "0xff", "not number" });
+ mMatrixCursor.moveToLast();
+ assertFalse(mMatrixCursor.isNull(COLUMN0_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN1_INDEX));
+ assertFalse(mMatrixCursor.isNull(COLUMN2_INDEX));
+ assertEquals("1.0E2", mMatrixCursor.getString(COLUMN0_INDEX));
+ assertEquals("0xff", mMatrixCursor.getString(COLUMN1_INDEX));
+ assertEquals("not number", mMatrixCursor.getString(COLUMN2_INDEX));
+
+ assertEquals(100f, mMatrixCursor.getFloat(COLUMN0_INDEX), 0.0f);
+ // strings can not be converted to numbers
+ try {
+ mMatrixCursor.getShort(COLUMN1_INDEX);
+ fail("Should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ // expected
+ }
+
+ try {
+ mMatrixCursor.getShort(COLUMN2_INDEX);
+ fail("Should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/MatrixCursor_RowBuilderTest.java b/tests/tests/database/src/android/database/cts/MatrixCursor_RowBuilderTest.java
new file mode 100644
index 0000000..98ed135
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/MatrixCursor_RowBuilderTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.database.CursorIndexOutOfBoundsException;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(RowBuilder.class)
+public class MatrixCursor_RowBuilderTest extends TestCase {
+ private static final int COLUMN0_INDEX = 0;
+
+ private static final int COLUMN1_INDEX = 1;
+
+ private static final int COLUMN2_INDEX = 2;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "add",
+ args = {java.lang.Object.class}
+ )
+ public void testAdd() {
+ MatrixCursor cursor = new MatrixCursor(new String[] { "column0", "column1", "column2" });
+ assertEquals(0, cursor.getCount());
+ RowBuilder builder = cursor.newRow();
+ assertNotNull(builder);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertTrue(cursor.isNull(COLUMN0_INDEX));
+ assertTrue(cursor.isNull(COLUMN1_INDEX));
+ assertTrue(cursor.isNull(COLUMN2_INDEX));
+
+ builder.add(Integer.MIN_VALUE);
+ assertFalse(cursor.isNull(COLUMN0_INDEX));
+ assertEquals(Integer.MIN_VALUE, cursor.getInt(COLUMN0_INDEX));
+ assertTrue(cursor.isNull(COLUMN1_INDEX));
+ assertTrue(cursor.isNull(COLUMN2_INDEX));
+
+ builder.add(0);
+ assertFalse(cursor.isNull(COLUMN0_INDEX));
+ assertEquals(Integer.MIN_VALUE, cursor.getInt(COLUMN0_INDEX));
+ assertFalse(cursor.isNull(COLUMN1_INDEX));
+ assertEquals(0, cursor.getInt(COLUMN1_INDEX));
+ assertTrue(cursor.isNull(COLUMN2_INDEX));
+
+ builder.add(Integer.MAX_VALUE);
+ assertFalse(cursor.isNull(COLUMN0_INDEX));
+ assertEquals(Integer.MIN_VALUE, cursor.getInt(COLUMN0_INDEX));
+ assertFalse(cursor.isNull(COLUMN1_INDEX));
+ assertEquals(0, cursor.getInt(COLUMN1_INDEX));
+ assertFalse(cursor.isNull(COLUMN2_INDEX));
+ assertEquals(Integer.MAX_VALUE, cursor.getInt(COLUMN2_INDEX));
+
+ try {
+ builder.add(1);
+ fail("Should throw CursorIndexOutOfBoundsException when adding too many values");
+ } catch (CursorIndexOutOfBoundsException e) {
+ // expected
+ }
+
+ assertNotNull(cursor.newRow());
+ assertEquals(2, cursor.getCount());
+ }
+}
diff --git a/tests/tests/database/src/android/database/cts/MergeCursorTest.java b/tests/tests/database/src/android/database/cts/MergeCursorTest.java
new file mode 100644
index 0000000..25e6aec
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/MergeCursorTest.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 android.database.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MergeCursor;
+import android.database.StaleDataException;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.util.Arrays;
+
+@TestTargetClass(android.database.MergeCursor.class)
+public class MergeCursorTest extends AndroidTestCase {
+ private final int NUMBER_1_COLUMN_INDEX = 1;
+ private static final String TABLE1_NAME = "test1";
+ private static final String TABLE2_NAME = "test2";
+ private static final String TABLE3_NAME = "test3";
+ private static final String TABLE4_NAME = "test4";
+ private static final String TABLE5_NAME = "test5";
+ private static final String COLUMN_FOR_NULL_TEST = "Null Field";
+
+ private SQLiteDatabase mDatabase;
+ private File mDatabaseFile;
+
+ Cursor[] mCursors = null;
+ private static final String TABLE1_COLUMNS = " number_1 INTEGER";
+ private static final String TABLE2_COLUMNS = " number_1 INTEGER, number_2 INTEGER";
+ private static final String TABLE3_COLUMNS = " text_1 TEXT, number_3 INTEGER, number_4 REAL";
+ private static final String TABLE2_COLUMN_NAMES = "_id,number_1,number_2";
+ private static final String TABLE3_COLUMN_NAMES = "_id,text_1,number_3,number_4";
+ private static final String TEXT_COLUMN_NAME = "text_1";
+ private static final int TABLE2_COLUMN_COUNT = 3;
+ private static final int TABLE3_COLUMN_COUNT = 4;
+ private static final int DEFAULT_TABLE_VALUE_BEGINS = 1;
+ private static final int MAX_VALUE = 10;
+ private static final int HALF_VALUE = MAX_VALUE / 2;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setupDatabase();
+ mCursors = new Cursor[2];
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ for (int i = 0; i < mCursors.length; i++) {
+ if (null != mCursors[i]) {
+ mCursors[i].close();
+ }
+ }
+ mDatabase.close();
+ mDatabaseFile.delete();
+ super.tearDown();
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "MergeCursor",
+ args = {android.database.Cursor[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getCount",
+ args = {}
+ )
+ })
+ public void testConstructor() {
+ // If each item of mCursors are null, count will be zero.
+ MergeCursor mergeCursor = new MergeCursor(mCursors);
+ assertEquals(0, mergeCursor.getCount());
+
+ createCursors();
+
+ // if the items are not null, getCount() will return the sum of all cursors' count.
+ mergeCursor = new MergeCursor(mCursors);
+ assertEquals(mCursors[0].getCount() + mCursors[1].getCount(), mergeCursor.getCount());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "onMove",
+ args = {int.class, int.class}
+ )
+ public void testOnMove() {
+ createCursors();
+ MergeCursor mergeCursor = new MergeCursor(mCursors);
+ for (int i = 0; i < MAX_VALUE; i++) {
+ mergeCursor.moveToNext();
+ //From 1~5, mCursor should be in mCursors[0], larger than 5, it should be in
+ //mCursors[1].
+ assertEquals(i + 1, mergeCursor.getInt(NUMBER_1_COLUMN_INDEX));
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test method related to column infos during MergeCursor is switching" +
+ " between different single cursors",
+ method = "getColumnNames",
+ args = {}
+ )
+ public void testCursorSwiching() {
+ mDatabase.execSQL("CREATE TABLE " + TABLE5_NAME + " (_id INTEGER PRIMARY KEY,"
+ + TABLE3_COLUMNS + ");");
+ String sql = "INSERT INTO " + TABLE5_NAME + " (" + TEXT_COLUMN_NAME + ") VALUES ('TEXT')";
+ mDatabase.execSQL(sql);
+
+ Cursor[] cursors = new Cursor[2];
+ cursors[0] = mDatabase.query(TABLE5_NAME, null, null, null, null, null, null);
+ assertEquals(1, cursors[0].getCount());
+ createCursors();
+ cursors[1] = mCursors[1];
+ assertTrue(cursors[1].getCount() > 0);
+ MergeCursor mergeCursor = new MergeCursor(cursors);
+ // MergeCursor should points to cursors[0] after moveToFirst.
+ mergeCursor.moveToFirst();
+
+ String[] tableColumns = TABLE3_COLUMN_NAMES.split("[,]");
+ assertEquals(TABLE3_COLUMN_COUNT, mergeCursor.getColumnCount());
+ assertTrue(Arrays.equals(tableColumns, mergeCursor.getColumnNames()));
+
+ // MergeCursor should points to cursors[1] moveToNext.
+ mergeCursor.moveToNext();
+ tableColumns = TABLE2_COLUMN_NAMES.split("[,]");
+ assertEquals(TABLE2_COLUMN_COUNT, mergeCursor.getColumnCount());
+ assertTrue(Arrays.equals(tableColumns, mergeCursor.getColumnNames()));
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getBlob",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getDouble",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getFloat",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getInt",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getLong",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getShort",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getString",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "isNull",
+ args = {int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "onMove",
+ args = {int.class, int.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getColumnNames",
+ args = {}
+ )
+ })
+ public void testGetValues() {
+ byte NUMBER_BLOB_UNIT = 99;
+ String[] TEST_STRING = new String[] {"Test String1", "Test String2"};
+ String[] tableNames = new String[] {TABLE3_NAME, TABLE4_NAME};
+
+ final double NUMBER_DOUBLE = Double.MAX_VALUE;
+ final double NUMBER_FLOAT = (float) NUMBER_DOUBLE;
+ final long NUMBER_LONG_INTEGER = (long) 0xaabbccddffL;
+ final long NUMBER_INTEGER = (int) NUMBER_LONG_INTEGER;
+ final long NUMBER_SHORT = (short) NUMBER_INTEGER;
+
+ // create tables
+ byte[][] originalBlobs = new byte[2][];
+ for (int i = 0; i < 2; i++) {
+ // insert blob and other values
+ originalBlobs[i] = new byte[1000];
+ Arrays.fill(originalBlobs[i], (byte) (NUMBER_BLOB_UNIT - i));
+ buildDatabaseWithTestValues(TEST_STRING[i], NUMBER_DOUBLE - i, NUMBER_LONG_INTEGER - i,
+ originalBlobs[i], tableNames[i]);
+ // Get cursors.
+ mCursors[i] = mDatabase.query(tableNames[i], null, null, null, null, null, null);
+ }
+
+ MergeCursor mergeCursor = new MergeCursor(mCursors);
+ assertEquals(4, mergeCursor.getCount());
+ String[] testColumns = new String[] {"_id", "string_text", "double_number", "int_number",
+ "blob_data"};
+ // Test getColumnNames().
+ assertTrue(Arrays.equals(testColumns, mergeCursor.getColumnNames()));
+
+ int columnBlob = mCursors[0].getColumnIndexOrThrow("blob_data");
+ int columnString = mCursors[0].getColumnIndexOrThrow("string_text");
+ int columnDouble = mCursors[0].getColumnIndexOrThrow("double_number");
+ int columnInteger = mCursors[0].getColumnIndexOrThrow("int_number");
+
+ // Test values.
+ for (int i = 0; i < 2; i++) {
+ mergeCursor.moveToNext();
+ assertEquals(5, mergeCursor.getColumnCount());
+
+ // Test getting value methods.
+ byte[] targetBlob = mergeCursor.getBlob(columnBlob);
+ assertTrue(Arrays.equals(originalBlobs[i], targetBlob));
+
+ assertEquals(TEST_STRING[i], mergeCursor.getString(columnString));
+ assertEquals(NUMBER_DOUBLE - i, mergeCursor.getDouble(columnDouble), 0.000000000001);
+ assertEquals(NUMBER_FLOAT - i, mergeCursor.getFloat(columnDouble), 0.000000000001f);
+ assertEquals(NUMBER_LONG_INTEGER - i, mergeCursor.getLong(columnInteger));
+ assertEquals(NUMBER_INTEGER - i, mergeCursor.getInt(columnInteger));
+ assertEquals(NUMBER_SHORT - i, mergeCursor.getShort(columnInteger));
+
+ // Test isNull(int).
+ assertFalse(mergeCursor.isNull(columnBlob));
+ mergeCursor.moveToNext();
+ assertEquals(COLUMN_FOR_NULL_TEST, mergeCursor.getString(columnString));
+ assertTrue(mergeCursor.isNull(columnBlob));
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "registerContentObserver",
+ args = {android.database.ContentObserver.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "unregisterContentObserver",
+ args = {android.database.ContentObserver.class}
+ )
+ })
+ public void testContentObsererOperations() throws IllegalStateException {
+ createCursors();
+ MergeCursor mergeCursor = new MergeCursor(mCursors);
+ ContentObserver observer = new ContentObserver(null) {};
+
+ // Can't unregister a Observer before it has been registered.
+ try {
+ mergeCursor.unregisterContentObserver(observer);
+ fail("testUnregisterContentObserver failed");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ mergeCursor.registerContentObserver(observer);
+
+ // Can't register a same observer twice before unregister it.
+ try {
+ mergeCursor.registerContentObserver(observer);
+ fail("testRegisterContentObserver failed");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ mergeCursor.unregisterContentObserver(observer);
+ // one Observer can be registered again after it has been unregistered.
+ mergeCursor.registerContentObserver(observer);
+
+ mergeCursor.unregisterContentObserver(observer);
+
+ try {
+ mergeCursor.unregisterContentObserver(observer);
+ fail("testUnregisterContentObserver failed");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "deactivate",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "registerDataSetObserver",
+ args = {android.database.DataSetObserver.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "unregisterDataSetObserver",
+ args = {android.database.DataSetObserver.class}
+ )
+ })
+ public void testDeactivate() throws IllegalStateException {
+ createCursors();
+ MergeCursor mergeCursor = new MergeCursor(mCursors);
+ MockObserver observer = new MockObserver();
+
+ // one DataSetObserver can't unregistered before it had been registered.
+ try {
+ mergeCursor.unregisterDataSetObserver(observer);
+ fail("testUnregisterDataSetObserver failed");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ // Before registering, observer can't be notified.
+ assertFalse(observer.hasInvalidated());
+ mergeCursor.moveToLast();
+ mergeCursor.deactivate();
+ assertFalse(observer.hasInvalidated());
+
+ // Test with registering DataSetObserver
+ assertTrue(mergeCursor.requery());
+ mergeCursor.registerDataSetObserver(observer);
+ assertFalse(observer.hasInvalidated());
+ mergeCursor.moveToLast();
+ assertEquals(MAX_VALUE, mergeCursor.getInt(NUMBER_1_COLUMN_INDEX));
+ mergeCursor.deactivate();
+ // deactivate method can invoke invalidate() method, can be observed by DataSetObserver.
+ assertTrue(observer.hasInvalidated());
+ // After deactivating, the cursor can not provide values from database record.
+ try {
+ mergeCursor.getInt(NUMBER_1_COLUMN_INDEX);
+ fail("After deactivating, cursor cannot execute getting value operations.");
+ } catch (StaleDataException e) {
+ // expected
+ }
+
+ // Can't register a same observer twice before unregister it.
+ try {
+ mergeCursor.registerDataSetObserver(observer);
+ fail("testRegisterDataSetObserver failed");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ // After runegistering, observer can't be notified.
+ mergeCursor.unregisterDataSetObserver(observer);
+ observer.resetStatus();
+ assertFalse(observer.hasInvalidated());
+ mergeCursor.moveToLast();
+ mergeCursor.deactivate();
+ assertFalse(observer.hasInvalidated());
+
+ // one DataSetObserver can't be unregistered twice continuously.
+ try {
+ mergeCursor.unregisterDataSetObserver(observer);
+ fail("testUnregisterDataSetObserver failed");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "requery",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "getCount",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "close",
+ args = {}
+ )
+ })
+ public void testRequery() {
+ final String TEST_VALUE1 = Integer.toString(MAX_VALUE + 1);
+ final String TEST_VALUE2 = Integer.toString(MAX_VALUE + 2);
+ createCursors();
+ MergeCursor mergeCursor = new MergeCursor(mCursors);
+ int cursor1Count = mCursors[0].getCount();
+ int cursor2Count = mCursors[0].getCount();
+
+ mDatabase.execSQL("INSERT INTO " + TABLE1_NAME + " (number_1) VALUES ('" + TEST_VALUE1
+ + "');");
+ assertEquals(cursor1Count + cursor2Count, mergeCursor.getCount());
+ assertTrue(mergeCursor.requery());
+ cursor1Count += 1;
+ assertEquals(cursor1Count + cursor2Count, mergeCursor.getCount());
+ mDatabase.execSQL("INSERT INTO " + TABLE2_NAME + " (number_1) VALUES ('" + TEST_VALUE2
+ + "');");
+ cursor2Count += 1;
+ assertTrue(mergeCursor.requery());
+ assertEquals(cursor1Count + cursor2Count, mergeCursor.getCount());
+
+ mergeCursor.close();
+ assertFalse(mergeCursor.requery());
+ }
+
+ private void buildDatabaseWithTestValues(String text, double doubleNumber, long intNumber,
+ byte[] blob, String tablename) {
+ Object[] args = new Object[4];
+ args[0] = text;
+ args[1] = doubleNumber;
+ args[2] = intNumber;
+ args[3] = blob;
+ mDatabase.execSQL("CREATE TABLE " + tablename + " (_id INTEGER PRIMARY KEY,"
+ + "string_text TEXT, double_number REAL, int_number INTEGER, blob_data BLOB);");
+
+ // Insert record in giving table.
+ String sql = "INSERT INTO " + tablename + " (string_text, double_number, int_number,"
+ + " blob_data) VALUES (?,?,?,?)";
+ mDatabase.execSQL(sql, args);
+ // insert null blob.
+ sql = "INSERT INTO " + tablename + " (string_text) VALUES ('" + COLUMN_FOR_NULL_TEST + "')";
+ mDatabase.execSQL(sql);
+ }
+
+ private void setupDatabase() {
+ mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db");
+ if (mDatabaseFile.exists()) {
+ mDatabaseFile.delete();
+ }
+ mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+ assertNotNull(mDatabaseFile);
+ createTable(TABLE1_NAME, TABLE1_COLUMNS);
+ createTable(TABLE2_NAME, TABLE2_COLUMNS);
+ addValuesIntoTable(TABLE1_NAME, DEFAULT_TABLE_VALUE_BEGINS, HALF_VALUE);
+ addValuesIntoTable(TABLE2_NAME, HALF_VALUE + 1, MAX_VALUE);
+ }
+
+ private void createTable(String tableName, String columnNames) {
+ String sql = "Create TABLE " + tableName + " (_id INTEGER PRIMARY KEY, " + columnNames
+ + " );";
+ mDatabase.execSQL(sql);
+ }
+
+ private void addValuesIntoTable(String tableName, int start, int end) {
+ for (int i = start; i <= end; i++) {
+ mDatabase.execSQL("INSERT INTO " + tableName + "(number_1) VALUES ('"
+ + i + "');");
+ }
+ }
+
+ private Cursor getCursor(String tableName, String selection, String[] columnNames) {
+ return mDatabase.query(tableName, columnNames, selection, null, null, null, "number_1");
+ }
+
+ private void createCursors() {
+ mCursors[0] = getCursor(TABLE1_NAME, null, null);
+ mCursors[1] = getCursor(TABLE2_NAME, null, null);
+ }
+
+ private class MockObserver extends DataSetObserver {
+ private boolean mHasChanged = false;
+ private boolean mHasInvalidated = false;
+
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ mHasChanged = true;
+ }
+
+ @Override
+ public void onInvalidated() {
+ super.onInvalidated();
+ mHasInvalidated = true;
+ }
+
+ public void resetStatus() {
+ mHasChanged = false;
+ mHasInvalidated = false;
+ }
+
+ public boolean hasChanged() {
+ return mHasChanged;
+ }
+
+ public boolean hasInvalidated () {
+ return mHasInvalidated;
+ }
+ }
+}