Add CTS tests for FDs backed by DBs and byte[]
The tests are partly based on code from
mdodd's change I4f21bdbe22be3c09eb8732a4e9b90b90d55d4941
Bug: http://b/issue?id=2595601
Change-Id: I47ab427a45cd584f958d27e4e9ac98b670e76d74
diff --git a/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java b/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
index c67002c..3c552e8 100644
--- a/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
+++ b/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
@@ -33,11 +33,15 @@
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;
import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintStream;
@TestTargetClass(android.database.DatabaseUtils.class)
@@ -63,6 +67,8 @@
assertNotNull(mDatabase);
mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, " +
"name TEXT, age INTEGER, address TEXT);");
+ mDatabase.execSQL(
+ "CREATE TABLE blob_test (_id INTEGER PRIMARY KEY, name TEXT, data BLOB)");
}
@Override
@@ -719,11 +725,98 @@
args = new String[] { "1000" }; // NO people can be older than this.
try {
- DatabaseUtils.stringForQuery(statement, args);
+ DatabaseUtils.blobFileDescriptorForQuery(statement, args);
fail("should throw SQLiteDoneException");
} catch (SQLiteDoneException e) {
// expected
}
statement.close();
}
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "blobFileDescriptorForQuery",
+ args = {android.database.sqlite.SQLiteDatabase.class, java.lang.String.class,
+ java.lang.String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "blobFileDescriptorForQuery",
+ args = {android.database.sqlite.SQLiteStatement.class, java.lang.String[].class}
+ )
+ })
+ public void testBlobFileDescriptorForQuery() throws Exception {
+ String data1 = "5300FEFF";
+ String data2 = "DECAFBAD";
+ mDatabase.execSQL("INSERT INTO blob_test (name, data) VALUES ('Mike', X'" + data1 + "')");
+
+ String query = "SELECT data FROM blob_test";
+ assertFileDescriptorContent(parseBlob(data1),
+ DatabaseUtils.blobFileDescriptorForQuery(mDatabase, query, null));
+
+ mDatabase.execSQL("INSERT INTO blob_test (name, data) VALUES ('Jack', X'" + data2 + "');");
+ query = "SELECT data FROM blob_test WHERE name = ?";
+ String[] args = new String[] { "Jack" };
+ assertFileDescriptorContent(parseBlob(data2),
+ DatabaseUtils.blobFileDescriptorForQuery(mDatabase, query, args));
+
+ args = new String[] { "No such name" };
+ try {
+ DatabaseUtils.stringForQuery(mDatabase, query, args);
+ fail("should throw SQLiteDoneException");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+
+ query = "SELECT data FROM blob_test WHERE name = ?;";
+ SQLiteStatement statement = mDatabase.compileStatement(query);
+ args = new String[] { "Mike" };
+ assertFileDescriptorContent(parseBlob(data1),
+ DatabaseUtils.blobFileDescriptorForQuery(statement, args));
+
+ args = new String[] { "No such name" };
+ try {
+ DatabaseUtils.blobFileDescriptorForQuery(statement, args);
+ fail("should throw SQLiteDoneException");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+ statement.close();
+ }
+
+ private static byte[] parseBlob(String src) {
+ int len = src.length();
+ byte[] result = new byte[len / 2];
+
+ for (int i = 0; i < len/2; i++) {
+ int val;
+ char c1 = src.charAt(i*2);
+ char c2 = src.charAt(i*2+1);
+ int val1 = Character.digit(c1, 16);
+ int val2 = Character.digit(c2, 16);
+ val = (val1 << 4) | val2;
+ result[i] = (byte)val;
+ }
+ return result;
+ }
+
+ private static void assertFileDescriptorContent(byte[] expected, ParcelFileDescriptor fd)
+ throws IOException {
+ assertInputStreamContent(expected, new ParcelFileDescriptor.AutoCloseInputStream(fd));
+ }
+
+ private static void assertInputStreamContent(byte[] expected, InputStream is)
+ throws IOException {
+ try {
+ byte[] observed = new byte[expected.length];
+ int count = is.read(observed);
+ assertEquals(expected.length, count);
+ assertEquals(-1, is.read());
+ MoreAsserts.assertEquals(expected, observed);
+ } finally {
+ is.close();
+ }
+ }
+
}
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java
index 5f4fe7a..828045a 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java
@@ -21,6 +21,7 @@
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
+import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
@@ -28,13 +29,27 @@
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteStatement;
+import android.os.ParcelFileDescriptor;
import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+
+import java.io.IOException;
+import java.io.InputStream;
@TestTargetClass(android.database.sqlite.SQLiteStatement.class)
public class SQLiteStatementTest extends AndroidTestCase {
private static final String STRING1 = "this is a test";
private static final String STRING2 = "another test";
+ private static final byte[][] BLOBS = new byte [][] {
+ parseBlob("86FADCF1A820666AEBD0789F47932151A2EF734269E8AC4E39630AB60519DFD8"),
+ new byte[0],
+ null,
+ parseBlob("00"),
+ parseBlob("FF"),
+ parseBlob("D7B500FECF25F7A4D83BF823D3858690790F2526013DE6CAE9A69170E2A1E47238"),
+ };
+
private static final String DATABASE_NAME = "database_test.db";
private static final int CURRENT_DATABASE_VERSION = 42;
@@ -61,6 +76,16 @@
mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
}
+ private void populateBlobTable() {
+ mDatabase.execSQL("CREATE TABLE blob_test (_id INTEGER PRIMARY KEY, data BLOB)");
+ for (int i = 0; i < BLOBS.length; i++) {
+ ContentValues values = new ContentValues();
+ values.put("_id", i);
+ values.put("data", BLOBS[i]);
+ mDatabase.insert("blob_test", null, values);
+ }
+ }
+
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "executeUpdateDelete",
@@ -217,4 +242,177 @@
statement.close();
}
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccessNormal() throws IOException {
+ doTestSimpleQueryForBlobFileDescriptorSuccess(0);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccessEmpty() throws IOException {
+ doTestSimpleQueryForBlobFileDescriptorSuccess(1);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccessNull() {
+ populateBlobTable();
+
+ String sql = "SELECT data FROM blob_test WHERE _id = " + 2;
+ SQLiteStatement stm = mDatabase.compileStatement(sql);
+ assertNull(stm.simpleQueryForBlobFileDescriptor());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccess00() throws IOException {
+ doTestSimpleQueryForBlobFileDescriptorSuccess(3);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccessFF() throws IOException {
+ doTestSimpleQueryForBlobFileDescriptorSuccess(4);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccessEmbeddedNul() throws IOException {
+ doTestSimpleQueryForBlobFileDescriptorSuccess(5);
+ }
+
+ private void doTestSimpleQueryForBlobFileDescriptorSuccess(int i) throws IOException {
+ populateBlobTable();
+
+ String sql = "SELECT data FROM blob_test WHERE _id = " + i;
+ SQLiteStatement stm = mDatabase.compileStatement(sql);
+ ParcelFileDescriptor fd = stm.simpleQueryForBlobFileDescriptor();
+ assertFileDescriptorContent(BLOBS[i], fd);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testSimpleQueryForBlobFileDescriptorSuccessParam() throws IOException {
+ populateBlobTable();
+
+ String sql = "SELECT data FROM blob_test WHERE _id = ?";
+ SQLiteStatement stm = mDatabase.compileStatement(sql);
+ stm.bindLong(1, 0);
+ ParcelFileDescriptor fd = stm.simpleQueryForBlobFileDescriptor();
+ assertFileDescriptorContent(BLOBS[0], fd);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testGetBlobFailureNoParam() throws Exception {
+ populateBlobTable();
+
+ String sql = "SELECT data FROM blob_test WHERE _id = 100";
+ SQLiteStatement stm = mDatabase.compileStatement(sql);
+ ParcelFileDescriptor fd = null;
+ SQLiteDoneException expectedException = null;
+ try {
+ fd = stm.simpleQueryForBlobFileDescriptor();
+ } catch (SQLiteDoneException ex) {
+ expectedException = ex;
+ } finally {
+ if (fd != null) {
+ fd.close();
+ fd = null;
+ }
+ }
+ assertNotNull("Should have thrown SQLiteDoneException", expectedException);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "simpleQueryForBlobFileDescriptor",
+ args = {}
+ )
+ public void testGetBlobFailureParam() throws Exception {
+ populateBlobTable();
+
+ String sql = "SELECT data FROM blob_test WHERE _id = ?";
+ SQLiteStatement stm = mDatabase.compileStatement(sql);
+ stm.bindLong(1, 100);
+ ParcelFileDescriptor fd = null;
+ SQLiteDoneException expectedException = null;
+ try {
+ fd = stm.simpleQueryForBlobFileDescriptor();
+ } catch (SQLiteDoneException ex) {
+ expectedException = ex;
+ } finally {
+ if (fd != null) {
+ fd.close();
+ fd = null;
+ }
+ }
+ assertNotNull("Should have thrown SQLiteDoneException", expectedException);
+ }
+
+ /*
+ * Convert string of hex digits to byte array.
+ * Results are undefined for poorly formed string.
+ *
+ * @param src hex string
+ */
+ private static byte[] parseBlob(String src) {
+ int len = src.length();
+ byte[] result = new byte[len / 2];
+
+ for (int i = 0; i < len/2; i++) {
+ int val;
+ char c1 = src.charAt(i*2);
+ char c2 = src.charAt(i*2+1);
+ int val1 = Character.digit(c1, 16);
+ int val2 = Character.digit(c2, 16);
+ val = (val1 << 4) | val2;
+ result[i] = (byte)val;
+ }
+ return result;
+ }
+
+ private static void assertFileDescriptorContent(byte[] expected, ParcelFileDescriptor fd)
+ throws IOException {
+ assertInputStreamContent(expected, new ParcelFileDescriptor.AutoCloseInputStream(fd));
+ }
+
+ private static void assertInputStreamContent(byte[] expected, InputStream is)
+ throws IOException {
+ try {
+ byte[] observed = new byte[expected.length];
+ int count = is.read(observed);
+ assertEquals(expected.length, count);
+ assertEquals(-1, is.read());
+ MoreAsserts.assertEquals(expected, observed);
+ } finally {
+ is.close();
+ }
+ }
}
diff --git a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java
index ce6658f..15c52cf 100644
--- a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java
@@ -28,9 +28,12 @@
import android.os.Parcelable;
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
@@ -110,6 +113,45 @@
}
@TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "fromData",
+ args = {byte[].class}
+ )
+ public void testFromData() throws IOException {
+ assertNull(ParcelFileDescriptor.fromData(null, null));
+ byte[] data = new byte[] { 0 };
+ assertFileDescriptorContent(data, ParcelFileDescriptor.fromData(data, null));
+ data = new byte[] { 0, 1, 2, 3 };
+ assertFileDescriptorContent(data, ParcelFileDescriptor.fromData(data, null));
+ data = new byte[0];
+ assertFileDescriptorContent(data, ParcelFileDescriptor.fromData(data, null));
+
+ // Check that modifying the data does not modify the data in the FD
+ data = new byte[] { 0, 1, 2, 3 };
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromData(data, null);
+ data[1] = 42;
+ assertFileDescriptorContent(new byte[] { 0, 1, 2, 3 }, pfd);
+ }
+
+ private static void assertFileDescriptorContent(byte[] expected, ParcelFileDescriptor fd)
+ throws IOException {
+ assertInputStreamContent(expected, new ParcelFileDescriptor.AutoCloseInputStream(fd));
+ }
+
+ private static void assertInputStreamContent(byte[] expected, InputStream is)
+ throws IOException {
+ try {
+ byte[] observed = new byte[expected.length];
+ int count = is.read(observed);
+ assertEquals(expected.length, count);
+ assertEquals(-1, is.read());
+ MoreAsserts.assertEquals(expected, observed);
+ } finally {
+ is.close();
+ }
+ }
+
+ @TestTargetNew(
level = TestLevel.COMPLETE,
method = "toString",
args = {}