danielcweeks commented on code in PR #11577:
URL: https://github.com/apache/iceberg/pull/11577#discussion_r1915252528


##########
azure/src/test/java/org/apache/iceberg/azure/adlsv2/VendedAdlsCredentialProviderTest.java:
##########
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.iceberg.azure.adlsv2;
+
+import static 
org.apache.iceberg.azure.AzureProperties.ADLS_SAS_TOKEN_EXPIRES_AT_MS_PREFIX;
+import static org.apache.iceberg.azure.AzureProperties.ADLS_SAS_TOKEN_PREFIX;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockserver.integration.ClientAndServer.startClientAndServer;
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.HttpResponse.response;
+
+import com.azure.core.credential.AzureSasCredential;
+import com.azure.core.http.HttpMethod;
+import java.io.IOException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import org.apache.iceberg.TestHelpers;
+import org.apache.iceberg.exceptions.RESTException;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
+import org.apache.iceberg.rest.credentials.Credential;
+import org.apache.iceberg.rest.credentials.ImmutableCredential;
+import org.apache.iceberg.rest.responses.ImmutableLoadCredentialsResponse;
+import org.apache.iceberg.rest.responses.LoadCredentialsResponse;
+import org.apache.iceberg.rest.responses.LoadCredentialsResponseParser;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockserver.integration.ClientAndServer;
+import org.mockserver.model.HttpRequest;
+import org.mockserver.model.HttpResponse;
+import org.mockserver.verify.VerificationTimes;
+
+public class VendedAdlsCredentialProviderTest {
+  private static final int PORT = 3232;
+  private static final String URI = 
String.format("http://127.0.0.1:%d/v1/credentials";, PORT);
+  private static ClientAndServer mockServer;
+  private static final String STORAGE_ACCOUNT = "account1";
+  private static final String CREDENTIAL_PREFIX =
+      "abfs://[email protected]/dir";
+  private static final String STORAGE_ACCOUNT_2 = "account2";
+  private static final String CREDENTIAL_PREFIX_2 =
+      "abfs://[email protected]/dir";
+
+  @BeforeAll
+  public static void beforeAll() {
+    mockServer = startClientAndServer(PORT);
+  }
+
+  @AfterAll
+  public static void stopServer() {
+    mockServer.stop();
+  }
+
+  @BeforeEach
+  public void before() {
+    mockServer.reset();
+  }
+
+  @Test
+  public void invalidOrMissingUri() {
+    assertThatThrownBy(() -> new VendedAdlsCredentialProvider(null))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Invalid properties: null");
+    assertThatThrownBy(() -> new 
VendedAdlsCredentialProvider(ImmutableMap.of()))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Invalid URI: null");
+
+    try (VendedAdlsCredentialProvider provider =
+        new VendedAdlsCredentialProvider(
+            ImmutableMap.of(VendedAdlsCredentialProvider.URI, "invalid uri"))) 
{
+      assertThatThrownBy(() -> provider.credentialForAccount(STORAGE_ACCOUNT))
+          .isInstanceOf(RESTException.class)
+          .hasMessageStartingWith("Failed to create request URI from base 
invalid uri");
+    }
+  }
+
+  @Test
+  public void noADLSCredentials() {
+    HttpRequest mockRequest = 
request("/v1/credentials").withMethod(HttpMethod.GET.name());
+
+    HttpResponse mockResponse =
+        response(
+                LoadCredentialsResponseParser.toJson(
+                    ImmutableLoadCredentialsResponse.builder().build()))
+            .withStatusCode(200);
+    mockServer.when(mockRequest).respond(mockResponse);
+
+    try (VendedAdlsCredentialProvider provider =
+        new 
VendedAdlsCredentialProvider(ImmutableMap.of(VendedAdlsCredentialProvider.URI, 
URI))) {
+      assertThatThrownBy(() -> provider.credentialForAccount(STORAGE_ACCOUNT))
+          .isInstanceOf(IllegalStateException.class)
+          .hasMessage("Invalid ADLS Credentials for storage-account account1: 
empty");
+    }
+  }
+
+  @Test
+  public void expirationNotSet() {
+    HttpRequest mockRequest = 
request("/v1/credentials").withMethod(HttpMethod.GET.name());
+    LoadCredentialsResponse response =
+        ImmutableLoadCredentialsResponse.builder()
+            .addCredentials(
+                ImmutableCredential.builder()
+                    .prefix(CREDENTIAL_PREFIX)
+                    .config(
+                        ImmutableMap.of(ADLS_SAS_TOKEN_PREFIX + 
STORAGE_ACCOUNT, "randomSasToken"))
+                    .build())
+            .build();
+    HttpResponse mockResponse =
+        
response(LoadCredentialsResponseParser.toJson(response)).withStatusCode(200);
+    mockServer.when(mockRequest).respond(mockResponse);
+
+    try (VendedAdlsCredentialProvider provider =
+        new 
VendedAdlsCredentialProvider(ImmutableMap.of(VendedAdlsCredentialProvider.URI, 
URI))) {
+      assertThatThrownBy(() -> provider.credentialForAccount(STORAGE_ACCOUNT))
+          .isInstanceOf(IllegalStateException.class)
+          .hasMessage("Invalid ADLS Credentials: 
adls.sas-token-expires-at-ms.account1 not set");
+    }
+  }
+
+  @Test
+  public void nonExpiredSasToken() {
+    HttpRequest mockRequest = 
request("/v1/credentials").withMethod(HttpMethod.GET.name());
+    Credential credential =
+        ImmutableCredential.builder()
+            .prefix(CREDENTIAL_PREFIX)
+            .config(
+                ImmutableMap.of(
+                    ADLS_SAS_TOKEN_PREFIX + STORAGE_ACCOUNT,
+                    "randomSasToken",
+                    ADLS_SAS_TOKEN_EXPIRES_AT_MS_PREFIX + STORAGE_ACCOUNT,
+                    Long.toString(Instant.now().plus(1, 
ChronoUnit.HOURS).toEpochMilli())))
+            .build();
+    LoadCredentialsResponse response =
+        
ImmutableLoadCredentialsResponse.builder().addCredentials(credential).build();
+    HttpResponse mockResponse =
+        
response(LoadCredentialsResponseParser.toJson(response)).withStatusCode(200);
+    mockServer.when(mockRequest).respond(mockResponse);
+
+    try (VendedAdlsCredentialProvider provider =
+        new 
VendedAdlsCredentialProvider(ImmutableMap.of(VendedAdlsCredentialProvider.URI, 
URI))) {
+      AzureSasCredential azureSasCredential = 
provider.credentialForAccount(STORAGE_ACCOUNT);
+      assertThat(azureSasCredential.getSignature())
+          .isEqualTo(credential.config().get(ADLS_SAS_TOKEN_PREFIX + 
STORAGE_ACCOUNT));
+
+      for (int i = 0; i < 5; i++) {
+        // resolving credentials multiple times should not hit the credentials 
endpoint again
+        
assertThat(provider.credentialForAccount(STORAGE_ACCOUNT)).isSameAs(azureSasCredential);
+      }
+    }
+    mockServer.verify(mockRequest, VerificationTimes.once());
+  }
+
+  @Test
+  public void expiredSasToken() throws InterruptedException {
+    HttpRequest mockRequest = 
request("/v1/credentials").withMethod(HttpMethod.GET.name());
+    Credential credential =
+        ImmutableCredential.builder()
+            .prefix(CREDENTIAL_PREFIX)
+            .config(
+                ImmutableMap.of(
+                    ADLS_SAS_TOKEN_PREFIX + STORAGE_ACCOUNT,
+                    "randomSasToken",
+                    ADLS_SAS_TOKEN_EXPIRES_AT_MS_PREFIX + STORAGE_ACCOUNT,
+                    Long.toString(Instant.now().minus(1, 
ChronoUnit.MINUTES).toEpochMilli())))
+            .build();
+    LoadCredentialsResponse response =
+        
ImmutableLoadCredentialsResponse.builder().addCredentials(credential).build();
+    HttpResponse mockResponse =
+        
response(LoadCredentialsResponseParser.toJson(response)).withStatusCode(200);
+    mockServer.when(mockRequest).respond(mockResponse);
+
+    try (VendedAdlsCredentialProvider provider =
+        new 
VendedAdlsCredentialProvider(ImmutableMap.of(VendedAdlsCredentialProvider.URI, 
URI))) {
+      AzureSasCredential azureSasCredential = 
provider.credentialForAccount(STORAGE_ACCOUNT);
+      assertThat(azureSasCredential.getSignature())
+          .isEqualTo(credential.config().get(ADLS_SAS_TOKEN_PREFIX + 
STORAGE_ACCOUNT));
+
+      Thread.sleep(20);

Review Comment:
   I think you should be able to the use `awaitility` here to avoid hard 
sleeps, which I would really prefer not to include in the tests.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to