1 /* 2 * Copyright (C) 2024 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 17 package android.health.connect; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.Mockito.when; 24 25 import android.content.Context; 26 import android.health.connect.aidl.IHealthConnectService; 27 import android.health.connect.datatypes.MedicalResource; 28 import android.os.OutcomeReceiver; 29 import android.os.RemoteException; 30 31 import androidx.test.core.app.ApplicationProvider; 32 33 import com.google.common.collect.ImmutableList; 34 import com.google.common.util.concurrent.MoreExecutors; 35 36 import org.junit.Rule; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.junit.runners.JUnit4; 40 import org.mockito.Mock; 41 import org.mockito.junit.MockitoJUnit; 42 import org.mockito.junit.MockitoRule; 43 44 import java.lang.reflect.InvocationTargetException; 45 import java.util.List; 46 import java.util.concurrent.Executor; 47 48 @RunWith(JUnit4.class) 49 public class HealthConnectManagerTest { 50 51 @Rule public final MockitoRule mockito = MockitoJUnit.rule(); 52 53 @Mock IHealthConnectService mService; 54 55 @Test testHealthConnectManager_getNoGrantedHealthPermissions_succeeds()56 public void testHealthConnectManager_getNoGrantedHealthPermissions_succeeds() throws Exception { 57 Context context = ApplicationProvider.getApplicationContext(); 58 HealthConnectManager healthConnectManager = newHealthConnectManager(context, mService); 59 60 List<String> grantedHealthPermissions = 61 healthConnectManager.getGrantedHealthPermissions("com.foo.bar"); 62 63 assertThat(grantedHealthPermissions).isEmpty(); 64 } 65 66 @Test testHealthConnectManager_getSomeGrantedHealthPermissions_succeeds()67 public void testHealthConnectManager_getSomeGrantedHealthPermissions_succeeds() 68 throws Exception { 69 Context context = ApplicationProvider.getApplicationContext(); 70 HealthConnectManager healthConnectManager = newHealthConnectManager(context, mService); 71 when(mService.getGrantedHealthPermissions(any(), any())) 72 .thenReturn( 73 ImmutableList.of( 74 "android.permission.health.READ_HEART_RATE", 75 "android.permission.health.WRITE_HEART_RATE")); 76 77 List<String> grantedHealthPermissions = 78 healthConnectManager.getGrantedHealthPermissions("com.foo.bar"); 79 80 assertThat(grantedHealthPermissions) 81 .containsExactly( 82 "android.permission.health.READ_HEART_RATE", 83 "android.permission.health.WRITE_HEART_RATE"); 84 } 85 86 @Test testHealthConnectManager_getGrantedHealthPermissionsException_rethrows()87 public void testHealthConnectManager_getGrantedHealthPermissionsException_rethrows() 88 throws Exception { 89 Context context = ApplicationProvider.getApplicationContext(); 90 HealthConnectManager healthConnectManager = newHealthConnectManager(context, mService); 91 when(mService.getGrantedHealthPermissions(any(), any())) 92 .thenThrow(new RemoteException("message")); 93 94 assertThrows( 95 RuntimeException.class, 96 () -> healthConnectManager.getGrantedHealthPermissions("com.foo.bar")); 97 } 98 99 @Test testHealthConnectManager_upsertMedicalResources_throws()100 public void testHealthConnectManager_upsertMedicalResources_throws() throws Exception { 101 Context context = ApplicationProvider.getApplicationContext(); 102 HealthConnectManager healthConnectManager = newHealthConnectManager(context, mService); 103 Executor executor = MoreExecutors.directExecutor(); 104 OutcomeReceiver<List<MedicalResource>, HealthConnectException> callback = result -> {}; 105 106 assertThrows( 107 UnsupportedOperationException.class, 108 () -> 109 healthConnectManager.upsertMedicalResources( 110 ImmutableList.of(), executor, callback)); 111 } 112 113 @Test testHealthConnectManager_deleteResources_notImplemented()114 public void testHealthConnectManager_deleteResources_notImplemented() throws Exception { 115 Context context = ApplicationProvider.getApplicationContext(); 116 HealthConnectManager healthConnectManager = newHealthConnectManager(context, mService); 117 Executor executor = MoreExecutors.directExecutor(); 118 OutcomeReceiver<Void, HealthConnectException> callback = 119 new OutcomeReceiver<>() { 120 @Override 121 public void onResult(Void result) {} 122 }; 123 assertThrows( 124 UnsupportedOperationException.class, 125 () -> 126 healthConnectManager.deleteMedicalResources( 127 ImmutableList.of(MedicalIdFilter.fromId("fictionalid")), 128 executor, 129 callback)); 130 } 131 132 /** 133 * Constructs a {@link HealthConnectManager} using reflection to access the constructor. 134 * 135 * <p>Unfortunately the {@link HealthConnectManager} loads from a different classloader to the 136 * unit test, so even though they are in the same package name, technically the packages are 137 * different. This leads to calling the constructor giving an {@link IllegalAccessError}. By 138 * using reflection we can avoid this error in test cases, but this code should not be used 139 * outside of testing. 140 */ newHealthConnectManager( Context context, IHealthConnectService service)141 private static HealthConnectManager newHealthConnectManager( 142 Context context, IHealthConnectService service) 143 throws InstantiationException, 144 IllegalAccessException, 145 InvocationTargetException, 146 NoSuchMethodException { 147 return HealthConnectManager.class 148 .getDeclaredConstructor(Context.class, IHealthConnectService.class) 149 .newInstance(context, service); 150 } 151 } 152