1 /* 2 * Copyright 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 17 package android.adservices.ondevicepersonalization; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertArrayEquals; 22 import static org.junit.Assert.assertNull; 23 24 import android.adservices.ondevicepersonalization.aidl.IDataAccessService; 25 import android.adservices.ondevicepersonalization.aidl.IDataAccessServiceCallback; 26 import android.os.Bundle; 27 import android.os.RemoteException; 28 29 import androidx.test.ext.junit.runners.AndroidJUnit4; 30 import androidx.test.filters.SmallTest; 31 32 import com.android.ondevicepersonalization.internal.util.ByteArrayParceledSlice; 33 34 import org.junit.Before; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 import java.util.HashMap; 39 import java.util.HashSet; 40 import java.util.Set; 41 import java.util.concurrent.CountDownLatch; 42 43 /** 44 * Unit Tests of RemoteData API. 45 */ 46 @SmallTest 47 @RunWith(AndroidJUnit4.class) 48 public class RemoteDataTest { 49 50 private KeyValueStore mRemoteData; 51 private RemoteDataService mRemoteDataService; 52 53 @Before setup()54 public void setup() { 55 mRemoteDataService = new RemoteDataService(); 56 mRemoteData = new RemoteDataImpl(IDataAccessService.Stub.asInterface(mRemoteDataService)); 57 } 58 59 @Test testLookupSuccess()60 public void testLookupSuccess() throws Exception { 61 assertArrayEquals(new byte[] {1, 2, 3}, mRemoteData.get("a")); 62 assertArrayEquals(new byte[] {7, 8, 9}, mRemoteData.get("c")); 63 assertNull(mRemoteData.get("e")); 64 65 mRemoteDataService.mLatch.await(); 66 assertThat(mRemoteDataService.mResponseCode).isEqualTo(Constants.STATUS_SUCCESS); 67 } 68 69 @Test testLookupError()70 public void testLookupError() throws Exception { 71 // Triggers an expected error in the mock service. 72 assertNull(mRemoteData.get("z")); 73 74 mRemoteDataService.mLatch.await(); 75 assertThat(mRemoteDataService.mResponseCode).isEqualTo(Constants.STATUS_SERVICE_FAILED); 76 } 77 78 @Test testLookupEmptyResult()79 public void testLookupEmptyResult() throws Exception { 80 // Triggers an expected error in the mock service. 81 assertNull(mRemoteData.get("empty")); 82 83 mRemoteDataService.mLatch.await(); 84 assertThat(mRemoteDataService.mResponseCode) 85 .isEqualTo(Constants.STATUS_SUCCESS_EMPTY_RESULT); 86 } 87 88 @Test testKeysetSuccess()89 public void testKeysetSuccess() throws Exception { 90 Set<String> expectedResult = new HashSet<>(); 91 expectedResult.add("a"); 92 expectedResult.add("b"); 93 expectedResult.add("c"); 94 95 assertThat(expectedResult).isEqualTo(mRemoteData.keySet()); 96 97 mRemoteDataService.mLatch.await(); 98 assertThat(mRemoteDataService.mResponseCode).isEqualTo(Constants.STATUS_SUCCESS); 99 } 100 101 public static class RemoteDataService extends IDataAccessService.Stub { 102 HashMap<String, byte[]> mContents = new HashMap<String, byte[]>(); 103 int mResponseCode; 104 CountDownLatch mLatch = new CountDownLatch(1); 105 RemoteDataService()106 public RemoteDataService() { 107 mContents.put("a", new byte[] {1, 2, 3}); 108 mContents.put("b", new byte[] {4, 5, 6}); 109 mContents.put("c", new byte[] {7, 8, 9}); 110 } 111 112 @Override onRequest( int operation, Bundle params, IDataAccessServiceCallback callback)113 public void onRequest( 114 int operation, 115 Bundle params, 116 IDataAccessServiceCallback callback) { 117 118 if (operation == Constants.DATA_ACCESS_OP_REMOTE_DATA_KEYSET) { 119 Bundle result = new Bundle(); 120 result.putSerializable(Constants.EXTRA_RESULT, 121 new HashSet<>(mContents.keySet())); 122 try { 123 callback.onSuccess(result); 124 } catch (RemoteException e) { 125 // Ignored. 126 } 127 return; 128 } 129 130 if (operation != Constants.DATA_ACCESS_OP_REMOTE_DATA_LOOKUP) { 131 throw new IllegalArgumentException("op: " + operation); 132 } 133 134 String key = params.getString(Constants.EXTRA_LOOKUP_KEYS); 135 if (key == null) { 136 throw new NullPointerException("key"); 137 } 138 if (key.equals("empty")) { 139 // Raise expected error. 140 try { 141 callback.onSuccess(null); 142 } catch (RemoteException e) { 143 // Ignored. 144 } 145 return; 146 } 147 148 if (key.equals("z")) { 149 // Raise expected error. 150 try { 151 callback.onError(Constants.STATUS_SERVICE_FAILED); 152 } catch (RemoteException e) { 153 // Ignored. 154 } 155 return; 156 } 157 byte[] value = null; 158 if (mContents.containsKey(key)) { 159 value = mContents.get(key); 160 } 161 Bundle result = new Bundle(); 162 result.putParcelable(Constants.EXTRA_RESULT, new ByteArrayParceledSlice(value)); 163 try { 164 callback.onSuccess(result); 165 } catch (RemoteException e) { 166 // Ignored. 167 } 168 } 169 170 @Override logApiCallStats(int apiName, long latencyMillis, int responseCode)171 public void logApiCallStats(int apiName, long latencyMillis, int responseCode) { 172 mLatch.countDown(); 173 mResponseCode = responseCode; 174 } 175 } 176 } 177