Skip to content

Commit 8c35d35

Browse files
committed
added unit tests
1 parent a460a84 commit 8c35d35

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
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.opentelemetry.javaagent.providers;
17+
18+
import static org.junit.jupiter.api.Assertions.*;
19+
import static org.mockito.Mockito.*;
20+
import static org.mockito.Mockito.when;
21+
22+
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
23+
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
24+
import io.opentelemetry.sdk.common.CompletableResultCode;
25+
import io.opentelemetry.sdk.trace.export.SpanExporter;
26+
import java.net.URI;
27+
import java.util.List;
28+
import java.util.Map;
29+
import java.util.function.Consumer;
30+
import java.util.function.Supplier;
31+
import org.junit.jupiter.api.AfterEach;
32+
import org.junit.jupiter.api.BeforeEach;
33+
import org.junit.jupiter.api.Test;
34+
import org.junit.jupiter.api.extension.ExtendWith;
35+
import org.mockito.ArgumentCaptor;
36+
import org.mockito.Mock;
37+
import org.mockito.MockedStatic;
38+
import org.mockito.junit.jupiter.MockitoExtension;
39+
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
40+
import software.amazon.awssdk.auth.credentials.AwsCredentials;
41+
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
42+
import software.amazon.awssdk.core.exception.SdkClientException;
43+
import software.amazon.awssdk.http.SdkHttpFullRequest;
44+
import software.amazon.awssdk.http.SdkHttpMethod;
45+
import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
46+
import software.amazon.awssdk.http.auth.spi.signer.SignRequest.Builder;
47+
import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;
48+
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
49+
50+
@ExtendWith(MockitoExtension.class)
51+
public class OtlpAwsSpanExporterTest {
52+
private static final String OTLP_CW_ENDPOINT = "https://xray.us-east-1.amazonaws.com/v1/traces";
53+
private static final String AUTHORIZATION_HEADER = "Authorization";
54+
private static final String X_AMZ_DATE_HEADER = "X-Amz-Date";
55+
private static final String X_AMZ_SECURITY_TOKEN_HEADER = "X-Amz-Security-Token";
56+
57+
private static final String EXPECTED_AUTH_HEADER =
58+
"AWS4-HMAC-SHA256 Credential=test_key/some_date/us-east-1/xray/aws4_request";
59+
private static final String EXPECTED_AUTH_X_AMZ_DATE = "some_date";
60+
private static final String EXPECTED_AUTH_SECURITY_TOKEN = "test_token";
61+
62+
AwsCredentials credentials = AwsBasicCredentials.create("test_access_key", "test_secret_key");
63+
SignedRequest signedRequest =
64+
SignedRequest.builder()
65+
.request(
66+
SdkHttpFullRequest.builder()
67+
.method(SdkHttpMethod.POST)
68+
.uri(URI.create(OTLP_CW_ENDPOINT))
69+
.putHeader(AUTHORIZATION_HEADER, EXPECTED_AUTH_HEADER)
70+
.putHeader("X-Amz-Date", EXPECTED_AUTH_X_AMZ_DATE)
71+
.putHeader("X-Amz-Security-Token", EXPECTED_AUTH_SECURITY_TOKEN)
72+
.build())
73+
.build();
74+
75+
private MockedStatic<DefaultCredentialsProvider> mockDefaultCredentialsProvider;
76+
private MockedStatic<AwsV4HttpSigner> mockAwsV4HttpSigner;
77+
private MockedStatic<OtlpHttpSpanExporter> otlpSpanExporterMock;
78+
79+
@Mock private DefaultCredentialsProvider credentialsProvider;
80+
@Mock private AwsV4HttpSigner signer;
81+
@Mock private OtlpHttpSpanExporterBuilder mockBuilder;
82+
@Mock private OtlpHttpSpanExporter mockExporter;
83+
84+
private ArgumentCaptor<Supplier<Map<String, String>>> headersCaptor;
85+
86+
@BeforeEach
87+
void setup() {
88+
this.mockDefaultCredentialsProvider = mockStatic(DefaultCredentialsProvider.class);
89+
this.mockDefaultCredentialsProvider
90+
.when(DefaultCredentialsProvider::create)
91+
.thenReturn(credentialsProvider);
92+
93+
this.mockAwsV4HttpSigner = mockStatic(AwsV4HttpSigner.class);
94+
this.mockAwsV4HttpSigner.when(AwsV4HttpSigner::create).thenReturn(this.signer);
95+
96+
this.otlpSpanExporterMock = mockStatic(OtlpHttpSpanExporter.class);
97+
98+
this.headersCaptor = ArgumentCaptor.forClass(Supplier.class);
99+
100+
when(OtlpHttpSpanExporter.builder()).thenReturn(mockBuilder);
101+
when(this.mockBuilder.setEndpoint(any())).thenReturn(mockBuilder);
102+
when(this.mockBuilder.setHeaders(headersCaptor.capture())).thenReturn(mockBuilder);
103+
when(this.mockBuilder.build()).thenReturn(mockExporter);
104+
when(this.mockExporter.export(any())).thenReturn(CompletableResultCode.ofSuccess());
105+
}
106+
107+
@AfterEach
108+
void afterEach() {
109+
reset(this.signer, this.credentialsProvider);
110+
this.mockDefaultCredentialsProvider.close();
111+
this.mockAwsV4HttpSigner.close();
112+
this.otlpSpanExporterMock.close();
113+
}
114+
115+
@Test
116+
void testAwsSpanExporterAddsSigV4Headers() {
117+
118+
when(this.credentialsProvider.resolveCredentials()).thenReturn(this.credentials);
119+
when(this.signer.sign((Consumer<Builder<AwsCredentialsIdentity>>) any()))
120+
.thenReturn(this.signedRequest);
121+
122+
SpanExporter exporter = new OtlpAwsSpanExporter(OTLP_CW_ENDPOINT);
123+
124+
exporter.export(List.of());
125+
126+
Map<String, String> headers = this.headersCaptor.getValue().get();
127+
128+
assertTrue(headers.containsKey(X_AMZ_DATE_HEADER));
129+
assertTrue(headers.containsKey(AUTHORIZATION_HEADER));
130+
assertTrue(headers.containsKey(X_AMZ_SECURITY_TOKEN_HEADER));
131+
132+
assertEquals(EXPECTED_AUTH_HEADER, headers.get(AUTHORIZATION_HEADER));
133+
assertEquals(EXPECTED_AUTH_X_AMZ_DATE, headers.get(X_AMZ_DATE_HEADER));
134+
assertEquals(EXPECTED_AUTH_SECURITY_TOKEN, headers.get(X_AMZ_SECURITY_TOKEN_HEADER));
135+
}
136+
137+
@Test
138+
void testAwsSpanExporterDoesNotAddSigV4HeadersIfFailureToRetrieveCredentials() {
139+
140+
when(this.credentialsProvider.resolveCredentials())
141+
.thenThrow(SdkClientException.builder().message("bad credentials").build());
142+
143+
SpanExporter exporter = new OtlpAwsSpanExporter(OTLP_CW_ENDPOINT);
144+
145+
exporter.export(List.of());
146+
147+
Supplier<Map<String, String>> headersSupplier = headersCaptor.getValue();
148+
Map<String, String> headers = headersSupplier.get();
149+
150+
assertFalse(headers.containsKey(X_AMZ_DATE_HEADER));
151+
assertFalse(headers.containsKey(AUTHORIZATION_HEADER));
152+
assertFalse(headers.containsKey(X_AMZ_SECURITY_TOKEN_HEADER));
153+
154+
verifyNoInteractions(this.signer);
155+
}
156+
157+
@Test
158+
void testAwsSpanExporterDoesNotAddSigV4HeadersIfFailureToSignHeaders() {
159+
160+
when(this.credentialsProvider.resolveCredentials()).thenReturn(this.credentials);
161+
when(this.signer.sign((Consumer<Builder<AwsCredentialsIdentity>>) any()))
162+
.thenThrow(SdkClientException.builder().message("bad signature").build());
163+
164+
SpanExporter exporter = new OtlpAwsSpanExporter(OTLP_CW_ENDPOINT);
165+
166+
exporter.export(List.of());
167+
168+
Map<String, String> headers = this.headersCaptor.getValue().get();
169+
170+
assertFalse(headers.containsKey(X_AMZ_DATE_HEADER));
171+
assertFalse(headers.containsKey(AUTHORIZATION_HEADER));
172+
assertFalse(headers.containsKey(X_AMZ_SECURITY_TOKEN_HEADER));
173+
}
174+
}

0 commit comments

Comments
 (0)