Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4344e876 authored by Hyundo Moon's avatar Hyundo Moon
Browse files

Add tests for BluetoothPbapSimVcardManager (1/2)

Bug: 237548430
Test: atest BluetoothPbapSimVcardManagerTest
Change-Id: Iaa66f434b742d44a647d5629f2fd699fa720513e
Merged-In: Iaa66f434b742d44a647d5629f2fd699fa720513e
parent 7d93c7e1
Loading
Loading
Loading
Loading
+24 −23
Original line number Diff line number Diff line
@@ -59,22 +59,28 @@ public class BluetoothPbapSimVcardManager {

    private static final boolean V = BluetoothPbapService.VERBOSE;

    private static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
    @VisibleForTesting
    public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO =
        "Failed to get database information";

    private static final String FAILURE_REASON_NO_ENTRY =
    @VisibleForTesting
    public static final String FAILURE_REASON_NO_ENTRY =
        "There's no exportable in the database";

    private static final String FAILURE_REASON_NOT_INITIALIZED =
    @VisibleForTesting
    public static final String FAILURE_REASON_NOT_INITIALIZED =
        "The vCard composer object is not correctly initialized";

    /** Should be visible only from developers... (no need to translate, hopefully) */
    private static final String FAILURE_REASON_UNSUPPORTED_URI =
    @VisibleForTesting
    public static final String FAILURE_REASON_UNSUPPORTED_URI =
        "The Uri vCard composer received is not supported by the composer.";

    private static final String NO_ERROR = "No error";
    @VisibleForTesting
    public static final String NO_ERROR = "No error";

    private final String SIM_URI = "content://icc/adn";
    @VisibleForTesting
    public static final Uri SIM_URI = Uri.parse("content://icc/adn");

    @VisibleForTesting
    public static final String SIM_PATH = "/SIM1/telecom";
@@ -105,15 +111,13 @@ public class BluetoothPbapSimVcardManager {

    public boolean init(final Uri contentUri, final String selection,
            final String[] selectionArgs, final String sortOrder) {
            final Uri myUri = Uri.parse(SIM_URI);
        if (!myUri.equals(contentUri)) {

        if (!SIM_URI.equals(contentUri)) {
            mErrorReason = FAILURE_REASON_UNSUPPORTED_URI;
            return false;
        }

        //checkpoint Figure out if we can apply selection, projection and sort order.
        mCursor = mContentResolver.query(
        mCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(mContentResolver,
                contentUri, SIM_PROJECTION, null, null, sortOrder);

        if (mCursor == null) {
@@ -234,7 +238,7 @@ public class BluetoothPbapSimVcardManager {
        return mErrorReason;
    }

    public void setPositionByAlpha(int position) {
    private void setPositionByAlpha(int position) {
        if(mCursor == null) {
            return;
        }
@@ -264,11 +268,11 @@ public class BluetoothPbapSimVcardManager {
    }

    public final int getSIMContactsSize() {
        final Uri myUri = Uri.parse(SIM_URI);
        int size = 0;
        Cursor contactCursor = null;
        try {
            contactCursor = mContentResolver.query(myUri, SIM_PROJECTION, null,null, null);
            contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(
                    mContentResolver, SIM_URI, SIM_PROJECTION, null,null, null);
            if (contactCursor != null) {
                size = contactCursor.getCount();
            }
@@ -285,10 +289,10 @@ public class BluetoothPbapSimVcardManager {
        nameList.add(BluetoothPbapService.getLocalPhoneName());
        //Since owner card should always be 0.vcf, maintain a separate list to avoid sorting
        ArrayList<String> allnames = new ArrayList<String>();
        final Uri myUri = Uri.parse(SIM_URI);
        Cursor contactCursor = null;
        try {
            contactCursor = mContentResolver.query(myUri, SIM_PROJECTION, null,null,null);
            contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(
                    mContentResolver, SIM_URI, SIM_PROJECTION, null,null,null);
            if (contactCursor != null) {
                for (contactCursor.moveToFirst(); !contactCursor.isAfterLast(); contactCursor
                        .moveToNext()) {
@@ -326,11 +330,10 @@ public class BluetoothPbapSimVcardManager {
        ArrayList<String> nameList = new ArrayList<String>();
        ArrayList<String> startNameList = new ArrayList<String>();
        Cursor contactCursor = null;
        final Uri uri = Uri.parse(SIM_URI);

        try {
            contactCursor = mContentResolver.query(uri, SIM_PROJECTION,
                    null, null, null);
            contactCursor = BluetoothPbapMethodProxy.getInstance().contentResolverQuery(
                    mContentResolver, SIM_URI, SIM_PROJECTION, null, null, null);

            if (contactCursor != null) {
                for (contactCursor.moveToFirst(); !contactCursor.isAfterLast(); contactCursor
@@ -381,14 +384,13 @@ public class BluetoothPbapSimVcardManager {
            Log.e(TAG, "internal error: startPoint or endPoint is not correct.");
            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
        }
        final Uri myUri = Uri.parse(SIM_URI);
        BluetoothPbapSimVcardManager composer = null;
        HandlerForStringBuffer buffer = null;
        try {
            composer = new BluetoothPbapSimVcardManager(mContext);
            buffer = new HandlerForStringBuffer(op, ownerVCard);

            if (!composer.init(myUri, null, null, null) || !buffer.onInit(mContext)) {
            if (!composer.init(SIM_URI, null, null, null) || !buffer.onInit(mContext)) {
                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
            }
            composer.moveToPosition(startPoint -1, false);
@@ -480,14 +482,13 @@ public class BluetoothPbapSimVcardManager {
            Log.e(TAG, "Internal error: offset is not correct.");
            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
        }
        final Uri myUri = Uri.parse(SIM_URI);
        if (V) Log.v(TAG, "composeAndSendSIMPhonebookOneVcard orderByWhat " + orderByWhat);
        BluetoothPbapSimVcardManager composer = null;
        HandlerForStringBuffer buffer = null;
        try {
            composer = new BluetoothPbapSimVcardManager(mContext);
            buffer = new HandlerForStringBuffer(op, ownerVCard);
            if (!composer.init(myUri, null, null,null)||
            if (!composer.init(SIM_URI, null, null,null)||
                               !buffer.onInit(mContext)) {
                return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
            }
+261 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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.bluetooth.pbap;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.UserManager;
import android.util.Log;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.obex.HeaderSet;
import com.android.bluetooth.obex.Operation;
import com.android.bluetooth.obex.ResponseCodes;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import com.android.bluetooth.pbap.BluetoothPbapObexServer.AppParamValue;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class BluetoothPbapSimVcardManagerTest {

    private static final String TAG = BluetoothPbapSimVcardManagerTest.class.getSimpleName();

    @Spy
    BluetoothPbapMethodProxy mPbapMethodProxy = BluetoothPbapMethodProxy.getInstance();

    Context mContext;
    BluetoothPbapSimVcardManager mManager;

    private static final Uri WRONG_URI = Uri.parse("content://some/wrong/uri");

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        BluetoothPbapMethodProxy.setInstanceForTesting(mPbapMethodProxy);
        mContext =  InstrumentationRegistry.getTargetContext();
        mManager = new BluetoothPbapSimVcardManager(mContext);
    }

    @After
    public void tearDown() throws Exception {
        BluetoothPbapMethodProxy.setInstanceForTesting(null);
    }

    @Test
    public void testInit_whenUriIsUnsupported() throws Exception {
        assertThat(mManager.init(WRONG_URI, null, null, null))
                .isFalse();
        assertThat(mManager.getErrorReason())
                .isEqualTo(BluetoothPbapSimVcardManager.FAILURE_REASON_UNSUPPORTED_URI);
    }

    @Test
    public void testInit_whenCursorIsNull() throws Exception {
        doReturn(null).when(mPbapMethodProxy)
                .contentResolverQuery(any(), any(), any(), any(), any(), any());

        assertThat(mManager.init(BluetoothPbapSimVcardManager.SIM_URI, null, null, null))
                .isFalse();
        assertThat(mManager.getErrorReason())
                .isEqualTo(BluetoothPbapSimVcardManager.FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO);
    }

    @Test
    public void testInit_whenCursorHasNoEntry() throws Exception {
        Cursor cursor = mock(Cursor.class);
        when(cursor.getCount()).thenReturn(0);
        doReturn(cursor).when(mPbapMethodProxy)
                .contentResolverQuery(any(), any(), any(), any(), any(), any());

        assertThat(mManager.init(BluetoothPbapSimVcardManager.SIM_URI, null, null, null))
                .isFalse();
        verify(cursor).close();
        assertThat(mManager.getErrorReason())
                .isEqualTo(BluetoothPbapSimVcardManager.FAILURE_REASON_NO_ENTRY);
    }

    @Test
    public void testInit_success() throws Exception {
        Cursor cursor = mock(Cursor.class);
        when(cursor.getCount()).thenReturn(1);
        when(cursor.moveToFirst()).thenReturn(true);
        doReturn(cursor).when(mPbapMethodProxy)
                .contentResolverQuery(any(), any(), any(), any(), any(), any());

        assertThat(mManager.init(BluetoothPbapSimVcardManager.SIM_URI, null, null, null))
                .isTrue();
        assertThat(mManager.getErrorReason()).isEqualTo(BluetoothPbapSimVcardManager.NO_ERROR);
    }

    @Test
    public void testCreateOneEntry_whenNotInitialized() throws Exception {
        assertThat(mManager.createOneEntry(true)).isNull();
        assertThat(mManager.getErrorReason())
                .isEqualTo(BluetoothPbapSimVcardManager.FAILURE_REASON_NOT_INITIALIZED);
    }

    @Test
    public void testCreateOneEntry_success() throws Exception {
        Cursor cursor = initManager();

        assertThat(mManager.createOneEntry(true)).isNotNull();
        assertThat(mManager.createOneEntry(false)).isNotNull();
        verify(cursor, times(2)).moveToNext();
    }

    @Test
    public void testTerminate() throws Exception {
        Cursor cursor = initManager();
        mManager.terminate();

        verify(cursor).close();
    }

    @Test
    public void testGetCount_beforeInit() {
        assertThat(mManager.getCount()).isEqualTo(0);
    }

    @Test
    public void testGetCount_success() {
        final int count = 5;
        Cursor cursor = initManager();
        when(cursor.getCount()).thenReturn(count);

        assertThat(mManager.getCount()).isEqualTo(count);
    }

    @Test
    public void testIsAfterLast_beforeInit() {
        assertThat(mManager.isAfterLast()).isFalse();
    }

    @Test
    public void testIsAfterLast_success() {
        final boolean isAfterLast = true;
        Cursor cursor = initManager();
        when(cursor.isAfterLast()).thenReturn(isAfterLast);

        assertThat(mManager.isAfterLast()).isEqualTo(isAfterLast);
    }

    @Test
    public void testMoveToPosition_beforeInit() {
        try {
            mManager.moveToPosition(0, /*sortByAlphabet=*/ true);
            mManager.moveToPosition(0, /*sortByAlphabet=*/ false);
        } catch (Exception e) {
            assertWithMessage("This should not throw exception").fail();
        }
    }

    @Test
    public void testMoveToPosition_byAlphabeticalOrder_success() {
        Cursor cursor = initManager();
        List<String> nameList = Arrays.asList("D", "C", "A", "B");

        // Implement Cursor iteration
        final int size = nameList.size();
        AtomicInteger currentPosition = new AtomicInteger(0);
        when(cursor.moveToFirst()).then((Answer<Boolean>) i -> {
            currentPosition.set(0);
            return true;
        });
        when(cursor.isAfterLast()).then((Answer<Boolean>) i -> {
            return currentPosition.get() >= size;
        });
        when(cursor.moveToNext()).then((Answer<Boolean>) i -> {
            currentPosition.getAndAdd(1);
            return true;
        });
        when(cursor.getString(anyInt())).then((Answer<String>) i -> {
            return nameList.get(currentPosition.get());
        });
        // Find first one in alphabetical order ("A")
        int position = 0;
        mManager.moveToPosition(position, /*sortByAlphabet=*/ true);

        assertThat(currentPosition.get()).isEqualTo(2);
    }

    @Test
    public void testMoveToPosition_notByAlphabeticalOrder_success() {
        Cursor cursor = initManager();
        int position = 3;

        mManager.moveToPosition(position, /*sortByAlphabet=*/ false);

        verify(cursor).moveToPosition(position);
    }

    @Test
    public void testGetSIMContactsSize() {
        final int count = 10;
        Cursor cursor = initManager();
        when(cursor.getCount()).thenReturn(count);

        assertThat(mManager.getSIMContactsSize()).isEqualTo(count);
        verify(cursor).close();
    }

    private Cursor initManager() {
        Cursor cursor = mock(Cursor.class);
        when(cursor.getCount()).thenReturn(10);
        when(cursor.moveToFirst()).thenReturn(true);
        when(cursor.isAfterLast()).thenReturn(false);
        doReturn(cursor).when(mPbapMethodProxy)
                .contentResolverQuery(any(), any(), any(), any(), any(), any());
        mManager.init(BluetoothPbapSimVcardManager.SIM_URI, null, null, null);

        return cursor;
    }
}