--- /dev/null
+/*
+ * 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.content.Context;
+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() {
+ File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
+ mDatabaseFile = new File(dbDir, "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");
+ }
+}