1 /* 2 * Copyright (C) 2023 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.debuggablects; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 23 import android.adservices.utils.MockWebServerRule; 24 import android.adservices.utils.ScenarioDispatcher; 25 import android.adservices.utils.ScenarioDispatcherFactory; 26 27 import org.junit.Rule; 28 import org.junit.Test; 29 30 import java.io.BufferedReader; 31 import java.io.InputStreamReader; 32 import java.net.HttpURLConnection; 33 import java.net.URL; 34 import java.util.List; 35 36 public class ScenarioDispatcherTest { 37 38 @Rule public MockWebServerRule mMockWebServerRule = MockWebServerRule.forHttp(); 39 40 @Test testScenarioDispatcher_happyPath_httpGetSuccess()41 public void testScenarioDispatcher_happyPath_httpGetSuccess() throws Exception { 42 ScenarioDispatcher dispatcher = 43 mMockWebServerRule.startMockWebServer( 44 ScenarioDispatcherFactory.createFromScenarioFile( 45 "scenarios/scenario-test-001.json")); 46 47 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 48 URL url = new URL(baseAddress + "/bidding"); 49 makeSimpleGetRequest(url); 50 51 assertThat(dispatcher.getCalledPaths()).containsExactlyElementsIn(List.of("/bidding")); 52 } 53 54 @Test testScenarioDispatcher_withPrefix_httpGetSuccess()55 public void testScenarioDispatcher_withPrefix_httpGetSuccess() throws Exception { 56 ScenarioDispatcher dispatcher = 57 mMockWebServerRule.startMockWebServer( 58 ScenarioDispatcherFactory.createFromScenarioFileWithRandomPrefix( 59 "scenarios/scenario-test-001.json")); 60 61 URL url = new URL(dispatcher.getBaseAddressWithPrefix() + "/bidding"); 62 makeSimpleGetRequest(url); 63 64 assertThat(dispatcher.getCalledPaths()).containsExactlyElementsIn(List.of("/bidding")); 65 } 66 67 @Test testScenarioDispatcher_withVerifyCalled_success()68 public void testScenarioDispatcher_withVerifyCalled_success() throws Exception { 69 ScenarioDispatcher dispatcher = 70 mMockWebServerRule.startMockWebServer( 71 ScenarioDispatcherFactory.createFromScenarioFile( 72 "scenarios/scenario-test-002.json")); 73 74 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 75 makeSimpleGetRequest(new URL(baseAddress + "/bidding")); 76 makeSimpleGetRequest(new URL(baseAddress + "/scoring")); 77 78 assertThat(dispatcher.getCalledPaths()) 79 .containsExactlyElementsIn(dispatcher.getVerifyCalledPaths()); 80 } 81 82 @Test testScenarioDispatcher_withVerifyNotCalled_success()83 public void testScenarioDispatcher_withVerifyNotCalled_success() throws Exception { 84 ScenarioDispatcher dispatcher = 85 mMockWebServerRule.startMockWebServer( 86 ScenarioDispatcherFactory.createFromScenarioFile( 87 "scenarios/scenario-test-003.json")); 88 89 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 90 makeSimpleGetRequest(new URL(baseAddress + "/bidding")); // Call something else. 91 92 assertThat(dispatcher.getCalledPaths()) 93 .doesNotContain(dispatcher.getVerifyNotCalledPaths()); 94 } 95 96 @Test testScenarioDispatcher_withTwoSecondDelay_success()97 public void testScenarioDispatcher_withTwoSecondDelay_success() throws Exception { 98 ScenarioDispatcher dispatcher = 99 mMockWebServerRule.startMockWebServer( 100 ScenarioDispatcherFactory.createFromScenarioFile( 101 "scenarios/scenario-test-004.json")); 102 103 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 104 long startTime = System.currentTimeMillis(); 105 makeSimpleGetRequest(new URL(baseAddress + "/bidding")); // Call something else. 106 long endTime = System.currentTimeMillis(); 107 108 assertThat(dispatcher.getCalledPaths()) 109 .containsNoneIn(dispatcher.getVerifyNotCalledPaths()); 110 assertThat(endTime - startTime).isAtLeast(2000); 111 } 112 113 @Test testScenarioDispatcher_withMultiplePathSegments_httpGetSuccess()114 public void testScenarioDispatcher_withMultiplePathSegments_httpGetSuccess() throws Exception { 115 ScenarioDispatcher dispatcher = 116 mMockWebServerRule.startMockWebServer( 117 ScenarioDispatcherFactory.createFromScenarioFile( 118 "scenarios/scenario-test-005.json")); 119 120 makeSimpleGetRequest(new URL(dispatcher.getBaseAddressWithPrefix() + "/hello/world")); 121 122 assertThat(dispatcher.getCalledPaths()).containsExactlyElementsIn(List.of("/hello/world")); 123 } 124 125 @Test testScenarioDispatcher_withDuplicatePathCalls_doesNotReturnEarly()126 public void testScenarioDispatcher_withDuplicatePathCalls_doesNotReturnEarly() 127 throws Exception { 128 ScenarioDispatcher dispatcher = 129 mMockWebServerRule.startMockWebServer( 130 ScenarioDispatcherFactory.createFromScenarioFile( 131 "scenarios/scenario-test-006.json")); 132 133 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 134 makeSimpleGetRequest(new URL(baseAddress + "/bidding")); 135 makeSimpleGetRequest(new URL(baseAddress + "/bidding")); 136 makeSimpleGetRequest(new URL(baseAddress + "/scoring")); 137 138 assertThat(dispatcher.getCalledPaths()) 139 .containsExactlyElementsIn(List.of("/bidding", "/scoring")); 140 } 141 142 // Regression test for bug b/325677040. 143 @Test testScenarioDispatcher_withComplexUrlStructure_success()144 public void testScenarioDispatcher_withComplexUrlStructure_success() throws Exception { 145 ScenarioDispatcher dispatcher = 146 mMockWebServerRule.startMockWebServer( 147 ScenarioDispatcherFactory.createFromScenarioFile( 148 "scenarios/scenario-test-007.json")); 149 150 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 151 makeSimpleGetRequest(new URL(baseAddress + "/bidding")); 152 makeSimpleGetRequest(new URL(baseAddress + "/scoring")); 153 makeSimpleGetRequest(new URL(baseAddress + "/seller/reportImpression")); 154 makeSimpleGetRequest( 155 new URL( 156 String.format( 157 "%s/seller/reportImpression?render_uri=%s/render/shirts/0?bid=5", 158 baseAddress, baseAddress))); 159 160 assertThat(dispatcher.getCalledPaths()) 161 .containsAtLeastElementsIn(List.of("/seller/reportImpression")); 162 } 163 164 @Test testScenarioDispatcher_withQueryParamPath_success()165 public void testScenarioDispatcher_withQueryParamPath_success() throws Exception { 166 ScenarioDispatcher dispatcher = 167 mMockWebServerRule.startMockWebServer( 168 ScenarioDispatcherFactory.createFromScenarioFile( 169 "scenarios/scenario-test-008.json")); 170 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 171 String path = 172 "/seller/reportImpression?render_uri=https://localhost:38383/render/shoes/0?bid=10"; 173 174 makeSimpleGetRequest(new URL(baseAddress + path)); 175 176 assertThat(dispatcher.getCalledPaths()).containsExactly(path); 177 } 178 179 @Test testScenarioDispatcher_withQueryParamPath_doesNotFallback()180 public void testScenarioDispatcher_withQueryParamPath_doesNotFallback() throws Exception { 181 ScenarioDispatcher dispatcher = 182 mMockWebServerRule.startMockWebServer( 183 ScenarioDispatcherFactory.createFromScenarioFile( 184 "scenarios/scenario-test-009.json")); 185 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 186 String path = 187 "/seller/reportImpression?render_uri=https://localhost:38383/render/shoes/0?bid=10"; 188 189 // Same structure as testScenarioDispatcher_withQueryParamPath_success except adding some 190 // more data into the path. 191 makeSimpleGetRequest(new URL(baseAddress + path)); 192 193 assertThat(dispatcher.getCalledPaths()).doesNotContain("/seller/reportImpression"); 194 } 195 196 @Test testScenarioDispatcher_withServerPathInQueryParams_success()197 public void testScenarioDispatcher_withServerPathInQueryParams_success() throws Exception { 198 ScenarioDispatcher dispatcher = 199 mMockWebServerRule.startMockWebServer( 200 ScenarioDispatcherFactory.createFromScenarioFile( 201 "scenarios/scenario-test-010.json")); 202 String baseAddress = dispatcher.getBaseAddressWithPrefix().toString(); 203 String path = 204 "/seller/reportImpression?render_uri=http://localhost:" 205 + mMockWebServerRule.getMockWebServer().getPort() 206 + "/render/shoes/0?bid=10"; 207 208 makeSimpleGetRequest(new URL(baseAddress + path)); 209 210 assertThat(dispatcher.getCalledPaths()).containsExactly(path); 211 } 212 213 @Test testScenarioDispatcher_withMissingSlashPrefix_throwsException()214 public void testScenarioDispatcher_withMissingSlashPrefix_throwsException() throws Exception { 215 ScenarioDispatcherFactory scenarioDispatcherFactory = 216 ScenarioDispatcherFactory.createFromScenarioFile( 217 "scenarios/scenario-test-011.json"); 218 219 assertThrows( 220 IllegalStateException.class, 221 () -> scenarioDispatcherFactory.getDispatcher(new URL("http://localhost:8080"))); 222 } 223 224 @SuppressWarnings("UnusedReturnValue") makeSimpleGetRequest(URL url)225 public static String makeSimpleGetRequest(URL url) throws Exception { 226 StringBuilder result = new StringBuilder(); 227 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 228 conn.setRequestMethod("GET"); 229 230 InputStreamReader isReader = new InputStreamReader(conn.getInputStream()); 231 try (BufferedReader reader = new BufferedReader(isReader)) { 232 String line; 233 do { 234 line = reader.readLine(); 235 result.append(line); 236 } while (line != null); 237 } 238 return result.toString(); 239 } 240 } 241