1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.car.content.pm;
17 
18 import static android.view.Display.DEFAULT_DISPLAY;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static org.junit.Assert.assertThrows;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyInt;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.car.CarVersion;
30 import android.content.Context;
31 import android.content.pm.PackageManager.NameNotFoundException;
32 import android.os.RemoteException;
33 import android.os.ServiceSpecificException;
34 import android.platform.test.annotations.DisabledOnRavenwood;
35 import android.platform.test.ravenwood.RavenwoodRule;
36 
37 import com.android.car.internal.ICarBase;
38 
39 import org.junit.Before;
40 import org.junit.Rule;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.mockito.Mock;
44 import org.mockito.junit.MockitoJUnitRunner;
45 
46 import java.util.concurrent.Executor;
47 
48 @RunWith(MockitoJUnitRunner.class)
49 public final class CarPackageManagerUnitTest {
50 
51     // Need to fake Process.myUserHandle().
52     @Rule
53     public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
54             .setProcessApp()
55             .build();
56 
57     @Mock
58     private ICarBase mCar;
59 
60     @Mock
61     private ICarPackageManager mService;
62 
63     @Mock
64     private Executor mExecutor;
65 
66     @Mock
67     private CarPackageManager.BlockingUiCommandListener mBlockingUiCommandListener;
68 
69     private CarPackageManager mMgr;
70 
71     @Before
setFixtures()72     public void setFixtures() {
73         mMgr = new CarPackageManager(mCar, mService);
74     }
75 
76     @Test
testGetTargetCarVersion_self_ok()77     public void testGetTargetCarVersion_self_ok() throws Exception {
78         mockPackageName("dr.evil");
79         CarVersion apiVersion = CarVersion.forMajorAndMinorVersions(66, 6);
80         when(mService.getSelfTargetCarVersion("dr.evil")).thenReturn(apiVersion);
81 
82         assertThat(mMgr.getTargetCarVersion()).isSameInstanceAs(apiVersion);
83     }
84 
85     @Test
testGetTargetCarVersion_self_remoteException()86     public void testGetTargetCarVersion_self_remoteException() throws Exception {
87         mockPackageName("the.meaning.of.life");
88         RemoteException cause = new RemoteException("D'OH!");
89         when(mService.getSelfTargetCarVersion("the.meaning.of.life")).thenThrow(cause);
90 
91         RuntimeException e = assertThrows(RuntimeException.class, () -> mMgr.getTargetCarVersion());
92 
93         assertThat(e.getCause()).isSameInstanceAs(cause);
94     }
95 
96     @Test
testGetTargetCarVersion_ok()97     public void testGetTargetCarVersion_ok() throws Exception {
98         CarVersion apiVersion = CarVersion.forMajorAndMinorVersions(66, 6);
99         when(mService.getTargetCarVersion("dr.evil")).thenReturn(apiVersion);
100 
101         assertThat(mMgr.getTargetCarVersion("dr.evil")).isSameInstanceAs(apiVersion);
102     }
103 
104     @Test
testGetTargetCarVersion_runtimeException()105     public void testGetTargetCarVersion_runtimeException() throws Exception {
106         RemoteException cause = new RemoteException("D'OH!");
107         when(mService.getTargetCarVersion("the.meaning.of.life")).thenThrow(cause);
108 
109         RuntimeException e = assertThrows(RuntimeException.class,
110                 () -> mMgr.getTargetCarVersion("the.meaning.of.life"));
111 
112         assertThat(e.getCause()).isSameInstanceAs(cause);
113     }
114 
115     @Test
testGetTargetCarVersion_serviceException_unexpectedErrorCode()116     public void testGetTargetCarVersion_serviceException_unexpectedErrorCode() throws Exception {
117         ServiceSpecificException cause = new ServiceSpecificException(666, "D'OH!");
118         when(mService.getTargetCarVersion("the.meaning.of.life")).thenThrow(cause);
119 
120         IllegalStateException e = assertThrows(IllegalStateException.class,
121                 () -> mMgr.getTargetCarVersion("the.meaning.of.life"));
122 
123         assertThat(e.getCause()).isSameInstanceAs(cause);
124     }
125 
126     @Test
127     @DisabledOnRavenwood(blockedBy = NameNotFoundException.class)
testGetTargetCarVersion_serviceException_notFound()128     public void testGetTargetCarVersion_serviceException_notFound() throws Exception {
129         when(mService.getTargetCarVersion("the.meaning.of.life"))
130                 .thenThrow(new ServiceSpecificException(CarPackageManager.ERROR_CODE_NO_PACKAGE,
131                         "D'OH!"));
132 
133         NameNotFoundException e = assertThrows(NameNotFoundException.class,
134                 () -> mMgr.getTargetCarVersion("the.meaning.of.life"));
135 
136         assertThat(e.getMessage()).contains("the.meaning.of.life");
137         assertThat(e.getMessage()).doesNotContain("D'OH!");
138     }
139 
140     @Test
registerBlockingUiCommandListener()141     public void registerBlockingUiCommandListener() throws Exception {
142         mMgr.registerBlockingUiCommandListener(DEFAULT_DISPLAY, mExecutor,
143                 mBlockingUiCommandListener);
144 
145         verify(mService).registerBlockingUiCommandListener(any(), anyInt());
146     }
147 
148     @Test
registerBlockingUiCommandListener_sameListenerNotRegisterForAnotherDisplay()149     public void registerBlockingUiCommandListener_sameListenerNotRegisterForAnotherDisplay()
150             throws Exception {
151         int tempDisplayId = 1;
152 
153         mMgr.registerBlockingUiCommandListener(DEFAULT_DISPLAY, mExecutor,
154                 mBlockingUiCommandListener);
155 
156         assertThrows(IllegalStateException.class,
157                 () -> mMgr.registerBlockingUiCommandListener(tempDisplayId, mExecutor,
158                         mBlockingUiCommandListener));
159     }
160 
161     @Test
unregisterBlockingUiCommandListener()162     public void unregisterBlockingUiCommandListener() throws Exception {
163         mMgr.registerBlockingUiCommandListener(DEFAULT_DISPLAY, mExecutor,
164                 mBlockingUiCommandListener);
165 
166         mMgr.unregisterBlockingUiCommandListener(mBlockingUiCommandListener);
167 
168         verify(mService).unregisterBlockingUiCommandListener(any());
169     }
170 
mockPackageName(String name)171     private void mockPackageName(String name) {
172         Context context = mock(Context.class);
173         when(context.getPackageName()).thenReturn(name);
174         when(mCar.getContext()).thenReturn(context);
175     }
176 }
177