1 /* 2 * Copyright (C) 2023 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 com.android.server.credentials; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.when; 23 24 import android.credentials.CredentialDescription; 25 import android.credentials.RegisterCredentialDescriptionRequest; 26 import android.service.credentials.CredentialEntry; 27 28 import androidx.test.filters.SmallTest; 29 import androidx.test.runner.AndroidJUnit4; 30 31 import org.junit.Before; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 35 import java.util.Collections; 36 import java.util.HashSet; 37 import java.util.List; 38 import java.util.Set; 39 import java.util.stream.Collectors; 40 41 /** 42 * Tests for CredentialDescriptionRegistry. 43 * 44 * atest FrameworksServicesTests:com.android.server.credentials.CredentialDescriptionRegistryTest 45 */ 46 @RunWith(AndroidJUnit4.class) 47 @SmallTest 48 public class CredentialDescriptionRegistryTest { 49 50 private static final int USER_ID_1 = 1; 51 private static final int USER_ID_2 = 2; 52 private static final String CALLING_PACKAGE_NAME = "com.credman.app"; 53 private static final String CALLING_PACKAGE_NAME_2 = "com.credman.app2"; 54 private static final String MDOC_CREDENTIAL_TYPE = "MDOC"; 55 private static final String PASSKEY_CREDENTIAL_TYPE = "PASSKEY"; 56 private static final HashSet<String> FLATTENED_REGISTRY = new HashSet<>(List.of( 57 "FLATTENED_REQ", "FLATTENED_REQ123", "FLATTENED_REQa")); 58 private static final HashSet<String> FLATTENED_REGISTRY_2 = 59 new HashSet<>(List.of("FLATTENED_REQ_2")); 60 private static final HashSet<String> FLATTENED_REQUEST = 61 new HashSet<>(List.of("FLATTENED_REQ;FLATTENED_REQ123")); 62 63 private CredentialDescriptionRegistry mCredentialDescriptionRegistry; 64 private CredentialEntry mEntry; 65 private CredentialEntry mEntry2; 66 private CredentialEntry mEntry3; 67 68 @SuppressWarnings("GuardedBy") 69 @Before setUp()70 public void setUp() { 71 CredentialDescriptionRegistry.clearAllSessions(); 72 mEntry = mock(CredentialEntry.class); 73 mEntry2 = mock(CredentialEntry.class); 74 mEntry3 = mock(CredentialEntry.class); 75 when(mEntry.getType()).thenReturn(MDOC_CREDENTIAL_TYPE); 76 when(mEntry2.getType()).thenReturn(MDOC_CREDENTIAL_TYPE); 77 when(mEntry3.getType()).thenReturn(PASSKEY_CREDENTIAL_TYPE); 78 mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(USER_ID_1); 79 } 80 81 @SuppressWarnings("GuardedBy") 82 @Test testForUser_createsUniqueInstanceForEachUserID()83 public void testForUser_createsUniqueInstanceForEachUserID() { 84 final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry 85 .forUser(USER_ID_2); 86 87 assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry); 88 } 89 90 @SuppressWarnings("GuardedBy") 91 @Test testForUser_returnsSameInstanceForSameUserID()92 public void testForUser_returnsSameInstanceForSameUserID() { 93 final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry 94 .forUser(USER_ID_1); 95 96 assertThat(mCredentialDescriptionRegistry).isSameInstanceAs(secondRegistry); 97 } 98 99 @SuppressWarnings("GuardedBy") 100 @Test testClearUserSession_removesExistingSessionForUserID()101 public void testClearUserSession_removesExistingSessionForUserID() { 102 CredentialDescriptionRegistry.clearUserSession(USER_ID_1); 103 final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry 104 .forUser(USER_ID_1); 105 106 assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry); 107 } 108 109 @Test testEvictProvider_existingProviders_succeeds()110 public void testEvictProvider_existingProviders_succeeds() { 111 final CredentialDescription credentialDescription = 112 new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY, 113 Collections.emptyList()); 114 final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest = 115 new RegisterCredentialDescriptionRequest(credentialDescription); 116 final CredentialDescription credentialDescription2 = 117 new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY_2, 118 Collections.emptyList()); 119 final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 = 120 new RegisterCredentialDescriptionRequest(credentialDescription2); 121 122 123 mCredentialDescriptionRegistry 124 .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME); 125 mCredentialDescriptionRegistry 126 .executeRegisterRequest(registerCredentialDescriptionRequest2, 127 CALLING_PACKAGE_NAME); 128 mCredentialDescriptionRegistry.evictProviderWithPackageName(CALLING_PACKAGE_NAME); 129 Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry 130 .getMatchingProviders(Set.of(FLATTENED_REQUEST)); 131 132 assertThat(providers).isEmpty(); 133 } 134 135 @Test testGetMatchingProviders_existingProviders_succeeds()136 public void testGetMatchingProviders_existingProviders_succeeds() { 137 final CredentialDescription credentialDescription = 138 new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY, 139 Collections.emptyList()); 140 final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest = 141 new RegisterCredentialDescriptionRequest(credentialDescription); 142 final CredentialDescription credentialDescription2 = 143 new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY, 144 Collections.emptyList()); 145 final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 = 146 new RegisterCredentialDescriptionRequest(credentialDescription2); 147 148 149 mCredentialDescriptionRegistry 150 .executeRegisterRequest(registerCredentialDescriptionRequest, 151 CALLING_PACKAGE_NAME); 152 mCredentialDescriptionRegistry 153 .executeRegisterRequest(registerCredentialDescriptionRequest2, 154 CALLING_PACKAGE_NAME_2); 155 156 Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry 157 .getMatchingProviders(Set.of(FLATTENED_REQUEST)); 158 Set<String> packageNames = providers.stream().map( 159 filterResult -> filterResult.mPackageName).collect(Collectors.toSet()); 160 161 assertThat(providers).hasSize(2); 162 assertThat(packageNames).contains(CALLING_PACKAGE_NAME); 163 assertThat(packageNames).contains(CALLING_PACKAGE_NAME_2); 164 } 165 166 @Test testExecuteRegisterRequest_noProviders_filterSucceedsWithNoResults()167 public void testExecuteRegisterRequest_noProviders_filterSucceedsWithNoResults() { 168 List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry 169 .getFilteredResultForProvider(CALLING_PACKAGE_NAME, 170 FLATTENED_REQUEST).stream().toList(); 171 172 assertThat(results).isEmpty(); 173 } 174 175 @Test testExecuteRegisterRequest_existingProviders_filterSucceeds()176 public void testExecuteRegisterRequest_existingProviders_filterSucceeds() { 177 final CredentialDescription credentialDescription = 178 new CredentialDescription(MDOC_CREDENTIAL_TYPE, 179 FLATTENED_REGISTRY, 180 List.of(mEntry, mEntry2)); 181 final CredentialDescription credentialDescription2 = 182 new CredentialDescription(PASSKEY_CREDENTIAL_TYPE, 183 FLATTENED_REGISTRY_2, 184 List.of(mEntry3)); 185 final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest = 186 new RegisterCredentialDescriptionRequest(Set.of(credentialDescription, 187 credentialDescription2)); 188 189 mCredentialDescriptionRegistry 190 .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME); 191 192 List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry 193 .getFilteredResultForProvider(CALLING_PACKAGE_NAME, FLATTENED_REQUEST) 194 .stream().toList(); 195 196 assertThat(results).hasSize(1); 197 assertThat(results.get(0).mCredentialEntries).hasSize(2); 198 assertThat(results.get(0).mCredentialEntries.get(0)).isSameInstanceAs(mEntry); 199 assertThat(results.get(0).mCredentialEntries.get(1)).isSameInstanceAs(mEntry2); 200 } 201 202 } 203