blob: 76ed9b07a914af6b9c05df56af9d4e47b82fa4e9 [file] [log] [blame]
/*
* 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 com.android.adservices.service.adselection;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.adservices.common.AdFilters;
import android.adservices.common.AdTechIdentifier;
import android.adservices.common.AppInstallFilters;
import android.adservices.common.CommonFixture;
import android.util.Pair;
import com.android.adservices.common.DBAdDataFixture;
import com.android.adservices.customaudience.DBCustomAudienceFixture;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.common.DBAdData;
import com.android.adservices.data.customaudience.DBCustomAudience;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@RunWith(MockitoJUnitRunner.class)
public class AdFiltererImplTest {
private static final String PACKAGE_NAME_TO_FILTER =
CommonFixture.TEST_PACKAGE_NAME_1 + ".filter";
private static final AppInstallFilters APP_INSTALL_FILTERS_TO_FILTER =
new AppInstallFilters.Builder()
.setPackageNames(new HashSet<>(Arrays.asList(PACKAGE_NAME_TO_FILTER)))
.build();
private static final DBAdData AD_TO_FILTER =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder()
.setAppInstallFilters(APP_INSTALL_FILTERS_TO_FILTER)
.build())
.build();
@Mock private AppInstallDao mAppInstallDaoMock;
private AdFilterer mAdFilterer;
@Before
public void setup() {
mAdFilterer = new AdFiltererImpl(mAppInstallDaoMock);
}
@Test
public void testFilterNullAdFilters() {
DBAdData dbAdData = DBAdDataFixture.getValidDbAdDataBuilder().setAdFilters(null).build();
List<DBAdData> inputList = Arrays.asList(dbAdData);
assertEquals(
inputList, mAdFilterer.filterContextualAds(inputList, CommonFixture.VALID_BUYER_1));
verifyNoMoreInteractions(mAppInstallDaoMock);
}
@Test
public void testFilterNullComponentFilters() {
DBAdData dbAdData =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder()
.setAppInstallFilters(null)
.setFrequencyCapFilters(null)
.build())
.build();
List<DBAdData> inputList = Arrays.asList(dbAdData);
assertEquals(
inputList, mAdFilterer.filterContextualAds(inputList, CommonFixture.VALID_BUYER_1));
verifyNoMoreInteractions(mAppInstallDaoMock);
}
@Test
public void testAppNotInstalled() {
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), any())).thenReturn(false);
AppInstallFilters appFilters =
new AppInstallFilters.Builder()
.setPackageNames(Collections.singleton(CommonFixture.TEST_PACKAGE_NAME_1))
.build();
DBAdData dbAdData =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder().setAppInstallFilters(appFilters).build())
.build();
List<DBAdData> inputList = Arrays.asList(dbAdData);
assertEquals(
inputList, mAdFilterer.filterContextualAds(inputList, CommonFixture.VALID_BUYER_1));
verify(mAppInstallDaoMock)
.canBuyerFilterPackage(
CommonFixture.VALID_BUYER_1, CommonFixture.TEST_PACKAGE_NAME_1);
}
@Test
public void testAppInstalled() {
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), any())).thenReturn(true);
AppInstallFilters appFilters =
new AppInstallFilters.Builder()
.setPackageNames(Collections.singleton(CommonFixture.TEST_PACKAGE_NAME_1))
.build();
DBAdData dbAdData =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder().setAppInstallFilters(appFilters).build())
.build();
List<DBAdData> inputList = Arrays.asList(dbAdData);
assertEquals(
Collections.EMPTY_LIST,
mAdFilterer.filterContextualAds(inputList, CommonFixture.VALID_BUYER_1));
verify(mAppInstallDaoMock)
.canBuyerFilterPackage(
CommonFixture.VALID_BUYER_1, CommonFixture.TEST_PACKAGE_NAME_1);
}
@Test
public void testMixedApps() {
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), eq(CommonFixture.TEST_PACKAGE_NAME_1)))
.thenReturn(true);
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), eq(CommonFixture.TEST_PACKAGE_NAME_2)))
.thenReturn(false);
AppInstallFilters appFilters =
new AppInstallFilters.Builder()
.setPackageNames(
new HashSet<>(
Arrays.asList(
CommonFixture.TEST_PACKAGE_NAME_1,
CommonFixture.TEST_PACKAGE_NAME_2)))
.build();
DBAdData dbAdData =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder().setAppInstallFilters(appFilters).build())
.build();
List<DBAdData> inputList = Arrays.asList(dbAdData);
assertEquals(
Collections.EMPTY_LIST,
mAdFilterer.filterContextualAds(inputList, CommonFixture.VALID_BUYER_1));
verify(mAppInstallDaoMock)
.canBuyerFilterPackage(
eq(CommonFixture.VALID_BUYER_1), eq(CommonFixture.TEST_PACKAGE_NAME_2));
}
@Test
public void testMixedAds() {
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), eq(CommonFixture.TEST_PACKAGE_NAME_1)))
.thenReturn(true);
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), eq(CommonFixture.TEST_PACKAGE_NAME_2)))
.thenReturn(false);
AppInstallFilters appFilters1 =
new AppInstallFilters.Builder()
.setPackageNames(
new HashSet<>(Arrays.asList(CommonFixture.TEST_PACKAGE_NAME_1)))
.build();
AppInstallFilters appFilters2 =
new AppInstallFilters.Builder()
.setPackageNames(
new HashSet<>(Arrays.asList(CommonFixture.TEST_PACKAGE_NAME_2)))
.build();
DBAdData dbAdData1 =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder().setAppInstallFilters(appFilters1).build())
.build();
DBAdData dbAdData2 =
DBAdDataFixture.getValidDbAdDataBuilder()
.setAdFilters(
new AdFilters.Builder().setAppInstallFilters(appFilters2).build())
.build();
assertEquals(
Arrays.asList(dbAdData2),
mAdFilterer.filterContextualAds(
Arrays.asList(dbAdData1, dbAdData2), CommonFixture.VALID_BUYER_1));
verify(mAppInstallDaoMock)
.canBuyerFilterPackage(
eq(CommonFixture.VALID_BUYER_1), eq(CommonFixture.TEST_PACKAGE_NAME_1));
verify(mAppInstallDaoMock)
.canBuyerFilterPackage(
eq(CommonFixture.VALID_BUYER_1), eq(CommonFixture.TEST_PACKAGE_NAME_2));
}
@Test
public void testCasNothingFiltered() {
List<DBCustomAudience> caList =
DBCustomAudienceFixture.getListOfBuyersCustomAudiences(
Arrays.asList(CommonFixture.VALID_BUYER_1, CommonFixture.VALID_BUYER_2));
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), any())).thenReturn(false);
assertEquals(caList, mAdFilterer.filterCustomAudiences(caList));
validateAppInstallDBCalls(caList);
}
@Test
public void testCasOneAdFiltered() {
List<DBCustomAudience> caListWithoutFilterAd =
DBCustomAudienceFixture.getListOfBuyersCustomAudiences(
Arrays.asList(CommonFixture.VALID_BUYER_1, CommonFixture.VALID_BUYER_2));
List<DBCustomAudience> caListWithFilterAd =
DBCustomAudienceFixture.getListOfBuyersCustomAudiences(
Arrays.asList(CommonFixture.VALID_BUYER_1, CommonFixture.VALID_BUYER_2));
caListWithFilterAd.get(0).getAds().add(AD_TO_FILTER);
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), any())).thenReturn(false);
when(mAppInstallDaoMock.canBuyerFilterPackage(
CommonFixture.VALID_BUYER_1, PACKAGE_NAME_TO_FILTER))
.thenReturn(true);
assertEquals(caListWithoutFilterAd, mAdFilterer.filterCustomAudiences(caListWithFilterAd));
validateAppInstallDBCalls(caListWithFilterAd);
}
@Test
public void testWholeCaFiltered() {
List<DBCustomAudience> caListWithoutFilteredCa =
DBCustomAudienceFixture.getListOfBuyersCustomAudiences(
Arrays.asList(CommonFixture.VALID_BUYER_2));
List<DBCustomAudience> caListWithFilteredCa =
DBCustomAudienceFixture.getListOfBuyersCustomAudiences(
Arrays.asList(CommonFixture.VALID_BUYER_2));
DBCustomAudience caToFilter =
DBCustomAudienceFixture.getValidBuilderByBuyer(CommonFixture.VALID_BUYER_1)
.setAds(Arrays.asList(AD_TO_FILTER))
.build();
caListWithFilteredCa.add(caToFilter);
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), any())).thenReturn(false);
when(mAppInstallDaoMock.canBuyerFilterPackage(
CommonFixture.VALID_BUYER_1, PACKAGE_NAME_TO_FILTER))
.thenReturn(true);
assertEquals(
caListWithoutFilteredCa, mAdFilterer.filterCustomAudiences(caListWithFilteredCa));
validateAppInstallDBCalls(caListWithFilteredCa);
}
@Test
public void testAllCasFiltered() {
DBCustomAudience caToFilter =
DBCustomAudienceFixture.getValidBuilderByBuyer(CommonFixture.VALID_BUYER_1)
.setAds(Arrays.asList(AD_TO_FILTER))
.build();
when(mAppInstallDaoMock.canBuyerFilterPackage(any(), any())).thenReturn(false);
when(mAppInstallDaoMock.canBuyerFilterPackage(
CommonFixture.VALID_BUYER_1, PACKAGE_NAME_TO_FILTER))
.thenReturn(true);
assertEquals(
Collections.EMPTY_LIST,
mAdFilterer.filterCustomAudiences(Arrays.asList(caToFilter)));
validateAppInstallDBCalls(Arrays.asList(caToFilter));
}
private void validateAppInstallDBCalls(List<DBCustomAudience> caList) {
/* We want to validate that all the calls that should have been made were made, but we
* can't just use a captor and compare lists since we can't guarantee the order.
*/
Map<Pair<AdTechIdentifier, String>, Integer> calls = new HashMap<>();
for (DBCustomAudience ca : caList) {
for (DBAdData ad : ca.getAds()) {
AdFilters filters = ad.getAdFilters();
if (filters == null || filters.getAppInstallFilters() == null) {
continue;
}
if (filters.getAppInstallFilters()
.getPackageNames()
.contains(PACKAGE_NAME_TO_FILTER)) {
calls.merge(new Pair<>(ca.getBuyer(), PACKAGE_NAME_TO_FILTER), 1, Integer::sum);
continue;
}
for (String packageName : filters.getAppInstallFilters().getPackageNames()) {
calls.merge(new Pair<>(ca.getBuyer(), packageName), 1, Integer::sum);
}
}
}
for (Pair<AdTechIdentifier, String> call : calls.keySet()) {
verify(mAppInstallDaoMock, times(calls.get(call)))
.canBuyerFilterPackage(call.first, call.second);
}
}
}