Fakes for SQLite databases and taggings on views
diff --git a/src/com/xtremelabs/droidsugar/view/FakeAbstractCursor.java b/src/com/xtremelabs/droidsugar/view/FakeAbstractCursor.java
new file mode 100644
index 0000000..d5eaad2
--- /dev/null
+++ b/src/com/xtremelabs/droidsugar/view/FakeAbstractCursor.java
@@ -0,0 +1,15 @@
+package com.xtremelabs.droidsugar.view;
+
+import android.database.AbstractCursor;
+
+public class FakeAbstractCursor {
+ private AbstractCursor real;
+
+ public FakeAbstractCursor(AbstractCursor real) {
+ this.real = real;
+ }
+
+ public final boolean moveToFirst() {
+ return real.getCount() > 0;
+ }
+}
diff --git a/src/com/xtremelabs/droidsugar/view/FakeContentValues.java b/src/com/xtremelabs/droidsugar/view/FakeContentValues.java
new file mode 100644
index 0000000..27c7306
--- /dev/null
+++ b/src/com/xtremelabs/droidsugar/view/FakeContentValues.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2007 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 com.xtremelabs.droidsugar.view;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import android.content.ContentValues;
+import android.util.Log;
+import com.xtremelabs.droidsugar.ProxyDelegatingHandler;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public final class FakeContentValues {
+ private HashMap<String, Object> values = new HashMap<String, Object>();
+ private static final String TAG = "FakeContentValues";
+
+ public void __constructor__(ContentValues from) {
+ values = new HashMap<String, Object>(proxyFor(from).values);
+ }
+
+ private void __constructor__(HashMap<String, Object> values) {
+ this.values = values;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof ContentValues)) {
+ return false;
+ }
+ return values.equals(proxyFor((ContentValues) object).values);
+ }
+
+ @Override
+ public int hashCode() {
+ return values.hashCode();
+ }
+
+ public void put(String key, String value) {
+ values.put(key, value);
+ }
+
+ public void putAll(ContentValues other) {
+ values.putAll(proxyFor(other).values);
+ }
+
+ private FakeContentValues proxyFor(ContentValues other) {
+ return ((FakeContentValues) ProxyDelegatingHandler.getInstance().proxyFor(other));
+ }
+
+ public void put(String key, Byte value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, Short value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, Integer value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, Long value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, Float value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, Double value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, Boolean value) {
+ values.put(key, value);
+ }
+
+ public void put(String key, byte[] value) {
+ values.put(key, value);
+ }
+
+ public void putNull(String key) {
+ values.put(key, null);
+ }
+
+ public int size() {
+ return values.size();
+ }
+
+ public void remove(String key) {
+ values.remove(key);
+ }
+
+ public void clear() {
+ values.clear();
+ }
+
+ public boolean containsKey(String key) {
+ return values.containsKey(key);
+ }
+
+ public Object get(String key) {
+ return values.get(key);
+ }
+
+ public String getAsString(String key) {
+ Object value = values.get(key);
+ return value != null ? value.toString() : null;
+ }
+
+ public Long getAsLong(String key) {
+ Object value = values.get(key);
+ try {
+ return value != null ? ((Number) value).longValue() : null;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ try {
+ return Long.valueOf(value.toString());
+ } catch (NumberFormatException e2) {
+ Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key);
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Long: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public Integer getAsInteger(String key) {
+ Object value = values.get(key);
+ try {
+ return value != null ? ((Number) value).intValue() : null;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ try {
+ return Integer.valueOf(value.toString());
+ } catch (NumberFormatException e2) {
+ Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key);
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Integer: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public Short getAsShort(String key) {
+ Object value = values.get(key);
+ try {
+ return value != null ? ((Number) value).shortValue() : null;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ try {
+ return Short.valueOf(value.toString());
+ } catch (NumberFormatException e2) {
+ Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key);
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Short: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public Byte getAsByte(String key) {
+ Object value = values.get(key);
+ try {
+ return value != null ? ((Number) value).byteValue() : null;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ try {
+ return Byte.valueOf(value.toString());
+ } catch (NumberFormatException e2) {
+ Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key);
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Byte: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public Double getAsDouble(String key) {
+ Object value = values.get(key);
+ try {
+ return value != null ? ((Number) value).doubleValue() : null;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ try {
+ return Double.valueOf(value.toString());
+ } catch (NumberFormatException e2) {
+ Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key);
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Double: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public Float getAsFloat(String key) {
+ Object value = values.get(key);
+ try {
+ return value != null ? ((Number) value).floatValue() : null;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ try {
+ return Float.valueOf(value.toString());
+ } catch (NumberFormatException e2) {
+ Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key);
+ return null;
+ }
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Float: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public Boolean getAsBoolean(String key) {
+ Object value = values.get(key);
+ try {
+ return (Boolean) value;
+ } catch (ClassCastException e) {
+ if (value instanceof CharSequence) {
+ return Boolean.valueOf(value.toString());
+ } else {
+ Log.e(TAG, "Cannot cast value for " + key + " to a Boolean: " + value, e);
+ return null;
+ }
+ }
+ }
+
+ public byte[] getAsByteArray(String key) {
+ Object value = values.get(key);
+ if (value instanceof byte[]) {
+ return (byte[]) value;
+ } else {
+ return null;
+ }
+ }
+
+ public Set<Map.Entry<String, Object>> valueSet() {
+ return values.entrySet();
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ @Deprecated
+ public void putStringArrayList(String key, ArrayList<String> value) {
+ values.put(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Deprecated
+ public ArrayList<String> getStringArrayList(String key) {
+ return (ArrayList<String>) values.get(key);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (String name : values.keySet()) {
+ String value = getAsString(name);
+ if (sb.length() > 0) sb.append(" ");
+ sb.append(name + "=" + value);
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/com/xtremelabs/droidsugar/view/FakeSQLiteDatabase.java b/src/com/xtremelabs/droidsugar/view/FakeSQLiteDatabase.java
new file mode 100644
index 0000000..c69f890
--- /dev/null
+++ b/src/com/xtremelabs/droidsugar/view/FakeSQLiteDatabase.java
@@ -0,0 +1,74 @@
+package com.xtremelabs.droidsugar.view;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteCursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import static com.xtremelabs.droidsugar.view.FakeHelper.newInstanceOf;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class FakeSQLiteDatabase {
+
+ public static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags) {
+ return newInstanceOf(SQLiteDatabase.class);
+ }
+
+ Map<String, Table> tables = new HashMap<String, Table>();
+
+ public long insert(String table, String nullColumnHack, ContentValues values) {
+ Table theTable = getTable(table);
+ theTable.insert(values);
+ return -1;
+ }
+
+ public Cursor query(final String table, final String[] columns, String selection,
+ String[] selectionArgs, String groupBy, String having,
+ String orderBy) {
+ final Table theTable = getTable(table);
+ return new SQLiteCursor(null, null, null, null) {
+ private int currentRowNumber = 0;
+
+ @Override
+ public int getCount() {
+ return theTable.rows.size();
+ }
+
+ @Override
+ public byte[] getBlob(int columnIndex) {
+ return (byte[]) get(columnIndex);
+ }
+
+ @Override
+ public String getString(int columnIndex) {
+ return (String) get(columnIndex);
+ }
+
+ private Object get(int columnIndex) {
+ return theTable.rows.get(currentRowNumber).get(columns[columnIndex]);
+ }
+ };
+ }
+
+ private Table getTable(String tableName) {
+ Table table = tables.get(tableName);
+ if (table == null) {
+ table = new Table();
+ tables.put(tableName, table);
+ }
+ return table;
+ }
+
+ private class Table {
+ List<ContentValues> rows = new ArrayList<ContentValues>();
+
+ public void insert(ContentValues values) {
+ rows.add(values);
+ }
+ }
+}
diff --git a/src/com/xtremelabs/droidsugar/view/FakeView.java b/src/com/xtremelabs/droidsugar/view/FakeView.java
index e31aef6..5a6af1a 100644
--- a/src/com/xtremelabs/droidsugar/view/FakeView.java
+++ b/src/com/xtremelabs/droidsugar/view/FakeView.java
@@ -1,13 +1,15 @@
package com.xtremelabs.droidsugar.view;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import com.xtremelabs.droidsugar.ProxyDelegatingHandler;
-import java.util.ArrayList;
-import java.util.List;
-
@SuppressWarnings({"ALL"})
public class FakeView {
private View realView;
@@ -20,6 +22,7 @@
public boolean selected;
private View.OnClickListener onClickListener;
private Object tag;
+ private Map<Integer, Object> tags = new HashMap<Integer, Object>();
public FakeView(View view) {
this.realView = view;
@@ -123,4 +126,13 @@
public void setTag(Object tag) {
this.tag = tag;
}
+
+ public Object getTag(int key) {
+ return tags.get(key);
+ }
+
+ public void setTag(int key, Object value) {
+ tags.put(key, value);
+ }
+
}
diff --git a/test/com/xtremelabs/droidsugar/view/SQLiteDatabaseTest.java b/test/com/xtremelabs/droidsugar/view/SQLiteDatabaseTest.java
new file mode 100644
index 0000000..37a2f4f
--- /dev/null
+++ b/test/com/xtremelabs/droidsugar/view/SQLiteDatabaseTest.java
@@ -0,0 +1,58 @@
+package com.xtremelabs.droidsugar.view;
+
+import android.content.ContentValues;
+import android.database.AbstractCursor;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import com.xtremelabs.droidsugar.DroidSugarAndroidTestRunner;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+@RunWith(DroidSugarAndroidTestRunner.class)
+public class SQLiteDatabaseTest {
+ private SQLiteDatabase database;
+
+ @Before
+ public void setUp() throws Exception {
+ DroidSugarAndroidTestRunner.addProxy(SQLiteDatabase.class, FakeSQLiteDatabase.class);
+ DroidSugarAndroidTestRunner.addProxy(ContentValues.class, FakeContentValues.class);
+ DroidSugarAndroidTestRunner.addProxy(AbstractCursor.class, FakeAbstractCursor.class);
+
+ database = SQLiteDatabase.openDatabase("path", null, 0);
+ }
+
+ @Test
+ public void testInsertAndQuery() throws Exception {
+
+ String stringColumnValue = "column_value";
+ byte[] byteColumnValue = new byte[] {1,2,3};
+
+ ContentValues values = new ContentValues();
+
+ values.put("first_column", stringColumnValue);
+ values.put("second_column", byteColumnValue);
+
+ database.insert("table_name", null, values);
+
+ Cursor cursor = database.query("table_name", new String[] {"second_column", "first_column"}, null, null, null, null, null);
+
+ assertThat(cursor.moveToFirst(), equalTo(true));
+
+ byte[] byteValueFromDatabase = cursor.getBlob(0);
+ String stringValueFromDatabase = cursor.getString(1);
+
+ assertThat(stringValueFromDatabase, equalTo(stringColumnValue));
+ assertThat(byteValueFromDatabase, equalTo(byteColumnValue));
+ }
+
+ @Test
+ public void testEmptyTable() throws Exception {
+ Cursor cursor = database.query("table_name", new String[] {"second_column", "first_column"}, null, null, null, null, null);
+
+ assertThat(cursor.moveToFirst(), equalTo(false));
+ }
+}