mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-21 23:58:06 +00:00
376 lines
14 KiB
Java
376 lines
14 KiB
Java
package io.datahubproject.metadata.context;
|
|
|
|
import static org.mockito.Mockito.*;
|
|
import static org.testng.Assert.*;
|
|
|
|
import com.google.common.net.HttpHeaders;
|
|
import com.linkedin.metadata.Constants;
|
|
import com.linkedin.metadata.utils.metrics.MetricUtils;
|
|
import com.linkedin.restli.server.ResourceContext;
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import org.mockito.MockedStatic;
|
|
import org.mockito.Mockito;
|
|
import org.testng.annotations.AfterMethod;
|
|
import org.testng.annotations.BeforeMethod;
|
|
import org.testng.annotations.Test;
|
|
|
|
public class RequestContextTest {
|
|
|
|
private HttpServletRequest mockHttpRequest;
|
|
private ResourceContext mockResourceContext;
|
|
private Map<String, String> mockHeaders;
|
|
private MockedStatic<MetricUtils> mockedMetrics;
|
|
private com.codahale.metrics.Counter mockCounter;
|
|
|
|
@BeforeMethod
|
|
public void setup() {
|
|
// Mock HTTP Servlet Request
|
|
mockHttpRequest = Mockito.mock(HttpServletRequest.class);
|
|
when(mockHttpRequest.getHeader(HttpHeaders.USER_AGENT)).thenReturn("Mozilla/5.0");
|
|
when(mockHttpRequest.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn("192.168.1.100");
|
|
when(mockHttpRequest.getRemoteAddr()).thenReturn("10.0.0.1");
|
|
|
|
// Mock ResourceContext
|
|
mockResourceContext = Mockito.mock(ResourceContext.class);
|
|
mockHeaders = new HashMap<>();
|
|
mockHeaders.put(HttpHeaders.USER_AGENT, "RestClient/1.0");
|
|
mockHeaders.put(HttpHeaders.X_FORWARDED_FOR, "192.168.1.101");
|
|
when(mockResourceContext.getRequestHeaders()).thenReturn(mockHeaders);
|
|
when(mockResourceContext.getRawRequestContext())
|
|
.thenReturn(mock(com.linkedin.r2.message.RequestContext.class));
|
|
when(mockResourceContext.getRawRequestContext().getLocalAttr("REMOTE_ADDR"))
|
|
.thenReturn("10.0.0.2");
|
|
|
|
// Mock MetricUtils for testing captureAPIMetrics
|
|
mockCounter = Mockito.mock(com.codahale.metrics.Counter.class);
|
|
mockedMetrics = Mockito.mockStatic(MetricUtils.class);
|
|
mockedMetrics.when(() -> MetricUtils.counter(anyString())).thenReturn(mockCounter);
|
|
}
|
|
|
|
@Test
|
|
public void testBuilderDefault() {
|
|
// Instead of directly calling .build(), use buildRestli method
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(
|
|
"urn:li:corpuser:testuser",
|
|
null, // null ResourceContext
|
|
"test-request",
|
|
"TestEntity");
|
|
|
|
assertEquals(context.getActorUrn(), "urn:li:corpuser:testuser");
|
|
assertEquals(context.getSourceIP(), ""); // Empty string since ResourceContext is null
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.RESTLI);
|
|
assertEquals(context.getRequestID(), "test-request([TestEntity])");
|
|
assertEquals(context.getUserAgent(), ""); // Empty string since ResourceContext is null
|
|
assertNotNull(context.getAgentClass());
|
|
}
|
|
|
|
@Test
|
|
public void testBuildGraphql() {
|
|
Map<String, Object> variables = new HashMap<>();
|
|
variables.put("key", "value");
|
|
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildGraphql(Constants.DATAHUB_ACTOR, mockHttpRequest, "GetUserQuery", variables);
|
|
|
|
assertEquals(context.getActorUrn(), Constants.DATAHUB_ACTOR);
|
|
assertEquals(context.getSourceIP(), "192.168.1.100");
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.GRAPHQL);
|
|
assertEquals(context.getRequestID(), "GetUserQuery");
|
|
assertEquals(context.getUserAgent(), "Mozilla/5.0");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRestliWithAction() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(Constants.SYSTEM_ACTOR, mockResourceContext, "GetMetadata");
|
|
|
|
assertEquals(context.getActorUrn(), Constants.SYSTEM_ACTOR);
|
|
assertEquals(context.getSourceIP(), "192.168.1.101");
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.RESTLI);
|
|
assertEquals(context.getRequestID(), "GetMetadata");
|
|
assertEquals(context.getUserAgent(), "RestClient/1.0");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRestliWithActionAndEntity() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(Constants.SYSTEM_ACTOR, mockResourceContext, "GetMetadata", "dataset");
|
|
|
|
assertEquals(context.getActorUrn(), Constants.SYSTEM_ACTOR);
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.RESTLI);
|
|
assertEquals(context.getRequestID(), "GetMetadata([dataset])");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRestliWithActionAndEntityArray() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(
|
|
Constants.SYSTEM_ACTOR,
|
|
mockResourceContext,
|
|
"GetMetadata",
|
|
new String[] {"dataset", "dashboard"});
|
|
|
|
assertEquals(context.getActorUrn(), Constants.SYSTEM_ACTOR);
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.RESTLI);
|
|
assertEquals(context.getRequestID(), "GetMetadata([dataset, dashboard])");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRestliWithActionAndEntityCollection() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(
|
|
Constants.SYSTEM_ACTOR,
|
|
mockResourceContext,
|
|
"GetMetadata",
|
|
Arrays.asList("dataset", "dashboard", "chart"));
|
|
|
|
assertEquals(context.getActorUrn(), Constants.SYSTEM_ACTOR);
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.RESTLI);
|
|
assertEquals(context.getRequestID(), "GetMetadata([dataset, dashboard, chart])");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRestliWithNullResourceContext() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(Constants.SYSTEM_ACTOR, null, "GetMetadata", "dataset");
|
|
|
|
assertEquals(context.getActorUrn(), Constants.SYSTEM_ACTOR);
|
|
assertEquals(context.getSourceIP(), "");
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.RESTLI);
|
|
assertEquals(context.getUserAgent(), "");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildOpenapiWithEntity() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildOpenapi(Constants.DATAHUB_ACTOR, mockHttpRequest, "GetMetadata", "chart");
|
|
|
|
assertEquals(context.getActorUrn(), Constants.DATAHUB_ACTOR);
|
|
assertEquals(context.getSourceIP(), "192.168.1.100");
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.OPENAPI);
|
|
assertEquals(context.getRequestID(), "GetMetadata([chart])");
|
|
assertEquals(context.getUserAgent(), "Mozilla/5.0");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildOpenapiWithEntityCollection() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildOpenapi(
|
|
Constants.DATAHUB_ACTOR,
|
|
mockHttpRequest,
|
|
"GetMetadata",
|
|
Arrays.asList("dataset", "chart"));
|
|
|
|
assertEquals(context.getActorUrn(), Constants.DATAHUB_ACTOR);
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.OPENAPI);
|
|
assertEquals(context.getRequestID(), "GetMetadata([dataset, chart])");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildOpenapiWithNullRequest() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildOpenapi(Constants.DATAHUB_ACTOR, null, "GetMetadata", "chart");
|
|
|
|
assertEquals(context.getActorUrn(), Constants.DATAHUB_ACTOR);
|
|
assertEquals(context.getSourceIP(), "");
|
|
assertEquals(context.getRequestAPI(), RequestContext.RequestAPI.OPENAPI);
|
|
assertEquals(context.getUserAgent(), "");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRequestIdWithNoEntities() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(
|
|
Constants.SYSTEM_ACTOR, mockResourceContext, "GetMetadata", (List<String>) null);
|
|
|
|
assertEquals(context.getRequestID(), "GetMetadata");
|
|
}
|
|
|
|
@Test
|
|
public void testBuildRequestIdWithEmptyEntities() {
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli(
|
|
Constants.SYSTEM_ACTOR,
|
|
mockResourceContext,
|
|
"GetMetadata",
|
|
Collections.emptyList());
|
|
|
|
assertEquals(context.getRequestID(), "GetMetadata");
|
|
}
|
|
|
|
@Test
|
|
public void testGetCacheKeyComponent() {
|
|
RequestContext context = RequestContext.TEST;
|
|
assertFalse(context.getCacheKeyComponent().isPresent());
|
|
}
|
|
|
|
@Test
|
|
public void testToString() {
|
|
// Using buildRestli instead of direct build()
|
|
RequestContext context =
|
|
RequestContext.builder().buildRestli("urn:li:corpuser:testuser", null, "test-request");
|
|
|
|
String toString = context.toString();
|
|
assertTrue(toString.contains("actorUrn='urn:li:corpuser:testuser'"));
|
|
assertTrue(toString.contains("sourceIP=''"));
|
|
assertTrue(toString.contains("requestAPI=RESTLI"));
|
|
assertTrue(toString.contains("requestID='test-request'"));
|
|
assertTrue(toString.contains("userAgent=''"));
|
|
assertTrue(toString.contains("agentClass='"));
|
|
}
|
|
|
|
@Test
|
|
public void testTestConstant() {
|
|
RequestContext test = RequestContext.TEST;
|
|
assertEquals(test.getRequestID(), "test");
|
|
assertEquals(test.getRequestAPI(), RequestContext.RequestAPI.TEST);
|
|
}
|
|
|
|
@Test
|
|
public void testCaptureAPIMetricsForSystemUser() {
|
|
// Using buildRestli instead of direct build()
|
|
RequestContext context =
|
|
RequestContext.builder().buildRestli(Constants.SYSTEM_ACTOR, null, "test-request");
|
|
|
|
// Verify that the counter was incremented
|
|
verify(mockCounter, times(1)).inc();
|
|
}
|
|
|
|
@Test
|
|
public void testCaptureAPIMetricsForDatahubUser() {
|
|
// Using buildRestli instead of direct build()
|
|
RequestContext context =
|
|
RequestContext.builder().buildRestli(Constants.DATAHUB_ACTOR, null, "test-request");
|
|
|
|
// Verify that the counter was incremented
|
|
verify(mockCounter, times(1)).inc();
|
|
}
|
|
|
|
@Test
|
|
public void testCaptureAPIMetricsForRegularUser() {
|
|
// Using buildRestli instead of direct build()
|
|
RequestContext context =
|
|
RequestContext.builder().buildRestli("urn:li:corpuser:testuser", null, "test-request");
|
|
|
|
// Verify that the counter was incremented
|
|
verify(mockCounter, times(1)).inc();
|
|
}
|
|
|
|
@Test
|
|
public void testEmptyUserAgent() {
|
|
// Mock a ResourceContext with empty user agent
|
|
ResourceContext emptyUAResourceContext = Mockito.mock(ResourceContext.class);
|
|
Map<String, String> emptyUAHeaders = new HashMap<>();
|
|
emptyUAHeaders.put(HttpHeaders.USER_AGENT, "");
|
|
when(emptyUAResourceContext.getRequestHeaders()).thenReturn(emptyUAHeaders);
|
|
when(emptyUAResourceContext.getRawRequestContext())
|
|
.thenReturn(mock(com.linkedin.r2.message.RequestContext.class));
|
|
when(emptyUAResourceContext.getRawRequestContext().getLocalAttr("REMOTE_ADDR"))
|
|
.thenReturn("10.0.0.2");
|
|
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli("urn:li:corpuser:testuser", emptyUAResourceContext, "test-request");
|
|
|
|
// Verify that the agentClass is set to "Unknown"
|
|
assertEquals("Unknown", context.getAgentClass());
|
|
|
|
// Verify that a metric was captured with "unknown" agent class
|
|
verify(mockCounter, times(1)).inc();
|
|
}
|
|
|
|
@Test
|
|
public void testNullUserAgent() {
|
|
try {
|
|
// Create a ResourceContext with null headers map
|
|
ResourceContext nullUAResourceContext = Mockito.mock(ResourceContext.class);
|
|
when(nullUAResourceContext.getRequestHeaders()).thenReturn(Collections.emptyMap());
|
|
when(nullUAResourceContext.getRawRequestContext())
|
|
.thenReturn(mock(com.linkedin.r2.message.RequestContext.class));
|
|
when(nullUAResourceContext.getRawRequestContext().getLocalAttr("REMOTE_ADDR"))
|
|
.thenReturn("10.0.0.2");
|
|
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli("urn:li:corpuser:testuser", nullUAResourceContext, "test-request");
|
|
|
|
// Verify agent class is set to "Unknown" for null user agent
|
|
assertEquals("Unknown", context.getAgentClass());
|
|
|
|
// Verify a metric was captured
|
|
verify(mockCounter, atLeastOnce()).inc();
|
|
} catch (NullPointerException e) {
|
|
fail("RequestContext should handle null userAgent gracefully");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testAgentClassPopulated() {
|
|
// Create a direct instance of RequestContext with a browser user agent
|
|
RequestContext context =
|
|
new RequestContext(
|
|
"urn:li:corpuser:testuser",
|
|
"192.168.1.1",
|
|
RequestContext.RequestAPI.TEST,
|
|
"test-request",
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
|
|
|
|
// Verify the agentClass is populated (exact value will depend on the UserAgentAnalyzer library
|
|
// results)
|
|
assertNotNull(context.getAgentClass());
|
|
// The agent class should be "Browser" for this user agent string, but we're only checking it's
|
|
// not null
|
|
assertFalse(context.getAgentClass().isEmpty());
|
|
}
|
|
|
|
@Test
|
|
public void testAgentClassWithMetrics() {
|
|
// Create a ResourceContext with browser user agent
|
|
ResourceContext browserUAResourceContext = Mockito.mock(ResourceContext.class);
|
|
Map<String, String> browserUAHeaders = new HashMap<>();
|
|
browserUAHeaders.put(
|
|
HttpHeaders.USER_AGENT,
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
|
|
when(browserUAResourceContext.getRequestHeaders()).thenReturn(browserUAHeaders);
|
|
when(browserUAResourceContext.getRawRequestContext())
|
|
.thenReturn(mock(com.linkedin.r2.message.RequestContext.class));
|
|
when(browserUAResourceContext.getRawRequestContext().getLocalAttr("REMOTE_ADDR"))
|
|
.thenReturn("10.0.0.2");
|
|
|
|
RequestContext context =
|
|
RequestContext.builder()
|
|
.buildRestli("urn:li:corpuser:testuser", browserUAResourceContext, "test-request");
|
|
|
|
// Verify the agentClass is populated
|
|
assertNotNull(context.getAgentClass());
|
|
|
|
// Verify a metric was captured
|
|
verify(mockCounter, times(1)).inc();
|
|
}
|
|
|
|
@AfterMethod
|
|
public void tearDown() {
|
|
if (mockedMetrics != null) {
|
|
mockedMetrics.close();
|
|
}
|
|
}
|
|
}
|