/* * Copyright (C) 2021 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.car.qc.controller; import static com.android.car.qc.provider.BaseQCProvider.EXTRA_URI; import static com.android.car.qc.testutils.TestQCProvider.IS_DESTROYED_KEY; import static com.android.car.qc.testutils.TestQCProvider.IS_SUBSCRIBED_KEY; import static com.android.car.qc.testutils.TestQCProvider.KEY_DEFAULT; import static com.android.car.qc.testutils.TestQCProvider.METHOD_IS_DESTROYED; import static com.android.car.qc.testutils.TestQCProvider.METHOD_IS_SUBSCRIBED; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import androidx.lifecycle.Observer; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import com.android.car.qc.QCItem; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class RemoteQCControllerTest extends BaseQCControllerTestCase { private final Uri mDefaultUri = Uri.parse( "content://com.android.car.qc.testutils.AllowedTestQCProvider/" + KEY_DEFAULT); private RemoteQCController mController; @Override protected RemoteQCController getController() { if (mController == null) { mController = new RemoteQCController(mContext, mDefaultUri, mContext.getMainExecutor()); } return mController; } @Test public void updateListening_listen_updatesQCItem() { Observer observer = mock(Observer.class); RemoteQCController spiedController = spy(getController()); spiedController.addObserver(observer); spiedController.listen(true); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); verify(spiedController).onQCItemUpdated(notNull()); } @Test public void updateListening_listen_providerSubscribed() throws RemoteException { Observer observer = mock(Observer.class); getController().addObserver(observer); getController().listen(true); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); Bundle extras = new Bundle(); extras.putParcelable(EXTRA_URI, mDefaultUri); Bundle res = getController().getClient().call(METHOD_IS_SUBSCRIBED, null, extras); assertThat(res).isNotNull(); boolean isSubscribed = res.getBoolean(IS_SUBSCRIBED_KEY, false); assertThat(isSubscribed).isTrue(); } @Test public void updateListening_doNotListen_providerUnsubscribed() throws RemoteException { Observer observer = mock(Observer.class); getController().addObserver(observer); getController().listen(true); getController().listen(false); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); Bundle extras = new Bundle(); extras.putParcelable(EXTRA_URI, mDefaultUri); Bundle res = getController().getClient().call(METHOD_IS_SUBSCRIBED, null, extras); assertThat(res).isNotNull(); boolean isSubscribed = res.getBoolean(IS_SUBSCRIBED_KEY, true); assertThat(isSubscribed).isFalse(); } @Test public void updateListening_listen_registerContentObserver() { ContentResolver resolver = mock(ContentResolver.class); when(mContext.getContentResolver()).thenReturn(resolver); when(resolver.acquireContentProviderClient(mDefaultUri)).thenReturn( mock(ContentProviderClient.class)); Observer observer = mock(Observer.class); getController().addObserver(observer); getController().listen(true); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); verify(resolver).registerContentObserver(eq(mDefaultUri), eq(true), any(ContentObserver.class)); } @Test public void updateListening_doNotListen_unregisterContentObserver() { ContentResolver resolver = mock(ContentResolver.class); when(mContext.getContentResolver()).thenReturn(resolver); when(resolver.acquireContentProviderClient(mDefaultUri)).thenReturn( mock(ContentProviderClient.class)); Observer observer = mock(Observer.class); getController().addObserver(observer); getController().listen(true); getController().listen(false); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); verify(resolver).unregisterContentObserver(any(ContentObserver.class)); } @Test public void onDestroy_callsProviderOnDestroy() throws RemoteException { Observer observer = mock(Observer.class); getController().addObserver(observer); getController().listen(true); getController().listen(false); getController().destroy(); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); Bundle extras = new Bundle(); extras.putParcelable(EXTRA_URI, mDefaultUri); Bundle res = getController().getClient().call(METHOD_IS_DESTROYED, null, extras); assertThat(res).isNotNull(); boolean isDestroyed = res.getBoolean(IS_DESTROYED_KEY, false); assertThat(isDestroyed).isTrue(); } }