1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 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 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.core.client.builder; 17 18 import static org.assertj.core.api.Assertions.assertThat; 19 import static org.assertj.core.api.Assertions.assertThatThrownBy; 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.never; 23 import static org.mockito.Mockito.times; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.DISABLE_HOST_PREFIX_INJECTION; 27 import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.SIGNER; 28 import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.USER_AGENT_PREFIX; 29 import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.USER_AGENT_SUFFIX; 30 import static software.amazon.awssdk.core.client.config.SdkClientOption.ADDITIONAL_HTTP_HEADERS; 31 import static software.amazon.awssdk.core.client.config.SdkClientOption.API_CALL_ATTEMPT_TIMEOUT; 32 import static software.amazon.awssdk.core.client.config.SdkClientOption.API_CALL_TIMEOUT; 33 import static software.amazon.awssdk.core.client.config.SdkClientOption.ENDPOINT_OVERRIDDEN; 34 import static software.amazon.awssdk.core.client.config.SdkClientOption.EXECUTION_ATTRIBUTES; 35 import static software.amazon.awssdk.core.client.config.SdkClientOption.EXECUTION_INTERCEPTORS; 36 import static software.amazon.awssdk.core.client.config.SdkClientOption.METRIC_PUBLISHERS; 37 import static software.amazon.awssdk.core.client.config.SdkClientOption.PROFILE_FILE; 38 import static software.amazon.awssdk.core.client.config.SdkClientOption.PROFILE_FILE_SUPPLIER; 39 import static software.amazon.awssdk.core.client.config.SdkClientOption.PROFILE_NAME; 40 import static software.amazon.awssdk.core.client.config.SdkClientOption.RETRY_POLICY; 41 import static software.amazon.awssdk.core.client.config.SdkClientOption.SCHEDULED_EXECUTOR_SERVICE; 42 import static software.amazon.awssdk.core.internal.SdkInternalTestAdvancedClientOption.ENDPOINT_OVERRIDDEN_OVERRIDE; 43 44 import com.google.common.collect.ImmutableSet; 45 import java.beans.BeanInfo; 46 import java.beans.Introspector; 47 import java.beans.PropertyDescriptor; 48 import java.lang.reflect.Method; 49 import java.net.URI; 50 import java.time.Duration; 51 import java.util.ArrayList; 52 import java.util.Arrays; 53 import java.util.HashMap; 54 import java.util.List; 55 import java.util.Map; 56 import java.util.Optional; 57 import java.util.Set; 58 import java.util.concurrent.Executors; 59 import java.util.concurrent.ScheduledExecutorService; 60 import java.util.function.Supplier; 61 import org.assertj.core.api.Assertions; 62 import org.junit.Before; 63 import org.junit.Test; 64 import org.junit.runner.RunWith; 65 import org.mockito.Mock; 66 import org.mockito.Mockito; 67 import org.mockito.junit.MockitoJUnitRunner; 68 import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 69 import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; 70 import software.amazon.awssdk.core.client.config.SdkClientConfiguration; 71 import software.amazon.awssdk.core.client.config.SdkClientOption; 72 import software.amazon.awssdk.core.interceptor.ExecutionAttribute; 73 import software.amazon.awssdk.core.interceptor.ExecutionAttributes; 74 import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; 75 import software.amazon.awssdk.core.retry.RetryPolicy; 76 import software.amazon.awssdk.core.signer.NoOpSigner; 77 import software.amazon.awssdk.core.signer.Signer; 78 import software.amazon.awssdk.http.SdkHttpClient; 79 import software.amazon.awssdk.http.SdkHttpConfigurationOption; 80 import software.amazon.awssdk.http.async.SdkAsyncHttpClient; 81 import software.amazon.awssdk.metrics.MetricCollection; 82 import software.amazon.awssdk.metrics.MetricPublisher; 83 import software.amazon.awssdk.profiles.ProfileFile; 84 import software.amazon.awssdk.utils.AttributeMap; 85 import software.amazon.awssdk.utils.StringInputStream; 86 87 /** 88 * Validate the functionality of the {@link SdkDefaultClientBuilder}. 89 */ 90 @RunWith(MockitoJUnitRunner.class) 91 public class DefaultClientBuilderTest { 92 93 private static final AttributeMap MOCK_DEFAULTS = AttributeMap 94 .builder() 95 .put(SdkHttpConfigurationOption.READ_TIMEOUT, Duration.ofSeconds(10)) 96 .build(); 97 98 private static final String ENDPOINT_PREFIX = "prefix"; 99 private static final URI DEFAULT_ENDPOINT = URI.create("https://defaultendpoint.com"); 100 private static final URI ENDPOINT = URI.create("https://example.com"); 101 private static final NoOpSigner TEST_SIGNER = new NoOpSigner(); 102 103 @Mock 104 private SdkHttpClient.Builder defaultHttpClientFactory; 105 106 @Mock 107 private SdkAsyncHttpClient.Builder defaultAsyncHttpClientFactory; 108 109 @Before setup()110 public void setup() { 111 when(defaultHttpClientFactory.buildWithDefaults(any())).thenReturn(mock(SdkHttpClient.class)); 112 when(defaultAsyncHttpClientFactory.buildWithDefaults(any())).thenReturn(mock(SdkAsyncHttpClient.class)); 113 } 114 115 @Test overrideConfigurationIsNeverNull()116 public void overrideConfigurationIsNeverNull() { 117 ClientOverrideConfiguration config = testClientBuilder().overrideConfiguration(); 118 assertThat(config).isNotNull(); 119 120 config = testClientBuilder().overrideConfiguration((ClientOverrideConfiguration) null).overrideConfiguration(); 121 assertThat(config).isNotNull(); 122 } 123 124 @Test overrideConfigurationReturnsSetValues()125 public void overrideConfigurationReturnsSetValues() { 126 List<ExecutionInterceptor> interceptors = new ArrayList<>(); 127 RetryPolicy retryPolicy = RetryPolicy.builder().build(); 128 Map<String, List<String>> headers = new HashMap<>(); 129 List<MetricPublisher> metricPublishers = new ArrayList<>(); 130 ExecutionAttributes executionAttributes = new ExecutionAttributes(); 131 Signer signer = (request, execAttributes) -> request; 132 String suffix = "suffix"; 133 String prefix = "prefix"; 134 Duration apiCallTimeout = Duration.ofMillis(42); 135 Duration apiCallAttemptTimeout = Duration.ofMillis(43); 136 ProfileFile profileFile = ProfileFile.builder() 137 .content(new StringInputStream("")) 138 .type(ProfileFile.Type.CONFIGURATION) 139 .build(); 140 Supplier<ProfileFile> profileFileSupplier = () -> profileFile; 141 String profileName = "name"; 142 ScheduledExecutorService scheduledExecutorService = mock(ScheduledExecutorService.class); 143 144 ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() 145 .executionInterceptors(interceptors) 146 .retryPolicy(retryPolicy) 147 .headers(headers) 148 .putAdvancedOption(SIGNER, signer) 149 .putAdvancedOption(USER_AGENT_SUFFIX, suffix) 150 .putAdvancedOption(USER_AGENT_PREFIX, prefix) 151 .apiCallTimeout(apiCallTimeout) 152 .apiCallAttemptTimeout(apiCallAttemptTimeout) 153 .putAdvancedOption(DISABLE_HOST_PREFIX_INJECTION, Boolean.TRUE) 154 .defaultProfileFileSupplier(profileFileSupplier) 155 .defaultProfileName(profileName) 156 .metricPublishers(metricPublishers) 157 .executionAttributes(executionAttributes) 158 .putAdvancedOption(ENDPOINT_OVERRIDDEN_OVERRIDE, Boolean.TRUE) 159 .scheduledExecutorService(scheduledExecutorService) 160 .build(); 161 162 TestClientBuilder builder = testClientBuilder().overrideConfiguration(overrideConfig); 163 ClientOverrideConfiguration builderOverrideConfig = builder.overrideConfiguration(); 164 165 assertThat(builderOverrideConfig.executionInterceptors()).isEqualTo(interceptors); 166 assertThat(builderOverrideConfig.retryPolicy()).isEqualTo(Optional.of(retryPolicy)); 167 assertThat(builderOverrideConfig.headers()).isEqualTo(headers); 168 assertThat(builderOverrideConfig.advancedOption(SIGNER)).isEqualTo(Optional.of(signer)); 169 assertThat(builderOverrideConfig.advancedOption(USER_AGENT_SUFFIX)).isEqualTo(Optional.of(suffix)); 170 assertThat(builderOverrideConfig.apiCallTimeout()).isEqualTo(Optional.of(apiCallTimeout)); 171 assertThat(builderOverrideConfig.apiCallAttemptTimeout()).isEqualTo(Optional.of(apiCallAttemptTimeout)); 172 assertThat(builderOverrideConfig.advancedOption(DISABLE_HOST_PREFIX_INJECTION)).isEqualTo(Optional.of(Boolean.TRUE)); 173 assertThat(builderOverrideConfig.defaultProfileFileSupplier()).hasValue(profileFileSupplier); 174 assertThat(builderOverrideConfig.defaultProfileFile()).isEqualTo(Optional.of(profileFile)); 175 assertThat(builderOverrideConfig.defaultProfileName()).isEqualTo(Optional.of(profileName)); 176 assertThat(builderOverrideConfig.metricPublishers()).isEqualTo(metricPublishers); 177 assertThat(builderOverrideConfig.executionAttributes().getAttributes()).isEqualTo(executionAttributes.getAttributes()); 178 assertThat(builderOverrideConfig.advancedOption(ENDPOINT_OVERRIDDEN_OVERRIDE)).isEqualTo(Optional.of(Boolean.TRUE)); 179 180 Runnable runnable = () -> { 181 }; 182 builderOverrideConfig.scheduledExecutorService().get().submit(runnable); 183 verify(scheduledExecutorService).submit(runnable); 184 } 185 186 @Test overrideConfigurationOmitsUnsetValues()187 public void overrideConfigurationOmitsUnsetValues() { 188 ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() 189 .build(); 190 191 TestClientBuilder builder = testClientBuilder().overrideConfiguration(overrideConfig); 192 ClientOverrideConfiguration builderOverrideConfig = builder.overrideConfiguration(); 193 194 assertThat(builderOverrideConfig.executionInterceptors()).isEmpty(); 195 assertThat(builderOverrideConfig.retryPolicy()).isEmpty(); 196 assertThat(builderOverrideConfig.headers()).isEmpty(); 197 assertThat(builderOverrideConfig.advancedOption(SIGNER)).isEmpty(); 198 assertThat(builderOverrideConfig.advancedOption(USER_AGENT_SUFFIX)).isEmpty(); 199 assertThat(builderOverrideConfig.apiCallTimeout()).isEmpty(); 200 assertThat(builderOverrideConfig.apiCallAttemptTimeout()).isEmpty(); 201 assertThat(builderOverrideConfig.advancedOption(DISABLE_HOST_PREFIX_INJECTION)).isEmpty(); 202 assertThat(builderOverrideConfig.defaultProfileFileSupplier()).isEmpty(); 203 assertThat(builderOverrideConfig.defaultProfileFile()).isEmpty(); 204 assertThat(builderOverrideConfig.defaultProfileName()).isEmpty(); 205 assertThat(builderOverrideConfig.metricPublishers()).isEmpty(); 206 assertThat(builderOverrideConfig.executionAttributes().getAttributes()).isEmpty(); 207 assertThat(builderOverrideConfig.advancedOption(ENDPOINT_OVERRIDDEN_OVERRIDE)).isEmpty(); 208 assertThat(builderOverrideConfig.scheduledExecutorService()).isEmpty(); 209 } 210 211 @Test buildIncludesClientOverrides()212 public void buildIncludesClientOverrides() { 213 List<ExecutionInterceptor> interceptors = new ArrayList<>(); 214 ExecutionInterceptor interceptor = new ExecutionInterceptor() {}; 215 interceptors.add(interceptor); 216 217 RetryPolicy retryPolicy = RetryPolicy.builder().build(); 218 ScheduledExecutorService scheduledExecutorService = Mockito.spy(Executors.newScheduledThreadPool(1)); 219 220 Map<String, List<String>> headers = new HashMap<>(); 221 List<String> headerValues = new ArrayList<>(); 222 headerValues.add("value"); 223 headers.put("client-override-test", headerValues); 224 225 List<MetricPublisher> metricPublishers = new ArrayList<>(); 226 MetricPublisher metricPublisher = new MetricPublisher() { 227 @Override 228 public void publish(MetricCollection metricCollection) { 229 230 } 231 232 @Override 233 public void close() { 234 235 } 236 }; 237 metricPublishers.add(metricPublisher); 238 239 ExecutionAttribute<String> execAttribute = new ExecutionAttribute<>("test"); 240 ExecutionAttributes executionAttributes = ExecutionAttributes.builder().put(execAttribute, "value").build(); 241 242 Signer signer = (request, execAttributes) -> request; 243 String suffix = "suffix"; 244 String prefix = "prefix"; 245 Duration apiCallTimeout = Duration.ofMillis(42); 246 Duration apiCallAttemptTimeout = Duration.ofMillis(43); 247 ProfileFile profileFile = ProfileFile.builder() 248 .content(new StringInputStream("")) 249 .type(ProfileFile.Type.CONFIGURATION) 250 .build(); 251 String profileName = "name"; 252 253 ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() 254 .executionInterceptors(interceptors) 255 .retryPolicy(retryPolicy) 256 .headers(headers) 257 .putAdvancedOption(SIGNER, signer) 258 .putAdvancedOption(USER_AGENT_SUFFIX, suffix) 259 .putAdvancedOption(USER_AGENT_PREFIX, prefix) 260 .apiCallTimeout(apiCallTimeout) 261 .apiCallAttemptTimeout(apiCallAttemptTimeout) 262 .putAdvancedOption(DISABLE_HOST_PREFIX_INJECTION, Boolean.TRUE) 263 .defaultProfileFile(profileFile) 264 .defaultProfileName(profileName) 265 .metricPublishers(metricPublishers) 266 .executionAttributes(executionAttributes) 267 .putAdvancedOption(ENDPOINT_OVERRIDDEN_OVERRIDE, Boolean.TRUE) 268 .scheduledExecutorService(scheduledExecutorService) 269 .build(); 270 271 SdkClientConfiguration config = 272 testClientBuilder().overrideConfiguration(overrideConfig).build().clientConfiguration; 273 274 assertThat(config.option(EXECUTION_INTERCEPTORS)).contains(interceptor); 275 assertThat(config.option(RETRY_POLICY)).isEqualTo(retryPolicy); 276 assertThat(config.option(ADDITIONAL_HTTP_HEADERS).get("client-override-test")).isEqualTo(headerValues); 277 assertThat(config.option(SIGNER)).isEqualTo(signer); 278 assertThat(config.option(USER_AGENT_SUFFIX)).isEqualTo(suffix); 279 assertThat(config.option(USER_AGENT_PREFIX)).isEqualTo(prefix); 280 assertThat(config.option(API_CALL_TIMEOUT)).isEqualTo(apiCallTimeout); 281 assertThat(config.option(API_CALL_ATTEMPT_TIMEOUT)).isEqualTo(apiCallAttemptTimeout); 282 assertThat(config.option(DISABLE_HOST_PREFIX_INJECTION)).isEqualTo(Boolean.TRUE); 283 assertThat(config.option(PROFILE_FILE)).isEqualTo(profileFile); 284 assertThat(config.option(PROFILE_FILE_SUPPLIER).get()).isEqualTo(profileFile); 285 assertThat(config.option(PROFILE_NAME)).isEqualTo(profileName); 286 assertThat(config.option(METRIC_PUBLISHERS)).contains(metricPublisher); 287 assertThat(config.option(EXECUTION_ATTRIBUTES).getAttribute(execAttribute)).isEqualTo("value"); 288 assertThat(config.option(ENDPOINT_OVERRIDDEN)).isEqualTo(Boolean.TRUE); 289 290 // Ensure that the SDK won't close the scheduled executor service we provided. 291 config.close(); 292 config.option(SCHEDULED_EXECUTOR_SERVICE).shutdownNow(); 293 config.option(SCHEDULED_EXECUTOR_SERVICE).shutdown(); 294 Mockito.verify(scheduledExecutorService, never()).shutdown(); 295 Mockito.verify(scheduledExecutorService, never()).shutdownNow(); 296 } 297 298 @Test buildIncludesServiceDefaults()299 public void buildIncludesServiceDefaults() { 300 TestClient client = testClientBuilder().build(); 301 assertThat(client.clientConfiguration.option(SIGNER)) 302 .isEqualTo(TEST_SIGNER); 303 } 304 305 @Test buildWithEndpointShouldHaveCorrectEndpointAndSigningRegion()306 public void buildWithEndpointShouldHaveCorrectEndpointAndSigningRegion() { 307 TestClient client = testClientBuilder().endpointOverride(ENDPOINT).build(); 308 309 assertThat(client.clientConfiguration.option(SdkClientOption.ENDPOINT)).isEqualTo(ENDPOINT); 310 } 311 312 @Test buildWithEndpointWithoutScheme_shouldThrowException()313 public void buildWithEndpointWithoutScheme_shouldThrowException() { 314 assertThatThrownBy(() -> testClientBuilder().endpointOverride(URI.create("localhost")).build()) 315 .hasMessageContaining("The URI scheme of endpointOverride must not be null"); 316 317 } 318 319 @Test noClientProvided_DefaultHttpClientIsManagedBySdk()320 public void noClientProvided_DefaultHttpClientIsManagedBySdk() { 321 TestClient client = testClientBuilder().build(); 322 assertThat(client.clientConfiguration.option(SdkClientOption.SYNC_HTTP_CLIENT)) 323 .isNotInstanceOf(SdkDefaultClientBuilder.NonManagedSdkHttpClient.class); 324 verify(defaultHttpClientFactory, times(1)).buildWithDefaults(any()); 325 } 326 327 @Test noAsyncClientProvided_DefaultAsyncHttpClientIsManagedBySdk()328 public void noAsyncClientProvided_DefaultAsyncHttpClientIsManagedBySdk() { 329 TestAsyncClient client = testAsyncClientBuilder().build(); 330 assertThat(client.clientConfiguration.option(SdkClientOption.ASYNC_HTTP_CLIENT)) 331 .isNotInstanceOf(SdkDefaultClientBuilder.NonManagedSdkAsyncHttpClient.class); 332 verify(defaultAsyncHttpClientFactory, times(1)).buildWithDefaults(any()); 333 } 334 335 @Test clientFactoryProvided_ClientIsManagedBySdk()336 public void clientFactoryProvided_ClientIsManagedBySdk() { 337 TestClient client = testClientBuilder().httpClientBuilder((SdkHttpClient.Builder) serviceDefaults -> { 338 Assertions.assertThat(serviceDefaults).isEqualTo(MOCK_DEFAULTS); 339 return mock(SdkHttpClient.class); 340 }) 341 .build(); 342 assertThat(client.clientConfiguration.option(SdkClientOption.SYNC_HTTP_CLIENT)) 343 .isNotInstanceOf(SdkDefaultClientBuilder.NonManagedSdkHttpClient.class); 344 verify(defaultHttpClientFactory, never()).buildWithDefaults(any()); 345 } 346 347 @Test asyncHttpClientFactoryProvided_ClientIsManagedBySdk()348 public void asyncHttpClientFactoryProvided_ClientIsManagedBySdk() { 349 TestAsyncClient client = testAsyncClientBuilder() 350 .httpClientBuilder((SdkAsyncHttpClient.Builder) serviceDefaults -> { 351 assertThat(serviceDefaults).isEqualTo(MOCK_DEFAULTS); 352 return mock(SdkAsyncHttpClient.class); 353 }) 354 .build(); 355 assertThat(client.clientConfiguration.option(SdkClientOption.ASYNC_HTTP_CLIENT)) 356 .isNotInstanceOf(SdkDefaultClientBuilder.NonManagedSdkAsyncHttpClient.class); 357 verify(defaultAsyncHttpClientFactory, never()).buildWithDefaults(any()); 358 } 359 360 @Test explicitClientProvided_ClientIsNotManagedBySdk()361 public void explicitClientProvided_ClientIsNotManagedBySdk() { 362 TestClient client = testClientBuilder() 363 364 .httpClient(mock(SdkHttpClient.class)) 365 .build(); 366 assertThat(client.clientConfiguration.option(SdkClientOption.SYNC_HTTP_CLIENT)) 367 .isInstanceOf(SdkDefaultClientBuilder.NonManagedSdkHttpClient.class); 368 verify(defaultHttpClientFactory, never()).buildWithDefaults(any()); 369 } 370 371 @Test explicitAsyncHttpClientProvided_ClientIsNotManagedBySdk()372 public void explicitAsyncHttpClientProvided_ClientIsNotManagedBySdk() { 373 TestAsyncClient client = testAsyncClientBuilder() 374 .httpClient(mock(SdkAsyncHttpClient.class)) 375 .build(); 376 assertThat(client.clientConfiguration.option(SdkClientOption.ASYNC_HTTP_CLIENT)) 377 .isInstanceOf(SdkDefaultClientBuilder.NonManagedSdkAsyncHttpClient.class); 378 verify(defaultAsyncHttpClientFactory, never()).buildWithDefaults(any()); 379 } 380 381 @Test clientBuilderFieldsHaveBeanEquivalents()382 public void clientBuilderFieldsHaveBeanEquivalents() throws Exception { 383 // Mutating properties might not have bean equivalents. This is probably fine, since very few customers require 384 // bean-equivalent methods and it's not clear what they'd expect them to be named anyway. Ignore these methods for now. 385 Set<String> NON_BEAN_EQUIVALENT_METHODS = ImmutableSet.of("addPlugin", "plugins", "putAuthScheme"); 386 SdkClientBuilder<TestClientBuilder, TestClient> builder = testClientBuilder(); 387 388 BeanInfo beanInfo = Introspector.getBeanInfo(builder.getClass()); 389 Method[] clientBuilderMethods = SdkClientBuilder.class.getDeclaredMethods(); 390 391 Arrays.stream(clientBuilderMethods).filter(m -> !m.isSynthetic()).forEach(builderMethod -> { 392 String propertyName = builderMethod.getName(); 393 394 if (NON_BEAN_EQUIVALENT_METHODS.contains(propertyName)) { 395 return; 396 } 397 398 Optional<PropertyDescriptor> propertyForMethod = 399 Arrays.stream(beanInfo.getPropertyDescriptors()) 400 .filter(property -> property.getName().equals(propertyName)) 401 .findFirst(); 402 403 assertThat(propertyForMethod).as(propertyName + " property").hasValueSatisfying(property -> { 404 assertThat(property.getReadMethod()).as(propertyName + " getter").isNull(); 405 assertThat(property.getWriteMethod()).as(propertyName + " setter").isNotNull(); 406 }); 407 }); 408 } 409 410 @Test defaultProfileFileSupplier_isStaticOrHasIdentityCaching()411 public void defaultProfileFileSupplier_isStaticOrHasIdentityCaching() { 412 SdkClientConfiguration config = 413 testClientBuilder().build().clientConfiguration; 414 415 Supplier<ProfileFile> defaultProfileFileSupplier = config.option(PROFILE_FILE_SUPPLIER); 416 ProfileFile firstGet = defaultProfileFileSupplier.get(); 417 ProfileFile secondGet = defaultProfileFileSupplier.get(); 418 419 assertThat(secondGet).isSameAs(firstGet); 420 } 421 testClientBuilder()422 private SdkDefaultClientBuilder<TestClientBuilder, TestClient> testClientBuilder() { 423 ClientOverrideConfiguration overrideConfig = 424 ClientOverrideConfiguration.builder() 425 .putAdvancedOption(SIGNER, TEST_SIGNER) 426 .build(); 427 428 return new TestClientBuilder().overrideConfiguration(overrideConfig); 429 } 430 testAsyncClientBuilder()431 private SdkDefaultClientBuilder<TestAsyncClientBuilder, TestAsyncClient> testAsyncClientBuilder() { 432 ClientOverrideConfiguration overrideConfig = 433 ClientOverrideConfiguration.builder() 434 .putAdvancedOption(SIGNER, TEST_SIGNER) 435 .build(); 436 437 return new TestAsyncClientBuilder().overrideConfiguration(overrideConfig); 438 } 439 440 private static class TestClient { 441 private final SdkClientConfiguration clientConfiguration; 442 TestClient(SdkClientConfiguration clientConfiguration)443 private TestClient(SdkClientConfiguration clientConfiguration) { 444 this.clientConfiguration = clientConfiguration; 445 } 446 } 447 448 private class TestClientWithoutEndpointDefaultBuilder extends SdkDefaultClientBuilder<TestClientBuilder, TestClient> 449 implements SdkClientBuilder<TestClientBuilder, TestClient> { 450 TestClientWithoutEndpointDefaultBuilder()451 public TestClientWithoutEndpointDefaultBuilder() { 452 super(defaultHttpClientFactory, null); 453 } 454 455 @Override buildClient()456 protected TestClient buildClient() { 457 return new TestClient(super.syncClientConfiguration()); 458 } 459 460 @Override mergeChildDefaults(SdkClientConfiguration configuration)461 protected SdkClientConfiguration mergeChildDefaults(SdkClientConfiguration configuration) { 462 return configuration.merge(c -> c.option(SdkAdvancedClientOption.SIGNER, TEST_SIGNER)); 463 } 464 465 @Override childHttpConfig()466 protected AttributeMap childHttpConfig() { 467 return MOCK_DEFAULTS; 468 } 469 } 470 471 private class TestClientBuilder extends SdkDefaultClientBuilder<TestClientBuilder, TestClient> 472 implements SdkClientBuilder<TestClientBuilder, TestClient> { 473 TestClientBuilder()474 public TestClientBuilder() { 475 super(defaultHttpClientFactory, null); 476 } 477 478 @Override buildClient()479 protected TestClient buildClient() { 480 return new TestClient(super.syncClientConfiguration()); 481 } 482 483 @Override mergeChildDefaults(SdkClientConfiguration configuration)484 protected SdkClientConfiguration mergeChildDefaults(SdkClientConfiguration configuration) { 485 return configuration.merge(c -> c.option(SdkClientOption.ENDPOINT, DEFAULT_ENDPOINT)); 486 } 487 488 @Override childHttpConfig()489 protected AttributeMap childHttpConfig() { 490 return MOCK_DEFAULTS; 491 } 492 } 493 494 private static class TestAsyncClient { 495 private final SdkClientConfiguration clientConfiguration; 496 TestAsyncClient(SdkClientConfiguration clientConfiguration)497 private TestAsyncClient(SdkClientConfiguration clientConfiguration) { 498 this.clientConfiguration = clientConfiguration; 499 } 500 } 501 502 private class TestAsyncClientBuilder extends SdkDefaultClientBuilder<TestAsyncClientBuilder, TestAsyncClient> 503 implements SdkClientBuilder<TestAsyncClientBuilder, TestAsyncClient> { 504 TestAsyncClientBuilder()505 public TestAsyncClientBuilder() { 506 super(defaultHttpClientFactory, defaultAsyncHttpClientFactory); 507 } 508 509 @Override buildClient()510 protected TestAsyncClient buildClient() { 511 return new TestAsyncClient(super.asyncClientConfiguration()); 512 } 513 514 @Override mergeChildDefaults(SdkClientConfiguration configuration)515 protected SdkClientConfiguration mergeChildDefaults(SdkClientConfiguration configuration) { 516 return configuration.merge(c -> c.option(SdkClientOption.ENDPOINT, DEFAULT_ENDPOINT)); 517 } 518 519 @Override childHttpConfig()520 protected AttributeMap childHttpConfig() { 521 return MOCK_DEFAULTS; 522 } 523 } 524 } 525