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.reporting; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.net.Uri; 24 import android.util.Pair; 25 26 import com.android.adservices.service.measurement.util.UnsignedLong; 27 28 import org.json.JSONArray; 29 import org.json.JSONException; 30 import org.json.JSONObject; 31 import org.junit.Test; 32 33 import java.util.Collections; 34 import java.util.List; 35 36 public class EventReportPayloadTest { 37 38 private static final List<Uri> ATTRIBUTION_DESTINATIONS = 39 List.of(Uri.parse("https://toasters.example")); 40 private static final Uri DESTINATION_1 = Uri.parse("https://destination1.test"); 41 private static final Uri DESTINATION_2 = Uri.parse("https://destination2.test"); 42 private static final String SCHEDULED_REPORT_TIME = "1675459163"; 43 private static final UnsignedLong SOURCE_EVENT_ID = new UnsignedLong(12345L); 44 private static final UnsignedLong TRIGGER_DATA = new UnsignedLong(2L); 45 private static final String REPORT_ID = "678"; 46 private static final String SOURCE_TYPE = "event"; 47 private static final double RANDOMIZED_TRIGGER_RATE = 0.0024; 48 private static final UnsignedLong SOURCE_DEBUG_KEY = new UnsignedLong(3894783L); 49 private static final UnsignedLong TRIGGER_DEBUG_KEY = new UnsignedLong(2387222L); 50 private static final Pair<Long, Long> TRIGGER_SUMMARY_BUCKET = Pair.create(5L, 37L); 51 private static final List<UnsignedLong> TRIGGER_DEBUG_KEYS = List.of( 52 new UnsignedLong(2387222L), new UnsignedLong("9223372036854775809")); 53 createEventReportPayload( UnsignedLong triggerData, List<UnsignedLong> triggerDebugKeys)54 private static EventReportPayload createEventReportPayload( 55 UnsignedLong triggerData, 56 List<UnsignedLong> triggerDebugKeys) { 57 return createEventReportPayload( 58 triggerData, 59 null, 60 null, 61 triggerDebugKeys, 62 ATTRIBUTION_DESTINATIONS); 63 } 64 createEventReportPayload( UnsignedLong triggerData, UnsignedLong sourceDebugKey, UnsignedLong triggerDebugKey)65 private static EventReportPayload createEventReportPayload( 66 UnsignedLong triggerData, 67 UnsignedLong sourceDebugKey, 68 UnsignedLong triggerDebugKey) { 69 return createEventReportPayload( 70 triggerData, 71 sourceDebugKey, 72 triggerDebugKey, 73 Collections.emptyList(), 74 ATTRIBUTION_DESTINATIONS); 75 } 76 createEventReportPayload( UnsignedLong triggerData, UnsignedLong sourceDebugKey, UnsignedLong triggerDebugKey, List<Uri> attributionDestinations)77 private static EventReportPayload createEventReportPayload( 78 UnsignedLong triggerData, 79 UnsignedLong sourceDebugKey, 80 UnsignedLong triggerDebugKey, 81 List<Uri> attributionDestinations) { 82 return createEventReportPayload( 83 triggerData, 84 sourceDebugKey, 85 triggerDebugKey, 86 Collections.emptyList(), 87 attributionDestinations); 88 } 89 createEventReportPayloadBuilder( UnsignedLong triggerData, UnsignedLong sourceDebugKey, UnsignedLong triggerDebugKey, List<UnsignedLong> triggerDebugKeys, List<Uri> destinations)90 private static EventReportPayload.Builder createEventReportPayloadBuilder( 91 UnsignedLong triggerData, 92 UnsignedLong sourceDebugKey, 93 UnsignedLong triggerDebugKey, 94 List<UnsignedLong> triggerDebugKeys, 95 List<Uri> destinations) { 96 return new EventReportPayload.Builder() 97 .setAttributionDestination(destinations) 98 .setScheduledReportTime(SCHEDULED_REPORT_TIME) 99 .setSourceEventId(SOURCE_EVENT_ID) 100 .setTriggerData(triggerData) 101 .setReportId(REPORT_ID) 102 .setSourceType(SOURCE_TYPE) 103 .setRandomizedTriggerRate(RANDOMIZED_TRIGGER_RATE) 104 .setSourceDebugKey(sourceDebugKey) 105 .setTriggerDebugKey(triggerDebugKey) 106 .setTriggerDebugKeys(triggerDebugKeys); 107 } 108 createEventReportPayload( UnsignedLong triggerData, UnsignedLong sourceDebugKey, UnsignedLong triggerDebugKey, List<UnsignedLong> triggerDebugKeys, List<Uri> destinations)109 private static EventReportPayload createEventReportPayload( 110 UnsignedLong triggerData, 111 UnsignedLong sourceDebugKey, 112 UnsignedLong triggerDebugKey, 113 List<UnsignedLong> triggerDebugKeys, 114 List<Uri> destinations) { 115 return createEventReportPayloadBuilder( 116 triggerData, 117 sourceDebugKey, 118 triggerDebugKey, 119 triggerDebugKeys, 120 destinations) 121 .build(); 122 } 123 124 @Test toJson_success()125 public void toJson_success() throws JSONException { 126 EventReportPayload eventReport = 127 createEventReportPayloadBuilder( 128 TRIGGER_DATA, 129 SOURCE_DEBUG_KEY, 130 TRIGGER_DEBUG_KEY, 131 TRIGGER_DEBUG_KEYS, 132 ATTRIBUTION_DESTINATIONS) 133 .setTriggerSummaryBucket(TRIGGER_SUMMARY_BUCKET) 134 .build(); 135 136 JSONObject eventPayloadReportJson = eventReport.toJson(); 137 138 Object destinationsObj = eventPayloadReportJson.get("attribution_destination"); 139 assertTrue(destinationsObj instanceof String); 140 assertEquals(ATTRIBUTION_DESTINATIONS.get(0).toString(), (String) destinationsObj); 141 assertEquals(SCHEDULED_REPORT_TIME, eventPayloadReportJson.get("scheduled_report_time")); 142 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 143 assertEquals(TRIGGER_DATA.toString(), eventPayloadReportJson.get("trigger_data")); 144 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 145 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 146 assertEquals(RANDOMIZED_TRIGGER_RATE, 147 eventPayloadReportJson.get("randomized_trigger_rate")); 148 assertEquals(SOURCE_DEBUG_KEY.toString(), eventPayloadReportJson.get("source_debug_key")); 149 assertEquals(TRIGGER_DEBUG_KEY.toString(), eventPayloadReportJson.get("trigger_debug_key")); 150 Object triggerDebugKeysObj = eventPayloadReportJson.get("trigger_debug_keys"); 151 assertTrue(triggerDebugKeysObj instanceof JSONArray); 152 assertEquals(TRIGGER_DEBUG_KEYS.get(0).toString(), 153 ((JSONArray) triggerDebugKeysObj).getString(0)); 154 assertEquals(TRIGGER_DEBUG_KEYS.get(1).toString(), 155 ((JSONArray) triggerDebugKeysObj).getString(1)); 156 // Trigger summary bucket 157 assertTrue(eventPayloadReportJson.get("trigger_summary_bucket") instanceof JSONArray); 158 JSONArray triggerSummaryBucket = 159 eventPayloadReportJson.getJSONArray("trigger_summary_bucket"); 160 Object first = triggerSummaryBucket.get(0); 161 assertTrue(first instanceof Number); 162 assertEquals(TRIGGER_SUMMARY_BUCKET.first, Long.valueOf((long) first)); 163 Object second = triggerSummaryBucket.get(1); 164 assertTrue(second instanceof Number); 165 assertEquals(TRIGGER_SUMMARY_BUCKET.second, Long.valueOf((long) second)); 166 } 167 168 @Test toJson_multipleAttributionDestinations_setsDestinationsAsOrderedJSONArray()169 public void toJson_multipleAttributionDestinations_setsDestinationsAsOrderedJSONArray() 170 throws JSONException { 171 EventReportPayload eventReport = createEventReportPayload( 172 TRIGGER_DATA, null, null, List.of(DESTINATION_2, DESTINATION_1)); 173 JSONObject eventPayloadReportJson = eventReport.toJson(); 174 175 Object obj = eventPayloadReportJson.get("attribution_destination"); 176 assertTrue(obj instanceof JSONArray); 177 assertEquals(DESTINATION_1.toString(), ((JSONArray) obj).getString(0)); 178 assertEquals(DESTINATION_2.toString(), ((JSONArray) obj).getString(1)); 179 assertEquals(SCHEDULED_REPORT_TIME, eventPayloadReportJson.get("scheduled_report_time")); 180 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 181 assertEquals(TRIGGER_DATA.toString(), eventPayloadReportJson.get("trigger_data")); 182 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 183 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 184 assertEquals(RANDOMIZED_TRIGGER_RATE, 185 eventPayloadReportJson.get("randomized_trigger_rate")); 186 } 187 188 @Test testEventPayloadJsonSerializationWithNullDebugKeys()189 public void testEventPayloadJsonSerializationWithNullDebugKeys() throws JSONException { 190 EventReportPayload eventReport = createEventReportPayload(TRIGGER_DATA, null, null); 191 JSONObject eventPayloadReportJson = eventReport.toJson(); 192 193 assertEquals( 194 ATTRIBUTION_DESTINATIONS.get(0).toString(), 195 eventPayloadReportJson.get("attribution_destination")); 196 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 197 assertEquals(TRIGGER_DATA.toString(), eventPayloadReportJson.get("trigger_data")); 198 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 199 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 200 assertEquals( 201 RANDOMIZED_TRIGGER_RATE, eventPayloadReportJson.get("randomized_trigger_rate")); 202 assertNull(eventPayloadReportJson.opt("source_debug_key")); 203 assertNull(eventPayloadReportJson.opt("trigger_debug_key")); 204 assertNull(eventPayloadReportJson.opt("trigger_debug_keys")); 205 } 206 207 @Test testEventPayloadJsonSerializationWithNullTriggerData()208 public void testEventPayloadJsonSerializationWithNullTriggerData() throws JSONException { 209 EventReportPayload eventReport = createEventReportPayload(null, null, null); 210 JSONObject eventPayloadReportJson = eventReport.toJson(); 211 212 assertEquals( 213 ATTRIBUTION_DESTINATIONS.get(0).toString(), 214 eventPayloadReportJson.get("attribution_destination")); 215 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 216 assertEquals(new UnsignedLong(0L).toString(), eventPayloadReportJson.get("trigger_data")); 217 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 218 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 219 assertEquals( 220 RANDOMIZED_TRIGGER_RATE, eventPayloadReportJson.get("randomized_trigger_rate")); 221 assertNull(eventPayloadReportJson.opt("source_debug_key")); 222 assertNull(eventPayloadReportJson.opt("trigger_debug_key")); 223 } 224 225 @Test testEventPayloadJsonSerializationWithSingleTriggerDebugKey()226 public void testEventPayloadJsonSerializationWithSingleTriggerDebugKey() throws JSONException { 227 EventReportPayload eventReport = 228 createEventReportPayload(TRIGGER_DATA, null, TRIGGER_DEBUG_KEY); 229 JSONObject eventPayloadReportJson = eventReport.toJson(); 230 231 assertEquals( 232 ATTRIBUTION_DESTINATIONS.get(0).toString(), 233 eventPayloadReportJson.get("attribution_destination")); 234 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 235 assertEquals(TRIGGER_DATA.toString(), eventPayloadReportJson.get("trigger_data")); 236 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 237 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 238 assertEquals( 239 RANDOMIZED_TRIGGER_RATE, eventPayloadReportJson.get("randomized_trigger_rate")); 240 assertNull(eventPayloadReportJson.opt("source_debug_key")); 241 assertEquals(TRIGGER_DEBUG_KEY.toString(), eventPayloadReportJson.get("trigger_debug_key")); 242 } 243 244 @Test testEventPayloadJsonSerializationWithMultipleTriggerDebugKeys()245 public void testEventPayloadJsonSerializationWithMultipleTriggerDebugKeys() 246 throws JSONException { 247 EventReportPayload eventReport = 248 createEventReportPayload(TRIGGER_DATA, TRIGGER_DEBUG_KEYS); 249 JSONObject eventPayloadReportJson = eventReport.toJson(); 250 251 assertEquals( 252 ATTRIBUTION_DESTINATIONS.get(0).toString(), 253 eventPayloadReportJson.get("attribution_destination")); 254 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 255 assertEquals(TRIGGER_DATA.toString(), eventPayloadReportJson.get("trigger_data")); 256 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 257 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 258 assertEquals( 259 RANDOMIZED_TRIGGER_RATE, eventPayloadReportJson.get("randomized_trigger_rate")); 260 assertNull(eventPayloadReportJson.opt("source_debug_key")); 261 assertNull(eventPayloadReportJson.opt("trigger_debug_key")); 262 Object triggerDebugKeysObj = eventPayloadReportJson.get("trigger_debug_keys"); 263 assertTrue(triggerDebugKeysObj instanceof JSONArray); 264 assertEquals(TRIGGER_DEBUG_KEYS.get(0).toString(), 265 ((JSONArray) triggerDebugKeysObj).getString(0)); 266 assertEquals(TRIGGER_DEBUG_KEYS.get(1).toString(), 267 ((JSONArray) triggerDebugKeysObj).getString(1)); 268 } 269 270 @Test testEventPayloadJsonSerialization_debugKeysSourceEventIdAndTriggerDataUse64thBit()271 public void testEventPayloadJsonSerialization_debugKeysSourceEventIdAndTriggerDataUse64thBit() 272 throws JSONException { 273 String unsigned64BitIntString = "18446744073709551615"; 274 UnsignedLong signed64BitInt = new UnsignedLong(-1L); 275 EventReportPayload eventReport = new EventReportPayload.Builder() 276 .setAttributionDestination(ATTRIBUTION_DESTINATIONS) 277 .setSourceEventId(signed64BitInt) 278 .setTriggerData(signed64BitInt) 279 .setReportId(REPORT_ID) 280 .setSourceType(SOURCE_TYPE) 281 .setRandomizedTriggerRate(RANDOMIZED_TRIGGER_RATE) 282 .setSourceDebugKey(signed64BitInt) 283 .setTriggerDebugKey(signed64BitInt) 284 .build(); 285 JSONObject eventPayloadReportJson = eventReport.toJson(); 286 287 assertEquals( 288 ATTRIBUTION_DESTINATIONS.get(0).toString(), 289 eventPayloadReportJson.get("attribution_destination")); 290 assertEquals(unsigned64BitIntString, eventPayloadReportJson.get("source_event_id")); 291 assertEquals(unsigned64BitIntString, eventPayloadReportJson.get("trigger_data")); 292 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 293 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 294 assertEquals( 295 RANDOMIZED_TRIGGER_RATE, eventPayloadReportJson.get("randomized_trigger_rate")); 296 assertEquals(unsigned64BitIntString, eventPayloadReportJson.opt("source_debug_key")); 297 assertEquals(unsigned64BitIntString, eventPayloadReportJson.get("trigger_debug_key")); 298 } 299 300 @Test testEventPayloadJsonSerializationWithSingleSourceDebugKey()301 public void testEventPayloadJsonSerializationWithSingleSourceDebugKey() throws JSONException { 302 EventReportPayload eventReport = 303 createEventReportPayload(TRIGGER_DATA, SOURCE_DEBUG_KEY, null); 304 JSONObject eventPayloadReportJson = eventReport.toJson(); 305 306 assertEquals( 307 ATTRIBUTION_DESTINATIONS.get(0).toString(), 308 eventPayloadReportJson.get("attribution_destination")); 309 assertEquals(SOURCE_EVENT_ID.toString(), eventPayloadReportJson.get("source_event_id")); 310 assertEquals(TRIGGER_DATA.toString(), eventPayloadReportJson.get("trigger_data")); 311 assertEquals(REPORT_ID, eventPayloadReportJson.get("report_id")); 312 assertEquals(SOURCE_TYPE, eventPayloadReportJson.get("source_type")); 313 assertEquals( 314 RANDOMIZED_TRIGGER_RATE, eventPayloadReportJson.get("randomized_trigger_rate")); 315 assertNull(eventPayloadReportJson.opt("trigger_debug_key")); 316 assertEquals(SOURCE_DEBUG_KEY.toString(), eventPayloadReportJson.get("source_debug_key")); 317 } 318 } 319