/* * Copyright (C) 2023 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 android.adservices.ondevicepersonalization; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertThrows; import android.adservices.ondevicepersonalization.aidl.IDataAccessService; import android.adservices.ondevicepersonalization.aidl.IDataAccessServiceCallback; import android.content.ContentValues; import android.os.Bundle; import android.os.RemoteException; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.ondevicepersonalization.internal.util.OdpParceledListSlice; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.time.Instant; import java.util.ArrayList; import java.util.List; /** * Unit Tests of LogReader API. */ @SmallTest @RunWith(AndroidJUnit4.class) public class LogReaderTest { LogReader mLogReader; @Before public void setup() { mLogReader = new LogReader( IDataAccessService.Stub.asInterface( new LogReaderTest.LocalDataService())); } @Test public void testGetRequestsSuccess() { List result = mLogReader.getRequests( Instant.ofEpochMilli(10), Instant.ofEpochMilli(100)); assertEquals(2, result.size()); assertEquals(1, result.get(0).getRows().size()); assertEquals((int) (result.get(0).getRows().get(0).getAsInteger("a")), 1); assertEquals((int) (result.get(0).getRows().get(0).getAsInteger("b")), 1); assertEquals(1, result.get(1).getRows().size()); assertEquals((int) (result.get(1).getRows().get(0).getAsInteger("a")), 1); assertEquals((int) (result.get(1).getRows().get(0).getAsInteger("b")), 1); } @Test public void testGetRequestsNullTimeError() { assertThrows(NullPointerException.class, () -> mLogReader.getRequests( null, Instant.ofEpochMilli(100))); assertThrows(NullPointerException.class, () -> mLogReader.getRequests( Instant.ofEpochMilli(100), null)); } @Test public void testGetRequestsError() { // Triggers an expected error in the mock service. assertThrows(IllegalStateException.class, () -> mLogReader.getRequests( Instant.ofEpochMilli(7), Instant.ofEpochMilli(100))); } @Test public void testGetRequestsNegativeTimeError() { assertThrows(IllegalArgumentException.class, () -> mLogReader.getRequests( Instant.ofEpochMilli(-1), Instant.ofEpochMilli(100))); } @Test public void testGetRequestsBadTimeRangeError() { assertThrows(IllegalArgumentException.class, () -> mLogReader.getRequests( Instant.ofEpochMilli(100), Instant.ofEpochMilli(100))); assertThrows(IllegalArgumentException.class, () -> mLogReader.getRequests( Instant.ofEpochMilli(1000), Instant.ofEpochMilli(100))); } @Test public void testGetJoinedEventsSuccess() { List result = mLogReader.getJoinedEvents( Instant.ofEpochMilli(10), Instant.ofEpochMilli(100)); assertEquals(2, result.size()); assertEquals(result.get(0).getTimeMillis(), 30); assertEquals(result.get(0).getRequestLogRecord().getTimeMillis(), 20); assertEquals(result.get(0).getType(), 1); assertEquals((int) (result.get(0).getData().getAsInteger("a")), 1); assertEquals((int) (result.get(0).getData().getAsInteger("b")), 1); assertEquals(result.get(1).getTimeMillis(), 40); assertEquals(result.get(1).getRequestLogRecord().getTimeMillis(), 30); assertEquals(result.get(1).getType(), 2); assertEquals((int) (result.get(1).getData().getAsInteger("a")), 1); assertEquals((int) (result.get(1).getData().getAsInteger("b")), 1); } @Test public void testGetJoinedEventsError() { // Triggers an expected error in the mock service. assertThrows(IllegalStateException.class, () -> mLogReader.getJoinedEvents( Instant.ofEpochMilli(7), Instant.ofEpochMilli(100))); } @Test public void testGetJoinedEventsNullTimeError() { assertThrows(NullPointerException.class, () -> mLogReader.getJoinedEvents( null, Instant.ofEpochMilli(100))); assertThrows(NullPointerException.class, () -> mLogReader.getJoinedEvents( Instant.ofEpochMilli(100), null)); } @Test public void testGetJoinedEventsNegativeTimeError() { assertThrows(IllegalArgumentException.class, () -> mLogReader.getJoinedEvents( Instant.ofEpochMilli(-1), Instant.ofEpochMilli(100))); } @Test public void testGetJoinedEventsInputError() { assertThrows(IllegalArgumentException.class, () -> mLogReader.getJoinedEvents( Instant.ofEpochMilli(100), Instant.ofEpochMilli(100))); assertThrows(IllegalArgumentException.class, () -> mLogReader.getJoinedEvents( Instant.ofEpochMilli(1000), Instant.ofEpochMilli(100))); } public static class LocalDataService extends IDataAccessService.Stub { public LocalDataService() { } @Override public void onRequest( int operation, Bundle params, IDataAccessServiceCallback callback) { if (operation == Constants.DATA_ACCESS_OP_GET_REQUESTS || operation == Constants.DATA_ACCESS_OP_GET_JOINED_EVENTS) { long[] timestamps = params.getLongArray(Constants.EXTRA_LOOKUP_KEYS); if (timestamps[0] == 7) { // Raise expected error. try { callback.onError(Constants.STATUS_INTERNAL_ERROR); } catch (RemoteException e) { // Ignored. } return; } Bundle result = new Bundle(); ContentValues values = new ContentValues(); values.put("a", 1); values.put("b", 1); if (operation == Constants.DATA_ACCESS_OP_GET_REQUESTS) { List records = new ArrayList<>(); records.add(new RequestLogRecord.Builder() .setRequestId(1) .addRow(values) .build()); records.add(new RequestLogRecord.Builder() .setRequestId(2) .addRow(values) .build()); result.putParcelable(Constants.EXTRA_RESULT, new OdpParceledListSlice(records)); } else if (operation == Constants.DATA_ACCESS_OP_GET_JOINED_EVENTS) { List records = new ArrayList<>(); records.add(new EventLogRecord.Builder() .setType(1) .setTimeMillis(30) .setData(values) .setRequestLogRecord(new RequestLogRecord.Builder() .setRequestId(0) .addRow(values) .setTimeMillis(20) .build()) .build()); records.add(new EventLogRecord.Builder() .setType(2) .setTimeMillis(40) .setData(values) .setRequestLogRecord(new RequestLogRecord.Builder() .setRequestId(0) .addRow(values) .setTimeMillis(30) .build()) .build()); result.putParcelable(Constants.EXTRA_RESULT, new OdpParceledListSlice(records)); } try { callback.onSuccess(result); } catch (RemoteException e) { // Ignored. } } } @Override public void logApiCallStats(int apiName, long latencyMillis, int responseCode) {} } }