1 /* 2 * Copyright (C) 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 com.android.adservices.service.measurement; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotEquals; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertThrows; 24 25 import android.util.Pair; 26 27 import androidx.test.filters.SmallTest; 28 29 import org.json.JSONArray; 30 import org.json.JSONException; 31 import org.json.JSONObject; 32 import org.junit.Test; 33 34 import java.util.Collections; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Set; 39 40 /** Unit tests for {@link AttributionConfig} */ 41 @SmallTest 42 public final class AttributionConfigTest { 43 private static final String SOURCE_AD_TECH = "AdTech1-Ads"; 44 45 @Test testCreation()46 public void testCreation() throws Exception { 47 AttributionConfig attributionConfig = createExample(); 48 49 assertEquals("AdTech1-Ads", attributionConfig.getSourceAdtech()); 50 assertEquals(100L, attributionConfig.getSourcePriorityRange().first.longValue()); 51 assertEquals(1000L, attributionConfig.getSourcePriorityRange().second.longValue()); 52 List<FilterMap> sourceFilter = attributionConfig.getSourceFilters(); 53 assertEquals(1, sourceFilter.get(0).getAttributionFilterMap().get("campaign_type").size()); 54 assertEquals(1, sourceFilter.get(0).getAttributionFilterMap().get("source_type").size()); 55 List<FilterMap> sourceNotFilter = attributionConfig.getSourceNotFilters(); 56 assertEquals( 57 1, sourceNotFilter.get(0).getAttributionFilterMap().get("campaign_type").size()); 58 assertEquals(600000L, attributionConfig.getSourceExpiryOverride().longValue()); 59 assertEquals(99L, attributionConfig.getPriority().longValue()); 60 assertEquals(604800L, attributionConfig.getExpiry().longValue()); 61 List<FilterMap> filterData = attributionConfig.getFilterData(); 62 assertEquals(1, filterData.get(0).getAttributionFilterMap().get("campaign_type").size()); 63 assertEquals(100000L, attributionConfig.getPostInstallExclusivityWindow().longValue()); 64 } 65 66 @Test testDefaults()67 public void testDefaults() throws Exception { 68 AttributionConfig attributionConfig = 69 new AttributionConfig.Builder().setSourceAdtech("AdTech1-Ads").build(); 70 assertNotNull(attributionConfig.getSourceAdtech()); 71 assertNull(attributionConfig.getSourcePriorityRange()); 72 assertNull(attributionConfig.getSourceFilters()); 73 assertNull(attributionConfig.getSourceNotFilters()); 74 assertNull(attributionConfig.getSourceExpiryOverride()); 75 assertNull(attributionConfig.getPriority()); 76 assertNull(attributionConfig.getExpiry()); 77 assertNull(attributionConfig.getFilterData()); 78 assertNull(attributionConfig.getPostInstallExclusivityWindow()); 79 } 80 81 @Test testHashCode_equals()82 public void testHashCode_equals() throws Exception { 83 final AttributionConfig config1 = createExample(); 84 final AttributionConfig config2 = createExample(); 85 final Set<AttributionConfig> configSet1 = Set.of(config1); 86 final Set<AttributionConfig> configSet2 = Set.of(config2); 87 assertEquals(config1.hashCode(), config2.hashCode()); 88 assertEquals(config1, config2); 89 assertEquals(configSet1, configSet2); 90 } 91 92 @Test testHashCode_notEquals()93 public void testHashCode_notEquals() throws Exception { 94 final AttributionConfig config1 = createExample(); 95 96 Pair<Long, Long> sourcePriorityRange = new Pair<>(100L, 1000L); 97 98 Map<String, List<String>> sourceFiltersMap = new HashMap<>(); 99 sourceFiltersMap.put("campaign_type", Collections.singletonList("install")); 100 sourceFiltersMap.put("source_type", Collections.singletonList("navigation")); 101 FilterMap sourceFilters = 102 new FilterMap.Builder().setAttributionFilterMap(sourceFiltersMap).build(); 103 104 Map<String, List<String>> sourceNotFiltersMap = new HashMap<>(); 105 sourceNotFiltersMap.put("campaign_type", Collections.singletonList("product")); 106 FilterMap sourceNotFilters = 107 new FilterMap.Builder().setAttributionFilterMap(sourceNotFiltersMap).build(); 108 109 Map<String, List<String>> filterDataMap = new HashMap<>(); 110 filterDataMap.put("campaign_type", Collections.singletonList("install")); 111 FilterMap filterData = 112 new FilterMap.Builder().setAttributionFilterMap(filterDataMap).build(); 113 114 AttributionConfig config2 = 115 new AttributionConfig.Builder() 116 .setSourceAdtech("AdTech2-Ads") 117 .setSourcePriorityRange(sourcePriorityRange) 118 .setSourceFilters(List.of(sourceFilters)) 119 .setSourceNotFilters(List.of(sourceNotFilters)) 120 .setSourceExpiryOverride(600000L) 121 .setPriority(99L) 122 .setExpiry(604800L) 123 .setFilterData(List.of(filterData)) 124 .setPostInstallExclusivityWindow(100000L) 125 .build(); 126 127 final Set<AttributionConfig> configSet1 = Set.of(config1); 128 final Set<AttributionConfig> configSet2 = Set.of(config2); 129 assertNotEquals(config1.hashCode(), config2.hashCode()); 130 assertNotEquals(config1, config2); 131 assertNotEquals(configSet1, configSet2); 132 } 133 134 @Test build_nonEmptyAttributionConfig_parseSuccess()135 public void build_nonEmptyAttributionConfig_parseSuccess() throws JSONException { 136 // Setup 137 AttributionConfig expected = createExampleAttributionConfig(); 138 139 // Action 140 AttributionConfig actual = 141 new AttributionConfig.Builder(createExampleAttributionConfigJson()).build(); 142 143 // Assertion 144 assertEquals(expected, actual); 145 } 146 147 @Test build_missingSourceAdTech_throwsJsonException()148 public void build_missingSourceAdTech_throwsJsonException() throws JSONException { 149 // Setup 150 JSONObject attributionConfigJson = createExampleAttributionConfigJson(); 151 attributionConfigJson.remove(AttributionConfig.AttributionConfigContract.SOURCE_NETWORK); 152 153 // Assertion 154 assertThrows( 155 JSONException.class, 156 () -> new AttributionConfig.Builder(attributionConfigJson).build()); 157 } 158 159 @Test build_withOnlySourceAdTechField_success()160 public void build_withOnlySourceAdTechField_success() throws JSONException { 161 // Setup 162 JSONObject attributionConfigJson = new JSONObject(); 163 attributionConfigJson.put("source_network", SOURCE_AD_TECH); 164 165 // Assertion 166 assertEquals( 167 new AttributionConfig.Builder().setSourceAdtech(SOURCE_AD_TECH).build(), 168 new AttributionConfig.Builder(attributionConfigJson).build()); 169 } 170 171 @Test serializeAsJson_success()172 public void serializeAsJson_success() throws JSONException { 173 // Setup 174 AttributionConfig attributionConfig = createExample(); 175 176 // Assertion 177 assertEquals( 178 attributionConfig, 179 new AttributionConfig.Builder(attributionConfig.serializeAsJson()).build()); 180 } 181 createExampleAttributionConfigJson()182 private JSONObject createExampleAttributionConfigJson() throws JSONException { 183 JSONObject attributionConfig = new JSONObject(); 184 attributionConfig.put("source_network", SOURCE_AD_TECH); 185 JSONObject sourcePriorityRangeJson = new JSONObject(); 186 sourcePriorityRangeJson.put("start", 100L); 187 sourcePriorityRangeJson.put("end", 1000L); 188 attributionConfig.put("source_priority_range", sourcePriorityRangeJson); 189 JSONObject sourceFiltersJson = new JSONObject(); 190 sourceFiltersJson.put( 191 "source_type", new JSONArray(Collections.singletonList("navigation"))); 192 JSONArray sourceFilterSet = new JSONArray(); 193 sourceFilterSet.put(sourceFiltersJson); 194 attributionConfig.put("source_filters", sourceFilterSet); 195 JSONObject sourceNotFiltersJson = new JSONObject(); 196 sourceNotFiltersJson.put( 197 "campaign_type", new JSONArray(Collections.singletonList("product"))); 198 JSONArray sourceNotFilterSet = new JSONArray(); 199 sourceNotFilterSet.put(sourceNotFiltersJson); 200 attributionConfig.put("source_not_filters", sourceNotFilterSet); 201 attributionConfig.put("source_expiry_override", 600000L); 202 attributionConfig.put("priority", 99L); 203 attributionConfig.put("expiry", 604800L); 204 JSONObject filterDataJson = new JSONObject(); 205 filterDataJson.put("campaign_type", new JSONArray(Collections.singletonList("install"))); 206 JSONArray filterDataSet = new JSONArray(); 207 filterDataSet.put(filterDataJson); 208 attributionConfig.put("filter_data", filterDataSet); 209 attributionConfig.put("post_install_exclusivity_window", 100000L); 210 return attributionConfig; 211 } 212 createExampleAttributionConfig()213 private AttributionConfig createExampleAttributionConfig() throws JSONException { 214 JSONObject sourceFiltersMap = new JSONObject(); 215 Pair<Long, Long> sourcePriorityRange = new Pair<>(100L, 1000L); 216 sourceFiltersMap.put("source_type", new JSONArray(Collections.singletonList("navigation"))); 217 FilterMap sourceFilters = new FilterMap.Builder().buildFilterData(sourceFiltersMap).build(); 218 219 JSONObject sourceNotFiltersMap = new JSONObject(); 220 sourceNotFiltersMap.put( 221 "campaign_type", new JSONArray(Collections.singletonList("product"))); 222 FilterMap sourceNotFilters = 223 new FilterMap.Builder().buildFilterData(sourceNotFiltersMap).build(); 224 225 JSONObject filterDataMap = new JSONObject(); 226 filterDataMap.put("campaign_type", new JSONArray(Collections.singletonList("install"))); 227 FilterMap filterData = new FilterMap.Builder().buildFilterData(filterDataMap).build(); 228 229 return new AttributionConfig.Builder() 230 .setSourceAdtech(SOURCE_AD_TECH) 231 .setSourcePriorityRange(sourcePriorityRange) 232 .setSourceFilters(List.of(sourceFilters)) 233 .setSourceNotFilters(List.of(sourceNotFilters)) 234 .setSourceExpiryOverride(600000L) 235 .setPriority(99L) 236 .setExpiry(604800L) 237 .setFilterData(List.of(filterData)) 238 .setPostInstallExclusivityWindow(100000L) 239 .build(); 240 } 241 createExample()242 private AttributionConfig createExample() { 243 Pair<Long, Long> sourcePriorityRange = new Pair<>(100L, 1000L); 244 245 Map<String, List<String>> sourceFiltersMap = new HashMap<>(); 246 sourceFiltersMap.put("campaign_type", Collections.singletonList("install")); 247 sourceFiltersMap.put("source_type", Collections.singletonList("navigation")); 248 FilterMap sourceFilters = 249 new FilterMap.Builder().setAttributionFilterMap(sourceFiltersMap).build(); 250 251 Map<String, List<String>> sourceNotFiltersMap = new HashMap<>(); 252 sourceNotFiltersMap.put("campaign_type", Collections.singletonList("product")); 253 FilterMap sourceNotFilters = 254 new FilterMap.Builder().setAttributionFilterMap(sourceNotFiltersMap).build(); 255 256 Map<String, List<String>> filterDataMap = new HashMap<>(); 257 filterDataMap.put("campaign_type", Collections.singletonList("install")); 258 FilterMap filterData = 259 new FilterMap.Builder().setAttributionFilterMap(filterDataMap).build(); 260 261 return new AttributionConfig.Builder() 262 .setSourceAdtech(SOURCE_AD_TECH) 263 .setSourcePriorityRange(sourcePriorityRange) 264 .setSourceFilters(List.of(sourceFilters)) 265 .setSourceNotFilters(List.of(sourceNotFilters)) 266 .setSourceExpiryOverride(600000L) 267 .setPriority(99L) 268 .setExpiry(604800L) 269 .setFilterData(List.of(filterData)) 270 .setPostInstallExclusivityWindow(100000L) 271 .build(); 272 } 273 } 274