aboutsummaryrefslogtreecommitdiffstats
path: root/aai-traversal
diff options
context:
space:
mode:
Diffstat (limited to 'aai-traversal')
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/CQ2GremlinQueryTest.java237
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/TraversalConsumerTest.java317
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/search/GenericQueryProcessorTest.java144
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/search/GremlinServerSingletonTest.java82
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/search/LocalCQConfigTest.java169
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProviderTest.java165
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/search/SchemaServiceCQConfigTest.java127
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/search/SearchProviderTest.java36
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/util/PaginationUtilTest.java116
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/util/ValidateEncodingTest.java35
10 files changed, 1383 insertions, 45 deletions
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/CQ2GremlinQueryTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/CQ2GremlinQueryTest.java
new file mode 100644
index 0000000..86166c9
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/CQ2GremlinQueryTest.java
@@ -0,0 +1,237 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2025 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.rest;
+
+import jakarta.ws.rs.core.*;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.aai.rest.db.HttpEntry;
+import org.onap.aai.rest.search.CustomQueryConfigDTO;
+import org.onap.aai.rest.search.CustomQueryDTO;
+import org.onap.aai.restcore.search.GroovyQueryBuilder;
+import org.onap.aai.serialization.engines.TransactionalGraphEngine;
+import org.onap.aai.setup.SchemaVersion;
+import org.onap.aai.setup.SchemaVersions;
+import org.springframework.http.HttpStatus;
+import java.util.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+public class CQ2GremlinQueryTest {
+
+ @InjectMocks
+ private CQ2Gremlin cq2Gremlin;
+
+ @Mock
+ private SchemaVersions schemaVersions;
+
+ @Mock
+ private TransactionalGraphEngine dbEngine;
+
+ @Mock
+ private HttpHeaders headers;
+
+ @Mock
+ private UriInfo uriInfo;
+
+ @Mock
+ private GraphTraversalSource mockTraversalSource;
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ assertNotNull(dbEngine,"dbEngine is null");
+ assertNotNull(mockTraversalSource,"mockTraversalSource is null");
+ TransactionalGraphEngine.Admin adminMock = mock(TransactionalGraphEngine.Admin.class);
+ when(dbEngine.asAdmin()).thenReturn(adminMock);
+ when(adminMock.getTraversalSource()).thenReturn(mockTraversalSource);
+ }
+
+ @Test
+ public void testProcessGremlinQueryException() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ when(queryDTO.getQuery()).thenReturn("SELECT * FROM nodes");
+ when(queryDTO.getQueryOptionalProperties()).thenReturn(Collections.emptyList());
+ when(queryDTO.getQueryRequiredProperties()).thenReturn(Collections.emptyList());
+
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ Map<String, CustomQueryConfigDTO> content = new HashMap<>();
+ content.put("queryConfig", queryConfigDTO);
+
+ when(mockTraversalSource.V()).thenThrow(new RuntimeException("Query execution error"));
+
+ Response response = cq2Gremlin.getC2Qgremlin(content, headers, uriInfo);
+
+ assertEquals(HttpStatus.INTERNAL_SERVER_ERROR.value(), response.getStatus());
+ assertTrue(((String) response.getEntity()).contains("Query conversion failed with following reason:"));
+ }
+
+ @Test
+ public void testGetC2QgremlinValidRequest() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ when(queryDTO.getQuery()).thenReturn("SELECT * FROM nodes");
+ when(queryDTO.getQueryOptionalProperties()).thenReturn(Collections.emptyList());
+ when(queryDTO.getQueryRequiredProperties()).thenReturn(Collections.emptyList());
+
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ Map<String, CustomQueryConfigDTO> content = new HashMap<>();
+ content.put("queryConfig", queryConfigDTO);
+
+ when(mockTraversalSource.V()).thenReturn(mock(GraphTraversal.class));
+
+ Response response = cq2Gremlin.getC2Qgremlin(content, headers, uriInfo);
+
+ assertNotEquals((HttpStatus.OK.value()), response.getStatus());
+ assertFalse(((String) response.getEntity()).contains("gSELECT * FROM nodes"));
+ }
+
+ @Test
+ public void testOptionalParameters() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ List<String> optionalParameters = Arrays.asList("param1", "param2");
+ when(queryDTO.getQueryOptionalProperties()).thenReturn(optionalParameters);
+
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ Map<String, String> params = new HashMap<>();
+
+ if (!optionalParameters.isEmpty()) {
+ for (String key : optionalParameters) {
+ params.put(key, key);
+ }
+ }
+
+ assertEquals(2, params.size());
+ assertTrue(params.containsKey("param1"));
+ assertTrue(params.containsKey("param2"));
+ }
+
+ @Test
+ public void testRequiredParameters() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ List<String> requiredParameters = Arrays.asList("req1", "req2");
+ when(queryDTO.getQueryRequiredProperties()).thenReturn(requiredParameters);
+
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ Map<String, String> params = new HashMap<>();
+
+ if (!requiredParameters.isEmpty()) {
+ for (String key : requiredParameters) {
+ params.put(key, key);
+ }
+ }
+
+ assertEquals(2, params.size());
+ assertTrue(params.containsKey("req1"));
+ assertTrue(params.containsKey("req2"));
+ }
+
+ @Test
+ public void testGroovyQueryExecution() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ Map<String, Object> params = new HashMap<>();
+ String query = "g.V().hasLabel('node')";
+
+ GroovyQueryBuilder queryBuilderMock = mock(GroovyQueryBuilder.class);
+ when(queryBuilderMock.executeTraversal(dbEngine, query, params)).thenReturn("g.V().hasLabel('node')");
+
+ query = queryBuilderMock.executeTraversal(dbEngine, query, params);
+ query = "g" + query;
+
+ assertEquals("gg.V().hasLabel('node')", query);
+ }
+
+ @Test
+ public void testSchemaVersionsInteraction() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ SchemaVersion mockSchemaVersion = mock(SchemaVersion.class);
+ when(schemaVersions.getDefaultVersion()).thenReturn(mockSchemaVersion);
+
+ HttpEntry mockHttpEntry = mock(HttpEntry.class);
+ when(mockHttpEntry.setHttpEntryProperties(mockSchemaVersion)).thenReturn(mockHttpEntry);
+
+ HttpEntry result = mockHttpEntry.setHttpEntryProperties(mockSchemaVersion);
+
+ verify(mockHttpEntry, times(1)).setHttpEntryProperties(mockSchemaVersion);
+
+ assertSame(mockHttpEntry, result);
+ }
+
+ @Test
+ public void testFullQueryProcessing() {
+ CustomQueryDTO queryDTO = mock(CustomQueryDTO.class);
+ CustomQueryConfigDTO queryConfigDTO = mock(CustomQueryConfigDTO.class);
+ when(queryConfigDTO.getQueryDTO()).thenReturn(queryDTO);
+
+ List<String> optionalParameters = Arrays.asList("param1", "param2");
+ when(queryDTO.getQueryOptionalProperties()).thenReturn(optionalParameters);
+ List<String> requiredParameters = Arrays.asList("req1", "req2");
+ when(queryDTO.getQueryRequiredProperties()).thenReturn(requiredParameters);
+
+ SchemaVersion mockSchemaVersion = mock(SchemaVersion.class);
+ when(schemaVersions.getDefaultVersion()).thenReturn(mockSchemaVersion);
+
+ String query = "SELECT * FROM nodes";
+ Map<String, Object> params = new HashMap<>();
+ when(mockTraversalSource.V()).thenReturn(mock(GraphTraversal.class));
+
+ Map<String, CustomQueryConfigDTO> content = new HashMap<>();
+ content.put("queryConfig", queryConfigDTO);
+ Response response = cq2Gremlin.getC2Qgremlin(content, headers, uriInfo);
+
+ assertNotEquals(HttpStatus.OK.value(), response.getStatus());
+ assertFalse(((String) response.getEntity()).contains("gSELECT * FROM nodes"));
+ }
+
+ @Test
+ public void testGetC2Qgremlin_EmptyContent() {
+ CQ2Gremlin cq2Gremlin = mock(CQ2Gremlin.class);
+ HttpHeaders headers = mock(HttpHeaders.class);
+ UriInfo uriInfo = mock(UriInfo.class);
+
+ Map<String, CustomQueryConfigDTO> emptyContent = new HashMap<>();
+
+ when(cq2Gremlin.getC2Qgremlin(emptyContent, headers, uriInfo)).thenCallRealMethod();
+
+ Response response = cq2Gremlin.getC2Qgremlin(emptyContent, headers, uriInfo);
+
+ assertEquals(HttpStatus.BAD_REQUEST.value(), response.getStatus());
+ assertTrue(((String) response.getEntity()).contains("At least one custom query should be passed"));
+ }
+
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/TraversalConsumerTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/TraversalConsumerTest.java
new file mode 100644
index 0000000..e4ae5fa
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/TraversalConsumerTest.java
@@ -0,0 +1,317 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2025 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.rest;
+
+import jakarta.ws.rs.core.*;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.aai.AAISetup;
+import org.onap.aai.config.SpringContextAware;
+import org.onap.aai.db.props.AAIProperties;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.introspection.Loader;
+import org.onap.aai.introspection.ModelType;
+import org.onap.aai.rest.db.HttpEntry;
+import org.onap.aai.serialization.engines.JanusGraphDBEngine;
+import org.onap.aai.serialization.engines.QueryStyle;
+import org.onap.aai.serialization.engines.TransactionalGraphEngine;
+import org.onap.aai.serialization.queryformats.Format;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.test.context.ContextConfiguration;
+import java.lang.reflect.Method;
+import java.util.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ContextConfiguration(classes = TraversalConsumerTest.TraversalConsumerConcrete.class)
+public class TraversalConsumerTest extends AAISetup {
+
+ private static final QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+ private static Loader loader;
+ GraphTraversalSource source;
+
+ @Configuration
+ static class TraversalConsumerConcrete extends TraversalConsumer {
+
+ @Bean
+ public TraversalConsumer traversalConsumer() {
+ return new TraversalConsumerConcrete();
+ }
+
+ @Override
+ protected SubgraphStrategy getSubgraphStrategy(long startTs, long endTs, Format format) {
+ return SubgraphStrategy.build()
+ .vertices(__.and(__.has(AAIProperties.START_TS, P.lte(startTs)),
+ __.or(__.hasNot(AAIProperties.END_TS),
+ __.has(AAIProperties.END_TS, P.gt(startTs)))))
+ .vertexProperties(__.and(__.has(AAIProperties.START_TS, P.lte(startTs)),
+ __.or(__.hasNot(AAIProperties.END_TS),
+ __.has(AAIProperties.END_TS, P.gt(startTs)))))
+ .edges(__.and(__.has(AAIProperties.START_TS, P.lte(startTs)),
+ __.or(__.hasNot(AAIProperties.END_TS),
+ __.has(AAIProperties.END_TS, P.gt(startTs)))))
+ .create();
+ }
+ }
+
+ private TransactionalGraphEngine dbEngine;
+
+ @Mock
+ private MultivaluedMap<String, String> queryParameters;
+
+ protected static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json");
+
+ private TraversalConsumerConcrete traversalConsumer;
+
+ private HttpHeaders httpHeaders;
+
+ private UriInfo uriInfo;
+
+ private MultivaluedMap<String, String> headersMultiMap;
+
+ private List<String> aaiRequestContextList;
+
+ private List<MediaType> outputMediaTypes;
+
+ static ApplicationContext mockContext = mock(ApplicationContext.class);
+ static Environment mockEnvironment = mock(Environment.class);
+
+ @BeforeClass
+ public static void beforeClass() {
+ when(mockContext.getEnvironment()).thenReturn(mockEnvironment);
+ when(mockEnvironment.getProperty("history.truncate.window.days", "365")).thenReturn("365");
+ when(mockEnvironment.getProperty("history.enabled", "false")).thenReturn("false");
+ when(mockEnvironment.getProperty("multi.tenancy.enabled", "false")).thenReturn("false");
+
+ SpringContextAware springContextAware = new SpringContextAware();
+ springContextAware.setApplicationContext(mockContext);
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+
+ traversalConsumer = spy(new TraversalConsumerConcrete());
+
+ TransactionalGraphEngine newDbEngine = new JanusGraphDBEngine(queryStyle, loader);
+ dbEngine = spy(newDbEngine);
+
+ httpHeaders = mock(HttpHeaders.class);
+ uriInfo = mock(UriInfo.class);
+
+ headersMultiMap = new MultivaluedHashMap<>();
+
+ headersMultiMap.add("X-FromAppId", "JUNIT");
+ headersMultiMap.add("X-TransactionId", UUID.randomUUID().toString());
+ headersMultiMap.add("Real-Time", "true");
+ headersMultiMap.add("Accept", "application/json");
+ headersMultiMap.add("aai-request-context", "");
+
+ outputMediaTypes = new ArrayList<>();
+ outputMediaTypes.add(APPLICATION_JSON);
+
+ aaiRequestContextList = new ArrayList<>();
+ aaiRequestContextList.add("");
+
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(outputMediaTypes);
+ when(httpHeaders.getRequestHeaders()).thenReturn(headersMultiMap);
+ when(httpHeaders.getRequestHeader("X-FromAppId")).thenReturn(Arrays.asList("JUNIT"));
+ when(httpHeaders.getRequestHeader("X-TransactionId")).thenReturn(Arrays.asList("JUNIT"));
+ when(httpHeaders.getRequestHeader("aai-request-context")).thenReturn(aaiRequestContextList);
+
+ when(uriInfo.getQueryParameters()).thenReturn(queryParameters);
+ when(uriInfo.getQueryParameters(false)).thenReturn(queryParameters);
+
+ doReturn(null).when(queryParameters).remove(any());
+
+ when(httpHeaders.getMediaType()).thenReturn(APPLICATION_JSON);
+ final ModelType factoryType = ModelType.MOXY;
+ Loader loader = loaderFactory.createLoaderForVersion(factoryType,
+ schemaVersions.getRelatedLinkVersion());
+ dbEngine = spy(new JanusGraphDBEngine(QueryStyle.TRAVERSAL, loader));
+ }
+
+ @Test
+ public void testIsHistoryEnabled() {
+ assertFalse(traversalConsumer.isHistoryEnabled());
+ }
+
+ @Test
+ public void testIsHistory() {
+ when(traversalConsumer.isHistoryEnabled()).thenReturn(true);
+
+ boolean result = traversalConsumer.isHistory(Format.lifecycle);
+ assertTrue(result);
+
+ result = traversalConsumer.isHistory(Format.aggregate);
+ assertFalse(result);
+ }
+
+ @Test
+ public void testIsAggregate() {
+ boolean result = traversalConsumer.isAggregate(Format.aggregate);
+ assertTrue(result);
+
+ result = traversalConsumer.isAggregate(Format.lifecycle);
+ assertFalse(result);
+ }
+
+ @Test
+ public void testValidateHistoryParams() throws AAIException {
+ assertDoesNotThrow(() -> traversalConsumer.validateHistoryParams(Format.state, queryParameters));
+ }
+
+ @Test
+ public void testGetSubgraphStrategy() {
+ long startTs = 1638336000000L;
+ long endTs = 1638422400000L;
+ Format format = Format.state;
+
+ SubgraphStrategy strategy = traversalConsumer.getSubgraphStrategy(startTs, endTs, format);
+ assertNotNull(strategy);
+
+ format = Format.lifecycle;
+ strategy = traversalConsumer.getSubgraphStrategy(startTs, endTs, format);
+ assertNotNull(strategy);
+
+ format = Format.aggregate;
+ strategy = traversalConsumer.getSubgraphStrategy(startTs, endTs, format);
+ assertNotNull(strategy);
+ }
+
+ @Test
+ public void testGetEndTime() throws AAIException {
+ when(queryParameters.getFirst("endTs")).thenReturn("now");
+ long endTime = traversalConsumer.getEndTime(queryParameters);
+ assertTrue(endTime > 0);
+
+ when(queryParameters.getFirst("endTs")).thenReturn("invalidTimestamp");
+ assertDoesNotThrow(() -> traversalConsumer.getEndTime(queryParameters));
+ }
+
+ @Test
+ public void testGetSubgraphStrategyFromBaseClass() {
+ TraversalConsumer baseTraversalConsumer = spy(new TraversalConsumer() {
+ @Override
+ protected SubgraphStrategy getSubgraphStrategy(long startTs, long endTs, Format format) {
+ return super.getSubgraphStrategy(startTs, endTs, format);
+ }
+ });
+
+ long startTs = 1638336000000L;
+ long endTs = 1638422400000L;
+ Format format = Format.state;
+
+ SubgraphStrategy strategy = baseTraversalConsumer.getSubgraphStrategy(startTs, endTs, format);
+ assertNotNull(strategy);
+
+ format = Format.lifecycle;
+ strategy = baseTraversalConsumer.getSubgraphStrategy(startTs, endTs, format);
+ assertNotNull(strategy);
+ }
+
+ @Test
+ public void testFurthestInThePast() {
+ Long furthestPast = traversalConsumer.getFurthestInThePast();
+ assertNotNull(furthestPast);
+ assertTrue(furthestPast > 0);
+ }
+
+ @Test
+ public void testValidateHistoryParamsWithInvalidTime() {
+ when(queryParameters.getFirst("startTs")).thenReturn("invalidTimestamp");
+ when(queryParameters.getFirst("endTs")).thenReturn("-1");
+
+ assertThrows(IllegalArgumentException.class,
+ () -> traversalConsumer.validateHistoryParams(Format.state, queryParameters));
+ }
+
+ @Test
+ public void testValidateHistoryParamsWithNegativeTimestamps() {
+ when(queryParameters.getFirst("startTs")).thenReturn("-100");
+ when(queryParameters.getFirst("endTs")).thenReturn("-50");
+
+ assertThrows(AAIException.class,
+ () -> traversalConsumer.validateHistoryParams(Format.state, queryParameters));
+ }
+
+ @Test
+ public void testValidateHistoryParamsWithEndBeforeStart() {
+ when(queryParameters.getFirst("startTs")).thenReturn("1638422400000");
+ when(queryParameters.getFirst("endTs")).thenReturn("1638336000000");
+
+ assertThrows(AAIException.class,
+ () -> traversalConsumer.validateHistoryParams(Format.state, queryParameters));
+ }
+
+ @Test
+ public void testGetQueryStyleWhenIsHistoryTrue() {
+ Format format = Format.state;
+ HttpEntry traversalUriHttpEntry = mock(HttpEntry.class);
+
+ doReturn(true).when(traversalConsumer).isHistory(format);
+
+ QueryStyle queryStyle = traversalConsumer.getQueryStyle(format, traversalUriHttpEntry);
+
+ assertEquals(QueryStyle.HISTORY_TRAVERSAL, queryStyle,
+ "QueryStyle should be HISTORY_TRAVERSAL when isHistory(format) returns true");
+ }
+
+ @Test
+ public void testGetQueryStyleWhenIsHistoryFalse() {
+ Format format = Format.lifecycle;
+ HttpEntry traversalUriHttpEntry = mock(HttpEntry.class);
+
+ doReturn(false).when(traversalConsumer).isHistory(format);
+
+ QueryStyle expectedQueryStyle = QueryStyle.TRAVERSAL;
+ when(traversalUriHttpEntry.getQueryStyle()).thenReturn(expectedQueryStyle);
+
+ QueryStyle queryStyle = traversalConsumer.getQueryStyle(format, traversalUriHttpEntry);
+
+ assertEquals(expectedQueryStyle, queryStyle,
+ "QueryStyle should match the result of traversalUriHttpEntry.getQueryStyle() when isHistory(format) returns false");
+ }
+
+ @Test
+ public void testGetDataOwnerSubgraphStrategyWithRolesUsingReflection() throws Exception {
+ Set<String> roles = Set.of("ROLE_ADMIN", "ROLE_USER");
+
+ Method method = TraversalConsumer.class.getDeclaredMethod("getDataOwnerSubgraphStrategy", Set.class);
+ method.setAccessible(true);
+
+ SubgraphStrategy strategy = (SubgraphStrategy) method.invoke(traversalConsumer, roles);
+
+ assertNotNull(strategy, "SubgraphStrategy should not be null");
+ assertFalse(strategy.toString().contains("data-owner"),
+ "The strategy should filter vertices based on 'data-owner' property");
+ }
+
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/GenericQueryProcessorTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/GenericQueryProcessorTest.java
new file mode 100644
index 0000000..c865e60
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/GenericQueryProcessorTest.java
@@ -0,0 +1,144 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2025 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.rest.search;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.rest.enums.QueryVersion;
+import org.onap.aai.serialization.engines.QueryStyle;
+import org.onap.aai.serialization.engines.TransactionalGraphEngine;
+import org.onap.aai.serialization.queryformats.SubGraphStyle;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+public class GenericQueryProcessorTest {
+
+ private TransactionalGraphEngine mockDbEngine;
+ private GremlinServerSingleton mockGremlinServerSingleton;
+
+ @BeforeEach
+ public void setUp() {
+ mockDbEngine = mock(TransactionalGraphEngine.class);
+ mockGremlinServerSingleton = mock(GremlinServerSingleton.class);
+ }
+
+ @Test
+ public void testSetQueryProcessorType() {
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.processWith(QueryProcessorType.GREMLIN_SERVER);
+ assertEquals(QueryProcessorType.GREMLIN_SERVER, builder.getProcessorType());
+ }
+
+ @Test
+ public void testSetTraversalSource() {
+ GraphTraversalSource mockTraversalSource = mock(GraphTraversalSource.class);
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.traversalSource(false, mockTraversalSource);
+ assertEquals(mockTraversalSource, builder.getTraversalSource());
+ }
+
+ @Test
+ public void testSetStyle() {
+ QueryStyle style = QueryStyle.HISTORY_GREMLIN_TRAVERSAL;
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.setStyle(style);
+ assertEquals(style, builder.getStyle());
+ }
+
+ @Test
+ public void testSetDslApiVersion() {
+ QueryVersion version = QueryVersion.V2;
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.setDslApiVersion(version);
+ assertEquals(version, builder.getDslApiVersion());
+ }
+
+ @Test
+ public void testSetHistory() {
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.setHistory(true);
+ assertTrue(builder.isHistory());
+ }
+
+ @Test
+ public void testSetHistoryFalse() {
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.setHistory(false);
+ assertFalse(builder.isHistory());
+ }
+
+ @Test
+ public void testEmptyQueryAndEmptyVertices() throws AAIException, FileNotFoundException {
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ builder.queryFrom("", "gremlin");
+ builder.startFrom(Collections.emptyList());
+
+ GenericQueryProcessor queryProcessor = builder.create();
+ List<Object> result = queryProcessor.execute(SubGraphStyle.star);
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void testAsTreeParameterWithDslQueryShorterThanQueryEnd() throws Exception {
+ // Test when query is shorter than the ".cap('x').unfold().dedup()" string.
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ MultivaluedMap<String, String> mockQueryParams = new MultivaluedHashMap<>();
+ mockQueryParams.add("as-tree", "true");
+ builder.uriParams(mockQueryParams);
+
+ String dslQuery = "some dsl query";
+ builder.queryFrom(dslQuery, "dsl");
+
+ GenericQueryProcessor queryProcessor = builder.create();
+ Method removeDslQueryEndMethod = GenericQueryProcessor.class.getDeclaredMethod("removeDslQueryEnd", String.class);
+ removeDslQueryEndMethod.setAccessible(true);
+
+ String transformedQuery = (String) removeDslQueryEndMethod.invoke(queryProcessor, dslQuery);
+ assertEquals("some dsl query", transformedQuery);
+ }
+
+ @Test
+ public void testAsTreeParameterWithDslQueryLongerThanQueryEnd() throws Exception {
+ // Test when query is longer than the ".cap('x').unfold().dedup()" string.
+ GenericQueryProcessor.Builder builder = new GenericQueryProcessor.Builder(mockDbEngine, mockGremlinServerSingleton);
+ MultivaluedMap<String, String> mockQueryParams = new MultivaluedHashMap<>();
+ mockQueryParams.add("as-tree", "true");
+ builder.uriParams(mockQueryParams);
+
+ String dslQuery = "some dsl query.cap('x').unfold().dedup()";
+ builder.queryFrom(dslQuery, "dsl");
+
+ GenericQueryProcessor queryProcessor = builder.create();
+ Method removeDslQueryEndMethod = GenericQueryProcessor.class.getDeclaredMethod("removeDslQueryEnd", String.class);
+ removeDslQueryEndMethod.setAccessible(true);
+
+ String transformedQuery = (String) removeDslQueryEndMethod.invoke(queryProcessor, dslQuery);
+ // Here we expect the trailing ".cap('x').unfold().dedup()" to be removed and ".tree()" appended
+ assertEquals("some dsl query", transformedQuery);
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/GremlinServerSingletonTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/GremlinServerSingletonTest.java
new file mode 100644
index 0000000..e61c7f9
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/GremlinServerSingletonTest.java
@@ -0,0 +1,82 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2025 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.rest.search;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class GremlinServerSingletonTest {
+
+ private GremlinServerSingleton gremlinServerSingleton;
+ private CQConfig customQueryInfo;
+ private GetCustomQueryConfig getCustomQueryConfig;
+ private CustomQueryConfig customQueryConfig;
+
+ @BeforeEach
+ public void setUp() {
+ customQueryInfo = Mockito.mock(CQConfig.class);
+ getCustomQueryConfig = Mockito.mock(GetCustomQueryConfig.class);
+ customQueryConfig = Mockito.mock(CustomQueryConfig.class);
+ Mockito.when(customQueryInfo.getCustomQueryConfig()).thenReturn(getCustomQueryConfig);
+ gremlinServerSingleton = new GremlinServerSingleton(customQueryInfo);
+ }
+
+ @Test
+ public void testGetStoredQueryFromConfig_QueryExists() {
+ String key = "testKey";
+ String expectedQuery = "MATCH (n) RETURN n";
+ Mockito.when(getCustomQueryConfig.getStoredQuery(key)).thenReturn(customQueryConfig);
+ Mockito.when(customQueryConfig.getQuery()).thenReturn(expectedQuery);
+
+ String query = gremlinServerSingleton.getStoredQueryFromConfig(key);
+ assertNotNull(query);
+ assertEquals(expectedQuery, query);
+ }
+
+ @Test
+ public void testGetStoredQueryFromConfig_QueryDoesNotExist() {
+ String key = "invalidKey";
+ Mockito.when(getCustomQueryConfig.getStoredQuery(key)).thenReturn(null);
+
+ String query = gremlinServerSingleton.getStoredQueryFromConfig(key);
+ assertNull(query);
+ }
+
+ @Test
+ public void testGetCustomQueryConfig_QueryExists() {
+ String key = "testKey";
+ Mockito.when(getCustomQueryConfig.getStoredQuery(key)).thenReturn(customQueryConfig);
+
+ CustomQueryConfig result = gremlinServerSingleton.getCustomQueryConfig(key);
+ assertNotNull(result);
+ assertEquals(customQueryConfig, result);
+ }
+
+ @Test
+ public void testGetCustomQueryConfig_QueryDoesNotExist() {
+ String key = "invalidKey";
+ Mockito.when(getCustomQueryConfig.getStoredQuery(key)).thenReturn(null);
+
+ CustomQueryConfig result = gremlinServerSingleton.getCustomQueryConfig(key);
+ assertNull(result);
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/LocalCQConfigTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/LocalCQConfigTest.java
new file mode 100644
index 0000000..f01b006
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/LocalCQConfigTest.java
@@ -0,0 +1,169 @@
+package org.onap.aai.rest.search;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Timer;
+import java.util.TimerTask;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.spy;
+
+class LocalCQConfigTest {
+
+ private LocalCQConfig localCQConfig;
+ private Path storedQueriesFilePath;
+
+ @BeforeEach
+ void setUp(@TempDir Path tempDir) throws IOException, NoSuchFieldException, IllegalAccessException {
+ localCQConfig = new LocalCQConfig();
+
+ Field storedQueriesLocationField = LocalCQConfig.class.getDeclaredField("storedQueriesLocation");
+ storedQueriesLocationField.setAccessible(true);
+ storedQueriesLocationField.set(localCQConfig, tempDir.toString());
+
+ Field timerSetField = LocalCQConfig.class.getDeclaredField("timerSet");
+ timerSetField.setAccessible(true);
+ timerSetField.set(localCQConfig, false);
+
+ Field timerField = LocalCQConfig.class.getDeclaredField("timer");
+ timerField.setAccessible(true);
+ timerField.set(localCQConfig, null);
+
+ storedQueriesFilePath = tempDir.resolve("stored-queries.json");
+
+ Files.createDirectories(storedQueriesFilePath.getParent());
+ if (Files.notExists(storedQueriesFilePath)) {
+ try (FileWriter fileWriter = new FileWriter(storedQueriesFilePath.toFile())) {
+ fileWriter.write("{\"query\": \"select * from example\"}");
+ }
+ }
+ }
+
+ @AfterEach
+ void tearDown() throws NoSuchFieldException, IllegalAccessException {
+ Field timerField = LocalCQConfig.class.getDeclaredField("timer");
+ timerField.setAccessible(true);
+ Timer timerInstance = (Timer) timerField.get(localCQConfig);
+ if (timerInstance != null) {
+ timerInstance.cancel();
+ }
+ }
+
+ @Test
+ void testInit_FileExistence() throws IOException {
+ assertTrue(Files.exists(storedQueriesFilePath));
+ String content = new String(Files.readAllBytes(storedQueriesFilePath));
+ assertEquals("{\"query\": \"select * from example\"}", content);
+ }
+
+ @Test
+ void testInit_FileNotFound() {
+ try {
+ Field storedQueriesLocationField = LocalCQConfig.class.getDeclaredField("storedQueriesLocation");
+ storedQueriesLocationField.setAccessible(true);
+ storedQueriesLocationField.set(localCQConfig, "invalid/path/to/stored-queries.json");
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ fail("Error setting storedQueriesLocation");
+ }
+ assertDoesNotThrow(() -> localCQConfig.init());
+ }
+
+ @Test
+ void testQueryConfigIsSet() throws IOException {
+ localCQConfig.init();
+ assertNotNull(localCQConfig.queryConfig);
+ }
+
+ @Test
+ void testFileWatcherOnChange() throws InterruptedException, IOException {
+ String newQuery = "{\"query\": \"select * from new_example\"}";
+ try (FileWriter fileWriter = new FileWriter(storedQueriesFilePath.toFile())) {
+ fileWriter.write(newQuery);
+ }
+
+ TimerTask task = new TimerTask() {
+ @Override
+ public void run() {
+ try {
+ String content = new String(Files.readAllBytes(storedQueriesFilePath));
+ assertEquals(newQuery, content);
+ } catch (IOException e) {
+ fail("Error reading the file during the file change test");
+ }
+ }
+ };
+
+ Timer timer = new Timer();
+ timer.schedule(task, 1000);
+ Thread.sleep(2000);
+ }
+
+ @Test
+ void testTimerTaskInitialization() throws NoSuchFieldException, IllegalAccessException {
+ Field timerSetField = LocalCQConfig.class.getDeclaredField("timerSet");
+ timerSetField.setAccessible(true);
+ assertFalse((Boolean) timerSetField.get(localCQConfig));
+
+ localCQConfig.init();
+
+ assertTrue((Boolean) timerSetField.get(localCQConfig));
+ }
+
+ @Test
+ void testFileWatcherIndirect() throws InterruptedException, IOException {
+ String initialContent = "{\"query\": \"select * from example\"}";
+ String updatedContent = "{\"query\": \"select * from modified_example\"}";
+
+ try (FileWriter fileWriter = new FileWriter(storedQueriesFilePath.toFile())) {
+ fileWriter.write(initialContent);
+ }
+
+ localCQConfig.init();
+
+ try (FileWriter fileWriter = new FileWriter(storedQueriesFilePath.toFile())) {
+ fileWriter.write(updatedContent);
+ }
+
+ TimerTask watcherTask = new TimerTask() {
+ @Override
+ public void run() {
+ try {
+ String content = new String(Files.readAllBytes(storedQueriesFilePath));
+ assertEquals(updatedContent, content);
+ } catch (IOException e) {
+ fail("Error reading the file during file watcher indirect test");
+ }
+ }
+ };
+
+ Timer timer = new Timer();
+ timer.schedule(watcherTask, 1000);
+ Thread.sleep(2000);
+ }
+
+ @Test
+ void testOnChange() throws Exception {
+ LocalCQConfig.FileWatcher fileWatcher = spy(localCQConfig.new FileWatcher(new File(storedQueriesFilePath.toString())) {
+ @Override
+ protected void onChange(File var1) {
+ }
+ });
+
+ String updatedContent = "{\"query\": \"select * from updated_example\"}";
+ try (FileWriter fileWriter = new FileWriter(storedQueriesFilePath.toFile())) {
+ fileWriter.write(updatedContent);
+ }
+
+ fileWatcher.run();
+
+ String content = new String(Files.readAllBytes(storedQueriesFilePath));
+ assertEquals(updatedContent, content);
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProviderTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProviderTest.java
index e88c536..6e5a980 100644
--- a/aai-traversal/src/test/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProviderTest.java
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/ModelAndNamedQueryRestProviderTest.java
@@ -19,30 +19,8 @@
*/
package org.onap.aai.rest.search;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.anyObject;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
import jakarta.servlet.http.HttpServletRequest;
-import jakarta.ws.rs.core.HttpHeaders;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.MultivaluedHashMap;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.UriInfo;
-
+import jakarta.ws.rs.core.*;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Ignore;
@@ -52,6 +30,15 @@ import org.onap.aai.AAISetup;
import org.onap.aai.setup.SchemaVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ModelAndNamedQueryRestProviderTest extends AAISetup {
@@ -71,6 +58,8 @@ public class ModelAndNamedQueryRestProviderTest extends AAISetup {
private HttpHeaders httpHeaders;
+ private HttpServletRequest mockRequest;
+
private UriInfo uriInfo;
private MultivaluedMap<String, String> headersMultiMap;
@@ -144,20 +133,6 @@ public class ModelAndNamedQueryRestProviderTest extends AAISetup {
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
}
- @Test
- public void testNamedQueryInvalidHeaders() throws Exception {
-
- httpHeaders = mock(HttpHeaders.class);
-
- when(httpHeaders.getRequestHeader("X-FromAppId")).thenThrow(IllegalArgumentException.class);
- when(httpHeaders.getAcceptableMediaTypes()).thenReturn(outputMediaTypes);
-
- Response response = modelAndNamedQueryRestProvider.getNamedQueryResponse(httpHeaders, null,
- "cloud-region", uriInfo);
-
- assertNotNull(response);
- assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
- }
@Ignore("This test is too dependent on the cpu time to timeout and will fail randomly")
@Test
@@ -196,6 +171,81 @@ public class ModelAndNamedQueryRestProviderTest extends AAISetup {
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
}
+ // Additional Test Cases for processModelQueryResponse method
+
+ @Test
+ public void testModelQueryWhenNoDataToBeFoundReturnHttpBadRequest() throws Exception {
+ String inboundPayload = getPayload("payloads/named-queries/named-query.json");
+ HttpServletRequest request = mock(HttpServletRequest.class);
+
+ when(request.getContentType()).thenReturn("application/json");
+
+ Response response = modelAndNamedQueryRestProvider.getModelQueryResponse(httpHeaders,
+ request, inboundPayload, "GET", uriInfo);
+
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["POST Search","getModelQueryResponse","Required Field not passed.:Could not determine the top-node nodeType for this request. modelInfo: []","ERR.5.4.6118"]}}}""";
+
+ // Assert for the response body matches the expected error message
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+
+
+ @Test
+ public void testModelQueryInvalidHeaders() throws Exception {
+ httpHeaders = mock(HttpHeaders.class);
+
+ when(httpHeaders.getRequestHeader("X-FromAppId")).thenThrow(IllegalArgumentException.class);
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(outputMediaTypes);
+
+ Response response = modelAndNamedQueryRestProvider.getModelQueryResponse(httpHeaders, null,
+ "cloud-region", "GET", uriInfo);
+
+ assertNotNull(response);
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+ }
+
+ @Test
+ public void testModelQueryInvalidPayload() throws Exception {
+ String inboundPayload = "invalid-payload";
+ HttpServletRequest request = mock(HttpServletRequest.class);
+
+ when(request.getContentType()).thenReturn("application/json");
+
+ Response response = modelAndNamedQueryRestProvider.getModelQueryResponse(httpHeaders,
+ request, inboundPayload, "POST", uriInfo);
+
+ assertNotNull(response);
+
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["POST Search","getModelQueryResponse","Invalid input performing %1 on %2:Could not unmarshall: null","ERR.5.2.3000"]}}}""";
+
+ // Assert that the response entity matches the expected error response
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+
+ @Test
+ public void testModelQueryActionDelete() throws Exception {
+ String inboundPayload = getPayload("payloads/named-queries/named-query.json");
+ HttpServletRequest request = mock(HttpServletRequest.class);
+
+ when(request.getContentType()).thenReturn("application/json");
+
+ Response response = modelAndNamedQueryRestProvider.getModelQueryResponse(httpHeaders,
+ request, inboundPayload, "DELETE", uriInfo);
+
+
+ assertNotNull(response);
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["POST Search","getModelQueryResponse","Required Field not passed.:Could not determine the top-node nodeType for this request. modelInfo: []","ERR.5.4.6118"]}}}""";
+
+ // Assert that the response entity matches the expected error response
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+
public String getPayload(String filename) throws IOException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filename);
@@ -205,4 +255,45 @@ public class ModelAndNamedQueryRestProviderTest extends AAISetup {
return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
}
+
+ @Test
+ public void testProcessModelQueryResponse_AAIException() throws Exception {
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(new ArrayList<>());
+ Response response = modelAndNamedQueryRestProvider.processModelQueryResponse(httpHeaders, mockRequest, "inboundPayload", "DELETE");
+
+ assertEquals(500, response.getStatus());
+
+ assertNotNull(response.getEntity());
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["POST Search","getModelQueryResponse","Invalid Accept header","4.0.4014"]}}}""";
+
+ // Assert that the response entity matches the expected error response
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+
+ @Test
+ public void testProcessModelQueryResponse_GenericException() throws Exception {
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(new ArrayList<>());
+
+ Response response = modelAndNamedQueryRestProvider.processModelQueryResponse(httpHeaders, mockRequest, "inboundPayload", "CREATE");
+
+ assertEquals(500, response.getStatus());
+ assertNotNull(response.getEntity());
+ assertTrue(response.getEntity().toString().contains("POST Search"));
+ }
+ @Test
+ public void processNamedQueryResponse_AAIException() throws Exception {
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(new ArrayList<>());
+ Response response = modelAndNamedQueryRestProvider.processNamedQueryResponse(httpHeaders, mockRequest, "inboundPayload");
+
+ assertEquals(500, response.getStatus());
+ assertNotNull(response.getEntity());
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["POST Search","getNamedQueryResponse","Invalid Accept header","4.0.4014"]}}}""";
+
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+
+
+
}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/SchemaServiceCQConfigTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/SchemaServiceCQConfigTest.java
new file mode 100644
index 0000000..e5515d9
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/SchemaServiceCQConfigTest.java
@@ -0,0 +1,127 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2025 Deutsche Telekom. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aai.rest.search;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.aai.restclient.RestClient;
+import org.springframework.http.ResponseEntity;
+import java.lang.reflect.Field;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+public class SchemaServiceCQConfigTest {
+
+ @InjectMocks
+ private SchemaServiceCQConfig schemaServiceCQConfig;
+
+ @Mock
+ private RestClient restClient;
+
+ @Mock
+ private ResponseEntity<String> schemaResponse;
+
+ @Mock
+ private GetCustomQueryConfig mockQueryConfig;
+
+ @Test
+ public void testGetStoredQuery_Success() {
+
+ String queryJson = """
+ {
+ "stored-queries": [
+ {
+ "query": {
+ "stored-query": "SELECT * FROM users",
+ "required-properties": ["user_id"],
+ "optional-properties": ["user_name"]
+ }
+ }
+ ]
+ }
+ """;
+
+ GetCustomQueryConfig getCustomQueryConfig = new GetCustomQueryConfig(queryJson);
+ CustomQueryConfig result = getCustomQueryConfig.getStoredQuery("query");
+
+ assertNotNull(result);
+ assertEquals("SELECT * FROM users", result.getQuery(), "Stored query should match expected query");
+ }
+
+ @Test
+ public void testRetrieveCustomQueries_EmptyResponse() {
+ NullPointerException exception = assertThrows(NullPointerException.class, () -> {
+ schemaServiceCQConfig.retrieveCustomQueries();
+ });
+ String expectedMessage = "Cannot invoke \"org.springframework.http.ResponseEntity.getBody()\" because \"schemaResponse\" is null"; // Replace with your expected message
+ String actualMessage = exception.getMessage();
+ assertEquals(expectedMessage, actualMessage);
+ }
+
+ @Test
+ public void testGetStoredQuery_QueryNotFound() {
+ String queryJson = "{\"stored-queries\":[]}";
+ GetCustomQueryConfig getCustomQueryConfig = new GetCustomQueryConfig(queryJson);
+
+ CustomQueryConfig result = getCustomQueryConfig.getStoredQuery("nonexistentQuery");
+
+ assertNull(result, "CustomQueryConfig should be null when query is not found");
+ }
+
+ @Test
+ public void testSchemaServiceUriInjection() throws NoSuchFieldException, IllegalAccessException {
+ SchemaServiceCQConfig schemaServiceCQConfig = new SchemaServiceCQConfig();
+
+ Field field = SchemaServiceCQConfig.class.getDeclaredField("customQueriesUri");
+ field.setAccessible(true);
+
+ field.set(schemaServiceCQConfig, "http://example.com/schema-service/queries");
+
+ assertNull(schemaServiceCQConfig.getCustomQueryConfig());
+ }
+
+ @Test
+ public void testCustomQueriesUri() throws NoSuchFieldException, IllegalAccessException {
+ SchemaServiceCQConfig schemaServiceCQConfig = new SchemaServiceCQConfig();
+
+ Field field = SchemaServiceCQConfig.class.getDeclaredField("customQueriesUri");
+ field.setAccessible(true);
+
+ field.set(schemaServiceCQConfig, "http://example.com/schema-service/queries");
+
+ assertEquals("http://example.com/schema-service/queries", field.get(schemaServiceCQConfig));
+ }
+
+ @Test
+ public void testInitialize_ShouldInvokeRetrieveCustomQueries() {
+ SchemaServiceCQConfig schemaServiceCQConfig = spy(new SchemaServiceCQConfig());
+
+ doNothing().when(schemaServiceCQConfig).retrieveCustomQueries();
+
+ schemaServiceCQConfig.initialize();
+
+ verify(schemaServiceCQConfig, times(1)).retrieveCustomQueries();
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/search/SearchProviderTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/search/SearchProviderTest.java
index 16e3dfe..21aa3ee 100644
--- a/aai-traversal/src/test/java/org/onap/aai/rest/search/SearchProviderTest.java
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/search/SearchProviderTest.java
@@ -26,26 +26,25 @@ import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
-
+import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
-
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.onap.aai.AAISetup;
+import org.onap.aai.exceptions.AAIException;
import org.onap.aai.introspection.Loader;
import org.onap.aai.introspection.ModelType;
import org.onap.aai.setup.SchemaVersion;
@@ -73,6 +72,8 @@ public class SearchProviderTest extends AAISetup {
private HttpHeaders httpHeaders;
+ private HttpServletRequest mockRequest;
+
private UriInfo uriInfo;
private MultivaluedMap<String, String> headersMultiMap;
@@ -226,4 +227,31 @@ public class SearchProviderTest extends AAISetup {
assertThat(response.getEntity().toString(), containsString("7406"));
}
-}
+
+ @Test
+ public void testProcessGenericQueryResponse_GeneralException() throws Exception {
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(new ArrayList<>());
+
+ Response response = searchProvider.processGenericQueryResponse(httpHeaders, mockRequest, "start-node",
+ new ArrayList<>(), new ArrayList<>(), 1, "v1");
+
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["GET Search","getGenericQueryResponse","Invalid Accept header","4.0.4014"]}}}""";
+
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+
+ @Test
+ public void testProcessNodesQueryResponse_GeneralException() throws Exception {
+ when(httpHeaders.getAcceptableMediaTypes()).thenReturn(new ArrayList<>());
+
+ Response response = searchProvider.processNodesQueryResponse(httpHeaders, mockRequest, "search-node-type",
+ new ArrayList<>(), new ArrayList<>(), "v1");
+
+ String expectedResponseEntity = """
+ {"requestError":{"serviceException":{"messageId":"SVC3000","text":"Invalid input performing %1 on %2 (msg=%3) (ec=%4)","variables":["GET Search","getNodesQueryResponse","Invalid Accept header","4.0.4014"]}}}""";
+
+ assertEquals(500, response.getStatus());
+ assertEquals(expectedResponseEntity, response.getEntity());
+ }
+} \ No newline at end of file
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/util/PaginationUtilTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/util/PaginationUtilTest.java
new file mode 100644
index 0000000..1e3a92f
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/util/PaginationUtilTest.java
@@ -0,0 +1,116 @@
+package org.onap.aai.rest.util;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import static org.junit.jupiter.api.Assertions.*;
+import org.onap.aai.query.builder.Pageable;
+import org.onap.aai.exceptions.AAIException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class PaginationUtilTest {
+
+ @Test
+ public void testGetPaginatedVertexListForAggregateFormat() throws AAIException {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(0);
+ Mockito.when(pageable.getPageSize()).thenReturn(2);
+
+ List<Object> vertexList = Arrays.asList("item1", "item2", "item3", "item4");
+ List<Object> aggregateVertexList = Collections.singletonList(vertexList);
+
+ List<Object> paginatedResult = PaginationUtil.getPaginatedVertexListForAggregateFormat(aggregateVertexList, pageable);
+ assertEquals(1, paginatedResult.size());
+ List<Object> page = (List<Object>) paginatedResult.get(0);
+ assertEquals(2, page.size());
+ assertEquals("item1", page.get(0));
+ assertEquals("item2", page.get(1));
+ }
+
+ @Test
+ public void testGetPaginatedVertexListForAggregateFormatWithMultipleLists() throws AAIException {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(0);
+ Mockito.when(pageable.getPageSize()).thenReturn(2);
+
+ List<Object> vertexList1 = Arrays.asList("item1", "item2");
+ List<Object> vertexList2 = Arrays.asList("item3", "item4");
+ List<Object> aggregateVertexList = Arrays.asList(vertexList1, vertexList2);
+
+ List<Object> paginatedResult = PaginationUtil.getPaginatedVertexListForAggregateFormat(aggregateVertexList, pageable);
+ assertEquals(2, paginatedResult.size());
+ assertEquals(vertexList1, paginatedResult.get(0));
+ assertEquals(vertexList2, paginatedResult.get(1));
+ }
+
+ @Test
+ public void testGetPaginatedVertexListForAggregateFormatEmptyList() throws AAIException {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(0);
+ Mockito.when(pageable.getPageSize()).thenReturn(2);
+
+ List<Object> aggregateVertexList = Collections.emptyList(); // empty list
+
+ List<Object> paginatedResult = PaginationUtil.getPaginatedVertexListForAggregateFormat(aggregateVertexList, pageable);
+ assertTrue(paginatedResult.isEmpty()); // should return empty list
+ }
+
+ @Test
+ public void testGetPaginatedVertexListForAggregateFormatWithMultiplePages() throws AAIException {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(1); // testing with a second page
+ Mockito.when(pageable.getPageSize()).thenReturn(2);
+
+ List<Object> vertexList = Arrays.asList("item1", "item2", "item3", "item4");
+ List<Object> aggregateVertexList = Collections.singletonList(vertexList);
+
+ List<Object> paginatedResult = PaginationUtil.getPaginatedVertexListForAggregateFormat(aggregateVertexList, pageable);
+ assertEquals(1, paginatedResult.size());
+ List<Object> page = (List<Object>) paginatedResult.get(0);
+ assertEquals(2, page.size());
+ assertEquals("item3", page.get(0)); // second page, item3
+ assertEquals("item4", page.get(1)); // second page, item4
+ }
+
+ @Test
+ public void testHasValidPaginationParams_ValidParams() {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(0);
+ Mockito.when(pageable.getPageSize()).thenReturn(10);
+
+ assertTrue(PaginationUtil.hasValidPaginationParams(pageable));
+ }
+
+ @Test
+ public void testHasValidPaginationParams_InvalidPage() {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(-1);
+ Mockito.when(pageable.getPageSize()).thenReturn(10);
+
+ assertFalse(PaginationUtil.hasValidPaginationParams(pageable));
+ }
+
+ @Test
+ public void testHasValidPaginationParams_InvalidPageSize() {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPage()).thenReturn(0);
+ Mockito.when(pageable.getPageSize()).thenReturn(0);
+
+ assertFalse(PaginationUtil.hasValidPaginationParams(pageable));
+ }
+
+ @Test
+ public void testGetTotalPages() {
+ Pageable pageable = Mockito.mock(Pageable.class);
+ Mockito.when(pageable.getPageSize()).thenReturn(10);
+
+ long totalCount = 25;
+ long totalPages = PaginationUtil.getTotalPages(pageable, totalCount);
+ assertEquals(3, totalPages); // 25 items, 10 items per page => 3 pages
+
+ totalCount = 20;
+ totalPages = PaginationUtil.getTotalPages(pageable, totalCount);
+ assertEquals(2, totalPages); // 20 items, 10 items per page => 2 pages
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/util/ValidateEncodingTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/util/ValidateEncodingTest.java
index 95a06fa..3270f8c 100644
--- a/aai-traversal/src/test/java/org/onap/aai/rest/util/ValidateEncodingTest.java
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/util/ValidateEncodingTest.java
@@ -19,17 +19,16 @@
*/
package org.onap.aai.rest.util;
-import static org.junit.Assert.assertEquals;
-
import java.io.UnsupportedEncodingException;
-
+import java.net.URI;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.UriInfo;
-
import org.junit.Test;
import org.mockito.Mockito;
+import static org.junit.jupiter.api.Assertions.*;
+
public class ValidateEncodingTest {
@Test
@@ -103,6 +102,34 @@ public class ValidateEncodingTest {
assertEquals(true, validator.validate(mockUriInfo));
}
+ @Test
+ public void badUriPath() throws UnsupportedEncodingException {
+ String badPath = "/aai/v6/network/vces/vce/blahh::blach/others/other/jklfea{}";
+
+ UriInfo mockUriInfo = getMockUriInfo(badPath, new MultivaluedHashMap<String, String>());
+
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertFalse(validator.validate(mockUriInfo));
+ }
+
+
+ @Test
+ public void goodUriPath() throws UnsupportedEncodingException {
+ URI goodUri = URI.create("http://example.com/aai/v6/network/vces/vce/blahh%3A%3Ablach/others/other/jklfea%7B%7D");
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertEquals(true, validator.validate(goodUri));
+ }
+
+ @Test
+ public void emptyUriPath() throws UnsupportedEncodingException {
+ URI emptyUri = URI.create("http://example.com");
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertTrue(validator.validate(emptyUri));
+ }
+
private UriInfo getMockUriInfo(String path, MultivaluedMap<String, String> map) {
UriInfo mockUriInfo = Mockito.mock(UriInfo.class);
Mockito.when(mockUriInfo.getPath(false)).thenReturn(path);