Add telephony-common-testing
This is a library for testing related logic used by telephony unit and
CTS tests.
Bug: 154363919
Test: atest TeleServiceTests:SimPhonebookProviderTest
Change-Id: I584150dd8352dbb49d70ea28c6d064a6336d018d
diff --git a/testing/Android.bp b/testing/Android.bp
new file mode 100644
index 0000000..527abc8
--- /dev/null
+++ b/testing/Android.bp
@@ -0,0 +1,23 @@
+android_library {
+ name: "telephony-common-testing",
+
+ srcs: ["**/*.java"],
+
+ static_libs: [
+ "androidx.annotation_annotation",
+ "guava",
+ "junit",
+ "mockito-target-minus-junit4",
+ "telephony-common",
+ "truth-prebuilt",
+ ],
+
+ sdk_version: "test_current",
+
+ visibility: [
+ "//cts/tests/tests/simphonebookprovider",
+ "//cts/tests/tests/simphonebookprovider/nosim",
+ "//frameworks/opt/telephony/tests",
+ "//packages/services/Telephony/tests",
+ ],
+}
diff --git a/testing/AndroidManifest.xml b/testing/AndroidManifest.xml
new file mode 100644
index 0000000..6be665b
--- /dev/null
+++ b/testing/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.telephony.testing">
+
+ <application>
+
+ </application>
+
+</manifest>
+
diff --git a/testing/src/com/android/internal/telephony/testing/CursorSubject.java b/testing/src/com/android/internal/telephony/testing/CursorSubject.java
new file mode 100644
index 0000000..999e92c
--- /dev/null
+++ b/testing/src/com/android/internal/telephony/testing/CursorSubject.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2020 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.android.internal.telephony.testing;
+
+import static com.google.common.truth.Truth.assertAbout;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.CursorWrapper;
+import android.database.DatabaseUtils;
+
+import androidx.annotation.Nullable;
+
+import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.IntegerSubject;
+import com.google.common.truth.IterableSubject;
+import com.google.common.truth.StringSubject;
+import com.google.common.truth.Subject;
+import com.google.common.truth.Truth;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Truth subject for making assertions about {@link Cursor}s. */
+public final class CursorSubject extends Subject {
+
+ private final Cursor mActual;
+
+ private CursorSubject(FailureMetadata metadata, @Nullable Cursor actual) {
+ super(metadata, new StringableCursor(actual));
+ this.mActual = new StringableCursor(actual);
+ }
+
+ /** Returns the factory for this subject. */
+ public static Factory<CursorSubject, Cursor> cursors() {
+ return CursorSubject::new;
+ }
+
+ /** Starts an assertion. */
+ public static CursorSubject assertThat(Cursor cursor) {
+ return assertAbout(cursors()).that(cursor);
+ }
+
+ /** Asserts {@link Cursor#getCount()} has the specified value. */
+ public void hasCount(int count) {
+ check("getCount()").that(mActual.getCount()).isEqualTo(count);
+ }
+
+ /** Asserts {@link Cursor#getColumnNames()} match those specified. */
+ public void hasColumnNames(String... columnNames) {
+ check("getColumnNames()").that(mActual.getColumnNames()).asList()
+ .containsExactlyElementsIn(columnNames).inOrder();
+ }
+
+ /** Positions the cursor under test at the specified row to make an assertion about it. */
+ public CursorSubject atRow(int position) {
+ check("moveToPosition").that(mActual.moveToPosition(position)).isTrue();
+ return this;
+ }
+
+ /** Asserts that the row at the cursor's current position has the specified values. */
+ public CursorSubject hasRowValues(Object... values) {
+ check("getColumnCount()").that(mActual.getColumnCount()).isEqualTo(values.length);
+ ContentValues expectedValues = new ContentValues();
+ for (int i = 0; i < values.length; i++) {
+ expectedValues.put(mActual.getColumnName(i), values[i].toString());
+ }
+
+ ContentValues actualValues = new ContentValues();
+ DatabaseUtils.cursorRowToContentValues(mActual, actualValues);
+
+ check("Row: %s", mActual.getPosition()).that(actualValues).isEqualTo(expectedValues);
+ return this;
+ }
+
+ /** Asserts that the cursor has a single row with the specified values. */
+ public void hasSingleRow(Object... values) {
+ hasCount(1);
+ atRow(0).hasRowValues(values);
+ }
+
+ /**
+ * Asserts that the row at the cursor's current position has the specified value for the
+ * specified column.
+ */
+ public CursorSubject hasRowValue(String columnName, Object value) {
+ int index = mActual.getColumnIndex(columnName);
+ check("getColumnIndex()").that(index).isNotEqualTo(-1);
+
+ check("Row[%s]: %s", columnName, index).that(mActual.getString(index))
+ .isEqualTo(value.toString());
+ return this;
+ }
+
+ /** Starts an assertion about the value of the specified column for the current row. */
+ public IntegerSubject intField(String columnName) {
+ int index = mActual.getColumnIndex(columnName);
+ check("getColumnIndex()").that(index).isNotEqualTo(-1);
+ check("getType()").that(mActual.getType(index)).isEqualTo(Cursor.FIELD_TYPE_INTEGER);
+
+ return check("getInt()").that(mActual.getInt(index));
+ }
+
+ /** Starts an assertion about the value of the specified column for the current row. */
+ public StringSubject stringField(String columnName) {
+ int index = mActual.getColumnIndex(columnName);
+ check("getColumnIndex()").that(index).isNotEqualTo(-1);
+ check("getType()").that(mActual.getType(index)).isEqualTo(Cursor.FIELD_TYPE_STRING);
+
+ return check("getString()").that(mActual.getString(index));
+ }
+
+ /** Asserts that the cursor rows match the data specified. */
+ public void hasData(Object[][] rows) {
+ hasCount(rows.length);
+ for (int i = 0; i < rows.length; i++) {
+ atRow(i).hasRowValues(rows[i]);
+ }
+ }
+
+ /** Starts an assertion about the cursor's rows. */
+ public IterableSubject asLists() {
+ List<List<String>> result = new ArrayList<>();
+ mActual.moveToPosition(-1);
+ while (mActual.moveToNext()) {
+ List<String> row = new ArrayList<>();
+ for (int i = 0; i < mActual.getColumnCount(); i++) {
+ row.add(mActual.getString(i));
+ }
+ result.add(row);
+ }
+ return Truth.assertThat(result);
+ }
+
+ private static class StringableCursor extends CursorWrapper {
+
+ StringableCursor(Cursor cursor) {
+ super(cursor);
+ }
+
+ @Override
+ public String toString() {
+ return DatabaseUtils.dumpCursorToString(getWrappedCursor());
+ }
+ }
+
+}
diff --git a/testing/src/com/android/internal/telephony/testing/TelephonyAssertions.java b/testing/src/com/android/internal/telephony/testing/TelephonyAssertions.java
new file mode 100644
index 0000000..d18a5cf
--- /dev/null
+++ b/testing/src/com/android/internal/telephony/testing/TelephonyAssertions.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 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.android.internal.telephony.testing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Assert;
+
+/** Assertions used by telephony tests. */
+public class TelephonyAssertions {
+
+ /**
+ * Asserts that the provided action throws the specified exception.
+ *
+ * <p>TODO: Replace with org.junit.Assert.assertThrows when Android upgrades to JUnit 4.12
+ *
+ * @return the exception that was thrown when the assertion passes.
+ */
+ public static <T extends Throwable> T assertThrows(
+ Class<T> throwableClass, ThrowingRunnable action) {
+ try {
+ action.run();
+ } catch (Throwable t) {
+ assertThat(t).isInstanceOf(throwableClass);
+ return throwableClass.cast(t);
+ }
+ Assert.fail("Expected " + throwableClass.getSimpleName() + " but no exception was thrown");
+ // This is unreachable but needed to compile.
+ return null;
+ }
+
+ /** Runnable that can throw a checked exception. */
+ public interface ThrowingRunnable {
+ /** Method with code that may throw a checked exception. */
+ void run() throws Exception;
+ }
+}