Skip to content

Commit ff9ea8c

Browse files
RoeyoOgenvishalya
authored andcommitted
add: added test class for TestRoutingTargetHandler
1 parent 886b535 commit ff9ea8c

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.gateway.ha.handler;
15+
16+
import com.google.common.collect.ImmutableMap;
17+
import io.airlift.http.client.HttpClient;
18+
import io.trino.gateway.ha.config.GatewayCookieConfiguration;
19+
import io.trino.gateway.ha.config.GatewayCookieConfigurationPropertiesProvider;
20+
import io.trino.gateway.ha.config.HaGatewayConfiguration;
21+
import io.trino.gateway.ha.config.RequestAnalyzerConfig;
22+
import io.trino.gateway.ha.config.RulesExternalConfiguration;
23+
import io.trino.gateway.ha.handler.schema.RoutingTargetResponse;
24+
import io.trino.gateway.ha.router.RoutingGroupSelector;
25+
import io.trino.gateway.ha.router.RoutingManager;
26+
import io.trino.gateway.ha.router.schema.ExternalRouterResponse;
27+
import jakarta.servlet.http.HttpServletRequest;
28+
import jakarta.ws.rs.HttpMethod;
29+
import org.junit.jupiter.api.BeforeAll;
30+
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.api.TestInstance;
32+
import org.junit.jupiter.api.extension.ExtendWith;
33+
import org.mockito.Mockito;
34+
import org.mockito.junit.jupiter.MockitoExtension;
35+
36+
import java.util.Arrays;
37+
import java.util.Collections;
38+
import java.util.List;
39+
import java.util.Map;
40+
41+
import static io.trino.gateway.ha.handler.HttpUtils.USER_HEADER;
42+
import static org.assertj.core.api.Assertions.assertThat;
43+
import static org.mockito.ArgumentMatchers.any;
44+
import static org.mockito.Mockito.when;
45+
46+
@ExtendWith(MockitoExtension.class)
47+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
48+
class TestRoutingTargetHandler
49+
{
50+
private RoutingManager routingManager;
51+
private HttpClient httpClient;
52+
private HttpServletRequest request;
53+
54+
private RoutingTargetHandler handler;
55+
private HaGatewayConfiguration config;
56+
57+
static HaGatewayConfiguration provideGatewayConfiguration()
58+
{
59+
HaGatewayConfiguration config = new HaGatewayConfiguration();
60+
config.setRequestAnalyzerConfig(new RequestAnalyzerConfig());
61+
62+
// Configure excluded headers
63+
RulesExternalConfiguration rulesExternalConfig = new RulesExternalConfiguration();
64+
rulesExternalConfig.setExcludeHeaders(List.of("Authorization", "Cookie"));
65+
rulesExternalConfig.setUrlPath("http://localhost:8080/api/routing");
66+
config.getRoutingRules().setRulesExternalConfiguration(rulesExternalConfig);
67+
68+
// Initialize cookie configuration
69+
GatewayCookieConfiguration cookieConfig = new GatewayCookieConfiguration();
70+
cookieConfig.setEnabled(false); // Disable cookies for testing
71+
GatewayCookieConfigurationPropertiesProvider.getInstance().initialize(cookieConfig);
72+
73+
return config;
74+
}
75+
76+
private HttpServletRequest prepareMockRequest()
77+
{
78+
HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
79+
when(mockRequest.getMethod()).thenReturn(HttpMethod.GET);
80+
when(mockRequest.getHeader(USER_HEADER)).thenReturn("test-user");
81+
82+
// Set up header names enumeration
83+
List<String> headerNames = List.of(
84+
USER_HEADER,
85+
"Authorization",
86+
"Cookie"
87+
);
88+
when(mockRequest.getHeaderNames()).thenReturn(Collections.enumeration(headerNames));
89+
90+
// Set up individual header values
91+
when(mockRequest.getHeader("Authorization")).thenReturn("secret-token");
92+
when(mockRequest.getHeader("Cookie")).thenReturn("session-id");
93+
94+
// Set up header values enumeration for each header
95+
when(mockRequest.getHeaders(USER_HEADER)).thenReturn(Collections.enumeration(List.of("test-user")));
96+
when(mockRequest.getHeaders("Authorization")).thenReturn(Collections.enumeration(List.of("secret-token")));
97+
when(mockRequest.getHeaders("Cookie")).thenReturn(Collections.enumeration(List.of("session-id")));
98+
99+
return mockRequest;
100+
}
101+
102+
@BeforeAll
103+
void setUp()
104+
{
105+
config = provideGatewayConfiguration();
106+
httpClient = Mockito.mock(HttpClient.class);
107+
routingManager = Mockito.mock(RoutingManager.class);
108+
request = prepareMockRequest();
109+
110+
// Initialize the handler with the configuration
111+
handler = new RoutingTargetHandler(routingManager, RoutingGroupSelector.byRoutingExternal(httpClient, config.getRoutingRules().getRulesExternalConfiguration(), config.getRequestAnalyzerConfig()), config);
112+
}
113+
114+
@Test
115+
void testBasicHeaderModification()
116+
throws Exception
117+
{
118+
// Setup routing group selector response
119+
Map<String, String> modifiedHeaders = ImmutableMap.of(
120+
"X-Original-Header", "new-value",
121+
"X-New-Header", "new-value");
122+
ExternalRouterResponse mockResponse = new ExternalRouterResponse(
123+
"test-group",
124+
Collections.emptyList(),
125+
modifiedHeaders);
126+
when(httpClient.execute(any(), any())).thenReturn(mockResponse);
127+
128+
// Execute
129+
RoutingTargetResponse response = handler.resolveRouting(request);
130+
131+
// Verify
132+
assertThat(response.modifiedRequest().getHeader("X-Original-Header"))
133+
.isEqualTo("new-value");
134+
assertThat(response.modifiedRequest().getHeader("X-New-Header"))
135+
.isEqualTo("new-value");
136+
}
137+
138+
@Test
139+
void testExcludedHeaders()
140+
throws Exception
141+
{
142+
// Setup routing group selector response
143+
Map<String, String> modifiedHeaders = ImmutableMap.of(
144+
"Authorization", "new-token",
145+
"Cookie", "new-session");
146+
ExternalRouterResponse mockResponse = new ExternalRouterResponse(
147+
"test-group",
148+
Collections.emptyList(),
149+
modifiedHeaders);
150+
when(httpClient.execute(any(), any())).thenReturn(mockResponse);
151+
152+
// Execute
153+
RoutingTargetResponse response = handler.resolveRouting(request);
154+
155+
// Verify sensitive headers are not modified
156+
assertThat(response.modifiedRequest().getHeader("Authorization"))
157+
.isEqualTo("secret-token");
158+
assertThat(response.modifiedRequest().getHeader("Cookie"))
159+
.isEqualTo("session-id");
160+
}
161+
162+
@Test
163+
void testNoHeaderModification()
164+
throws Exception
165+
{
166+
// Setup routing group selector response with no header modifications
167+
ExternalRouterResponse mockResponse = new ExternalRouterResponse(
168+
"test-group",
169+
Collections.emptyList(),
170+
ImmutableMap.of());
171+
when(httpClient.execute(any(), any())).thenReturn(mockResponse);
172+
173+
// Execute
174+
RoutingTargetResponse response = handler.resolveRouting(request);
175+
176+
// Verify original headers are preserved
177+
assertThat(response.modifiedRequest().getHeader("X-Original-Header"))
178+
.isNull();
179+
}
180+
181+
@Test
182+
void testEmptyHeader()
183+
throws Exception
184+
{
185+
// Setup routing group selector response
186+
Map<String, String> modifiedHeaders = ImmutableMap.of(
187+
"X-Empty-Header", "",
188+
"X-New-Header", "new-value");
189+
ExternalRouterResponse mockResponse = new ExternalRouterResponse(
190+
"test-group",
191+
Collections.emptyList(),
192+
modifiedHeaders);
193+
when(httpClient.execute(any(), any())).thenReturn(mockResponse);
194+
195+
// Execute
196+
RoutingTargetResponse response = handler.resolveRouting(request);
197+
198+
// Verify
199+
assertThat(response.modifiedRequest().getHeader("X-Empty-Header"))
200+
.isEmpty();
201+
assertThat(response.modifiedRequest().getHeader("X-New-Header"))
202+
.isEqualTo("new-value");
203+
}
204+
205+
@Test
206+
void testEmptyRoutingGroup()
207+
throws Exception
208+
{
209+
// Setup routing group selector response with empty routing group
210+
Map<String, String> modifiedHeaders = ImmutableMap.of(
211+
"X-Empty-Group-Header", "should-be-set");
212+
ExternalRouterResponse mockResponse = new ExternalRouterResponse(
213+
"",
214+
Collections.emptyList(),
215+
modifiedHeaders);
216+
when(httpClient.execute(any(), any())).thenReturn(mockResponse);
217+
218+
// Execute
219+
RoutingTargetResponse response = handler.resolveRouting(request);
220+
221+
// Verify that when no routing group header is set, we default to "adhoc"
222+
assertThat(response.routingDestination().routingGroup()).isEqualTo("adhoc");
223+
assertThat(response.modifiedRequest().getHeader("X-Empty-Group-Header"))
224+
.isEqualTo("should-be-set");
225+
}
226+
227+
@Test
228+
void testErrorsGiven()
229+
throws Exception
230+
{
231+
// Setup routing group selector response with errors
232+
Map<String, String> modifiedHeaders = ImmutableMap.of(
233+
"X-New-Header", "new-value");
234+
List<String> someErrors = Arrays.asList("ErrorA", "ErrorB");
235+
ExternalRouterResponse mockResponse = new ExternalRouterResponse(
236+
"test-group", // This value should be ignored due to errors
237+
someErrors,
238+
modifiedHeaders);
239+
when(httpClient.execute(any(), any())).thenReturn(mockResponse);
240+
241+
// Execute
242+
RoutingTargetResponse response = handler.resolveRouting(request);
243+
244+
// Verify that when errors are present, we default to "adhoc" group
245+
assertThat(response.routingDestination().routingGroup()).isEqualTo("adhoc");
246+
}
247+
}

0 commit comments

Comments
 (0)