From d749a1072e23073e320ffe78c3f0576da0486279 Mon Sep 17 00:00:00 2001 From: Fiete Ostkamp Date: Tue, 23 Jan 2024 14:40:32 +0100 Subject: Update tinkerpop to 3.2.4 - work around hasStep inlining - add tests that more directly assert traversal state - add TinkerpopUpgradeTests test suite [1] - bump aai-common version to 1.13.2 [1] this allows to run the tests that are likely affected by a tinkerpop upgrade Issue-ID: AAI-3740 Change-Id: I86fb9b0c86802c7c0f74a5aae0976e81bf501eb0 Signed-off-by: Fiete Ostkamp --- .../java/org/onap/aai/parsers/uri/URIParser.java | 4 +- .../aai/query/builder/GraphTraversalBuilder.java | 27 ++++-- .../org/onap/aai/query/builder/QueryBuilder.java | 17 +++- .../org/onap/aai/query/builder/TraversalQuery.java | 87 ++++++++++++++++++- .../engines/TransactionalGraphEngine.java | 33 +++----- .../test/java/org/onap/aai/TinkerpopUpgrade.java | 26 ++++++ .../java/org/onap/aai/TinkerpopUpgradeTests.java | 43 ++++++++++ .../aai/introspection/sideeffect/DataLinkTest.java | 53 +++++++++++- .../onap/aai/parsers/query/GraphTraversalTest.java | 3 + .../onap/aai/query/builder/TraversalQueryTest.java | 99 ++++++++++++++++++++++ 10 files changed, 355 insertions(+), 37 deletions(-) create mode 100644 aai-core/src/test/java/org/onap/aai/TinkerpopUpgrade.java create mode 100644 aai-core/src/test/java/org/onap/aai/TinkerpopUpgradeTests.java (limited to 'aai-core/src') diff --git a/aai-core/src/main/java/org/onap/aai/parsers/uri/URIParser.java b/aai-core/src/main/java/org/onap/aai/parsers/uri/URIParser.java index 409631f5..0d25a15e 100644 --- a/aai-core/src/main/java/org/onap/aai/parsers/uri/URIParser.java +++ b/aai-core/src/main/java/org/onap/aai/parsers/uri/URIParser.java @@ -131,8 +131,8 @@ public class URIParser { uriKeys = queryParams; } else { for (String key : keys) { - part = UriUtils.decode(parts[i+1], "UTF-8"); - introspector.setValue(key, part); + String value = UriUtils.decode(parts[i+1], "UTF-8"); + introspector.setValue(key, value); // skip this for further processing i++; } diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java index 3c5c4489..c5c4512e 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/GraphTraversalBuilder.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ + * * Modifications Copyright © 2024 DEUTSCHE TELEKOM AG. + * ================================================================================ * 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 @@ -32,6 +34,7 @@ import java.util.Set; import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Path; +import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traversal.Admin; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; @@ -62,6 +65,9 @@ public abstract class GraphTraversalBuilder extends QueryBuilder { protected GraphTraversal traversal = null; protected Admin completeTraversal = null; + protected QueryBuilder containerQuery; + protected QueryBuilder parentQuery; + /** * Instantiates a new graph traversal builder. * @@ -73,6 +79,12 @@ public abstract class GraphTraversalBuilder extends QueryBuilder { } + public GraphTraversalBuilder(Loader loader, GraphTraversalSource source, GraphTraversal traversal) { + super(loader, source); + this.traversal = traversal; + + } + /** * Instantiates a new graph traversal builder. * @@ -336,11 +348,7 @@ public abstract class GraphTraversalBuilder extends QueryBuilder { } } - /** - * @{inheritDoc} - */ @Override - public QueryBuilder createContainerQuery(Introspector obj) { String type = obj.getChildDBName(); String abstractType = obj.getMetadata(ObjectMetadata.ABSTRACT); @@ -851,17 +859,18 @@ public abstract class GraphTraversalBuilder extends QueryBuilder { */ @Override public QueryBuilder getParentQuery() { - - return cloneQueryAtStep(parentStepIndex); + return this.parentQuery != null + ? this.parentQuery + : cloneQueryAtStep(parentStepIndex); } @Override public QueryBuilder getContainerQuery() { - + if (this.parentStepIndex == 0) { return removeQueryStepsBetween(0, containerStepIndex); } else { - return cloneQueryAtStep(containerStepIndex); + return this.containerQuery; } } @@ -870,11 +879,13 @@ public abstract class GraphTraversalBuilder extends QueryBuilder { */ @Override public void markParentBoundary() { + this.parentQuery = cloneQueryAtStep(stepIndex); parentStepIndex = stepIndex; } @Override public void markContainer() { + this.containerQuery = cloneQueryAtStep(stepIndex); containerStepIndex = stepIndex; } diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java b/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java index 2bc90726..66532529 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/QueryBuilder.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ + * Modifications Copyright © 2024 DEUTSCHE TELEKOM AG. + * ================================================================================ * 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 @@ -90,6 +92,11 @@ public abstract class QueryBuilder implements Iterator { this.loader = loader; } + /** + * Creates a new {@link QueryBuilder} that contains the traversal up to the provided index. + * @param index + * @return + */ protected abstract QueryBuilder cloneQueryAtStep(int index); /** @@ -266,9 +273,15 @@ public abstract class QueryBuilder implements Iterator { public abstract QueryBuilder createKeyQuery(Introspector obj); /** - * Creates the container query. + * Creates the container query.
+ * A container query is a query that will return a collection of objects: + *
+     * /cloud-infrastructure/complexes/complex/key1
+     *           ↑              ↑        ↑
+     *       namespace      container  object
      *
-     * @param obj the obj
+     * 
+ * @param obj the Introspector into the db schema * @return the query builder */ public abstract QueryBuilder createContainerQuery(Introspector obj); diff --git a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java index 579c3571..ca9d232c 100644 --- a/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java +++ b/aai-core/src/main/java/org/onap/aai/query/builder/TraversalQuery.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ + * Modifications Copyright © 2024 DEUTSCHE TELEKOM AG. + * ================================================================================ * 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 @@ -23,12 +25,15 @@ package org.onap.aai.query.builder; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.List; +import java.util.stream.Collectors; import javax.ws.rs.core.MultivaluedMap; import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; @@ -52,6 +57,11 @@ public class TraversalQuery extends GraphTraversalBuilder { this.factory = new TraversalStrategy(this.loader, this); } + public TraversalQuery(Loader loader, GraphTraversalSource source, GraphTraversal traversal) { + super(loader, source, traversal); + this.factory = new TraversalStrategy(this.loader, this); + } + /** * Instantiates a new traversal query. * @@ -159,12 +169,85 @@ public class TraversalQuery extends GraphTraversalBuilder { @Override protected QueryBuilder removeQueryStepsBetween(int start, int end) { + if(start > 0) { + throw new IllegalArgumentException("A start index > 0 is currently not supported"); + } GraphTraversal clone = this.traversal.asAdmin().clone(); GraphTraversal.Admin cloneAdmin = clone.asAdmin(); - for (int i = end - 2; i >= start; i--) { - cloneAdmin.removeStep(i); + List steps = cloneAdmin.getSteps(); + + // TODO: Use containerAdjusted start index to support start > 0 + // TraversalQueryTest#removeQueryStepsBetweenTest27 can guide the implementation + int containerAdjusted = start > 0 + ? getContainerAdjustedStart(cloneAdmin, steps, start) + : start; + for (int i = start; i < end - 1; i++) { + Step step = steps.get(start); + if (step instanceof HasStep) { + List hasContainers = ((HasStep) step).getHasContainers(); + int hasContainerSize = hasContainers.size(); + boolean isEndWithinHasContainer = isEndWithinHasContainer(end, i, hasContainers); + if (isEndWithinHasContainer) { + int splitPosition = end - i - 1; + splitHasContainerAtPosition(cloneAdmin, hasContainers, start, splitPosition); + i += (hasContainerSize - splitPosition); + } else { + cloneAdmin.removeStep(start); + i += (hasContainerSize - 1); + } + } else { + cloneAdmin.removeStep(start); + } } return new TraversalQuery<>(cloneAdmin, loader, source, this); } + + private boolean isEndWithinHasContainer(int end, int i, List hasContainers) { + return (i + hasContainers.size()) >= end - 1; + } + + /** + * Since the has-step inlining that was introduced with tinkerpop version 3.2.4, + * a Step can be a HasContainer that can contain multiple steps. + * The start index needs to be adjusted to account for this fact + * @param cloneAdmin + * @param steps + * @param start + * @return + */ + private int getContainerAdjustedStart(GraphTraversal.Admin cloneAdmin, List steps, int start) { + int adjustedIndex = start; + for (int i = 0; i < start; i++) { + Step step = steps.get(i); + if (step instanceof HasStep) { + if(isEndWithinHasContainer(adjustedIndex, i, ((HasStep) step).getHasContainers())){ + adjustedIndex -= 1; + } + adjustedIndex -= ((HasStep) step).getHasContainers().size(); + } + } + return adjustedIndex; + } + + /** + * Split the hasContainer at the provided position and append everything + * after it to the step Array + * @param cloneAdmin + * @param hasContainers + * @param splitPosition + */ + private void splitHasContainerAtPosition(GraphTraversal.Admin cloneAdmin, + List hasContainers, int start, int splitPosition) { + List newContainers = hasContainers.stream() + .skip(splitPosition) + .collect(Collectors.toList()); + int replaceIndex = start; + cloneAdmin.removeStep(replaceIndex); + for (HasContainer hasContainer : newContainers) { + cloneAdmin.addStep(replaceIndex, new HasStep<>(cloneAdmin, hasContainer)); + replaceIndex++; + } + } + } diff --git a/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java b/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java index 73cdc3c8..54c8b7ce 100644 --- a/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java +++ b/aai-core/src/main/java/org/onap/aai/serialization/engines/TransactionalGraphEngine.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ + * Modifications Copyright © 2024 DEUTSCHE TELEKOM AG. + * ================================================================================ * 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 @@ -20,13 +22,13 @@ package org.onap.aai.serialization.engines; -import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; 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.optimization.InlineFilterStrategy; -import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.LazyBarrierStrategy; import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; @@ -153,27 +155,14 @@ public abstract class TransactionalGraphEngine { public QueryBuilder getQueryBuilder(QueryStyle style, Loader loader) { GraphTraversalSource source = this.asAdmin().getTraversalSource(); - if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) { - return new GremlinTraversal<>(loader, source); - } else if (style.equals(QueryStyle.GREMLIN_UNIQUE)) { - return new GremlinUnique<>(loader, source); - } else if (style.equals(QueryStyle.GREMLINPIPELINE_TRAVERSAL)) { - // return new GremlinPipelineTraversal(loader); - } else if (style.equals(QueryStyle.TRAVERSAL)) { - return new TraversalQuery<>(loader, source != null ? source.withoutStrategies(InlineFilterStrategy.class) : source); - } else if (style.equals(QueryStyle.TRAVERSAL_URI)) { - return new TraversalURIOptimizedQuery<>(loader, source != null ? source.withoutStrategies(InlineFilterStrategy.class) : source); - } else if (style.equals(QueryStyle.HISTORY_TRAVERSAL)) { - throw new IllegalArgumentException("History Traversal needs history traversal source"); - } else if (style.equals(QueryStyle.HISTORY_GREMLIN_TRAVERSAL)) { - throw new IllegalArgumentException("History Gremlin Traversal needs history traversal source"); - } else { - throw new IllegalArgumentException("Query Builder type not recognized"); - } - return queryBuilder; + return this.getQueryBuilder(style, loader, source); } public QueryBuilder getQueryBuilder(QueryStyle style, Loader loader, GraphTraversalSource source) { + return this.getQueryBuilder(style, loader, source, (GraphTraversal) __.start()); + } + + public QueryBuilder getQueryBuilder(QueryStyle style, Loader loader, GraphTraversalSource source, GraphTraversal traversal) { if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) { return new GremlinTraversal<>(loader, source); } else if (style.equals(QueryStyle.GREMLIN_UNIQUE)) { @@ -181,9 +170,9 @@ public abstract class TransactionalGraphEngine { } else if (style.equals(QueryStyle.GREMLINPIPELINE_TRAVERSAL)) { // return new GremlinPipelineTraversal(loader); } else if (style.equals(QueryStyle.TRAVERSAL)) { - return new TraversalQuery<>(loader, source); + return new TraversalQuery<>(loader, source != null ? source.withoutStrategies(InlineFilterStrategy.class) : source, traversal); } else if (style.equals(QueryStyle.TRAVERSAL_URI)) { - return new TraversalURIOptimizedQuery<>(loader, source); + return new TraversalURIOptimizedQuery<>(loader, source != null ? source.withoutStrategies(InlineFilterStrategy.class) : source); } else if (style.equals(QueryStyle.HISTORY_TRAVERSAL)) { return new HistoryTraversalURIOptimizedQuery<>(loader, source); } else if (style.equals(QueryStyle.HISTORY_GREMLIN_TRAVERSAL)) { diff --git a/aai-core/src/test/java/org/onap/aai/TinkerpopUpgrade.java b/aai-core/src/test/java/org/onap/aai/TinkerpopUpgrade.java new file mode 100644 index 00000000..a6aa1e4c --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/TinkerpopUpgrade.java @@ -0,0 +1,26 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 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; +/** + * Marker interface for Junit to annotate tests + * that affect the tinkerpop dependency update + */ +public interface TinkerpopUpgrade {} \ No newline at end of file diff --git a/aai-core/src/test/java/org/onap/aai/TinkerpopUpgradeTests.java b/aai-core/src/test/java/org/onap/aai/TinkerpopUpgradeTests.java new file mode 100644 index 00000000..81c3ed81 --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/TinkerpopUpgradeTests.java @@ -0,0 +1,43 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 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; + +import org.junit.experimental.categories.Categories; +import org.junit.experimental.categories.Categories.IncludeCategory; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; +import org.onap.aai.introspection.sideeffect.DataLinkTest; +import org.onap.aai.parsers.query.GraphTraversalTest; +import org.onap.aai.query.builder.TraversalQueryTest; + +/** + * Collection of tests that are likely affected by a Tinkerpop update + * This is to more targedly run these tests during development: + * mvn test -Dcheckstyle.skip -Dtest=TinkerpopUpgradeTests + */ +@RunWith(Categories.class) +@IncludeCategory(TinkerpopUpgrade.class) +@SuiteClasses({ + DataLinkTest.class, + GraphTraversalTest.class, + TraversalQueryTest.class +}) +public class TinkerpopUpgradeTests {} diff --git a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java index 2a68e53d..7ccf1305 100644 --- a/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java +++ b/aai-core/src/test/java/org/onap/aai/introspection/sideeffect/DataLinkTest.java @@ -28,12 +28,18 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.UUID; +import javax.ws.rs.core.MultivaluedMap; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; @@ -42,24 +48,32 @@ import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphFactory; import org.janusgraph.core.schema.JanusGraphManagement; import org.junit.*; +import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.DataLinkSetup; +import org.onap.aai.TinkerpopUpgrade; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.edges.enums.EdgeProperty; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.Introspector; import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderUtil; import org.onap.aai.introspection.ModelType; +import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; import org.onap.aai.parsers.query.QueryParser; +import org.onap.aai.query.builder.QueryBuilder; +import org.onap.aai.query.builder.TraversalQuery; +import org.onap.aai.restcore.util.URITools; import org.onap.aai.serialization.db.DBSerializer; import org.onap.aai.serialization.engines.JanusGraphDBEngine; import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; +@Category(TinkerpopUpgrade.class) @RunWith(value = Parameterized.class) public class DataLinkTest extends DataLinkSetup { @@ -81,7 +95,7 @@ public class DataLinkTest extends DataLinkSetup { @Parameterized.Parameters(name = "QueryStyle.{0}") public static Collection data() { - return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}, {QueryStyle.TRAVERSAL_URI}}); + return Arrays.asList(new Object[][] {{QueryStyle.TRAVERSAL}}); } @BeforeClass @@ -204,6 +218,43 @@ public class DataLinkTest extends DataLinkSetup { } + /** + * This is more directly testing the modification mechanism (see verifyModificationOfVertex test) + */ + @Test + public void linkQuery() throws UnsupportedEncodingException, AAIException, URISyntaxException { + Graph g = graph.newTransaction(); + GraphTraversalSource source = g.traversal(); + final Loader loader = LoaderUtil.getLatestVersion(); + URI uri = new URI("/network/vpn-bindings/vpn-binding/modifyKey/route-targets/route-target/modifyTargetKey2/modifyRoleKey2"); + MultivaluedMap map = URITools.getQueryMap(uri); + GraphTraversal traversal = __.start(); + + QueryParser uriQuery = dbEngine.getQueryBuilder(this.queryStyle, loader, source, traversal).createQueryFromURI(uri, map); + // assertEquals(6, traversal.asAdmin().getSteps().size()); + // assertEquals("HasStep([vpn-id.eq(modifyKey)])", traversal.asAdmin().getSteps().get(0).toString()); + // assertEquals("HasStep([aai-node-type.eq(vpn-binding)])", traversal.asAdmin().getSteps().get(1).toString()); + // assertEquals("VertexStep(IN,[org.onap.relationships.inventory.BelongsTo],vertex)", traversal.asAdmin().getSteps().get(2).toString()); + // assertEquals("HasStep([aai-node-type.eq(route-target)])", traversal.asAdmin().getSteps().get(3).toString()); + // assertEquals("HasStep([global-route-target.eq(modifyTargetKey2)])", traversal.asAdmin().getSteps().get(4).toString()); + // assertEquals("HasStep([route-target-role.eq(modifyRoleKey2)])", traversal.asAdmin().getSteps().get(5).toString()); + List results = uriQuery.getQueryBuilder().toList(); + + assertEquals(0, results.size()); + // assertEquals(traversal.asAdmin().getSteps().size(), 6); + // assertEquals("HasStep([vpn-id.eq(modifyKey)])", traversal.asAdmin().getSteps().get(0).toString()); + // assertEquals("HasStep([aai-node-type.eq(vpn-binding)])", traversal.asAdmin().getSteps().get(1).toString()); + // assertEquals("VertexStep(IN,[org.onap.relationships.inventory.BelongsTo],vertex)", traversal.asAdmin().getSteps().get(2).toString()); + // assertEquals("HasStep([aai-node-type.eq(route-target)])", traversal.asAdmin().getSteps().get(3).toString()); + // assertEquals("HasStep([global-route-target.eq(modifyTargetKey2)])", traversal.asAdmin().getSteps().get(4).toString()); + // assertEquals("HasStep([route-target-role.eq(modifyRoleKey2)])", traversal.asAdmin().getSteps().get(5).toString()); + + QueryBuilder queryBuilder = uriQuery.getQueryBuilder().getContainerQuery() + .getVerticesByProperty(AAIProperties.LINKED, true); + List linkedVertices = queryBuilder.toList(); + assertEquals(1, linkedVertices.size()); + } + @Test public void verifyModificationOfVertex() throws AAIException, UnsupportedEncodingException, IllegalArgumentException, SecurityException { diff --git a/aai-core/src/test/java/org/onap/aai/parsers/query/GraphTraversalTest.java b/aai-core/src/test/java/org/onap/aai/parsers/query/GraphTraversalTest.java index b038b72a..34b29ceb 100644 --- a/aai-core/src/test/java/org/onap/aai/parsers/query/GraphTraversalTest.java +++ b/aai-core/src/test/java/org/onap/aai/parsers/query/GraphTraversalTest.java @@ -43,10 +43,12 @@ import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.onap.aai.DataLinkSetup; +import org.onap.aai.TinkerpopUpgrade; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.exceptions.AAIException; import org.onap.aai.introspection.ModelType; @@ -56,6 +58,7 @@ import org.onap.aai.serialization.engines.QueryStyle; import org.onap.aai.serialization.engines.TransactionalGraphEngine; import org.springframework.test.annotation.DirtiesContext; +@Category(TinkerpopUpgrade.class) @RunWith(value = Parameterized.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) public class GraphTraversalTest extends DataLinkSetup { diff --git a/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java b/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java index eca5c54e..df922b08 100644 --- a/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java +++ b/aai-core/src/test/java/org/onap/aai/query/builder/TraversalQueryTest.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ + * Modifications Copyright © 2024 DEUTSCHE TELEKOM AG. + * ================================================================================ * 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 @@ -30,16 +32,26 @@ import java.util.List; import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +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.step.util.Tree; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphFactory; import org.junit.Ignore; import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.onap.aai.TinkerpopUpgrade; import org.onap.aai.db.props.AAIProperties; import org.onap.aai.edges.enums.EdgeType; import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Introspector; +import org.onap.aai.introspection.Loader; +import org.onap.aai.introspection.LoaderUtil; +import org.onap.aai.introspection.exceptions.AAIUnknownObjectException; +@Category(TinkerpopUpgrade.class) public class TraversalQueryTest extends QueryBuilderTestAbstraction { @Override @@ -258,4 +270,91 @@ public class TraversalQueryTest extends QueryBuilderTestAbstraction { } + @Test + public void createDBQueryTest() throws AAIUnknownObjectException { + JanusGraph graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + GraphTraversalSource source = graph.newTransaction().traversal(); + final Loader loader = LoaderUtil.getLatestVersion(); + GraphTraversal traversal = __.start(); + TraversalQuery traversalQuery = new TraversalQuery<>(loader, source, traversal); + Introspector obj = loader.introspectorFromName("vpn-binding"); + obj.setValue("vpn-id", "modifyKey"); + + traversalQuery.createKeyQuery(obj); + assertEquals(1, traversal.asAdmin().getSteps().size()); + assertEquals("HasStep([vpn-id.eq(modifyKey)])", traversal.asAdmin().getSteps().get(0).toString()); + traversalQuery.createContainerQuery(obj); + assertEquals(1, traversal.asAdmin().getSteps().size()); + assertEquals("HasStep([vpn-id.eq(modifyKey), aai-node-type.eq(vpn-binding)])", traversal.asAdmin().getSteps().get(0).toString()); + } + + @Test + public void removeQueryStepsBetweenTest() throws AAIUnknownObjectException { + JanusGraph graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + GraphTraversalSource source = graph.newTransaction().traversal(); + final Loader loader = LoaderUtil.getLatestVersion(); + TraversalQuery traversalQuery = new TraversalQuery<>(loader, source); + traversalQuery.has("propertyKey", "value"); + + QueryBuilder clonedQuery = traversalQuery.removeQueryStepsBetween(0, 1); + String query = clonedQuery.getQuery().toString(); + assertEquals("[HasStep([propertyKey.eq(value)])]", query); + } + + @Test + public void removeQueryStepsBetweenTest02() throws AAIUnknownObjectException { + JanusGraph graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + GraphTraversalSource source = graph.newTransaction().traversal(); + final Loader loader = LoaderUtil.getLatestVersion(); + TraversalQuery traversalQuery = new TraversalQuery<>(loader, source); + traversalQuery.has("propertyKey", "value"); + + QueryBuilder clonedQuery = traversalQuery.removeQueryStepsBetween(0, 2); + String query = clonedQuery.getQuery().toString(); + assertEquals("[]", query); + } + + @Test + public void removeQueryStepsBetweenTest07() throws AAIUnknownObjectException { + JanusGraph graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + GraphTraversalSource source = graph.newTransaction().traversal(); + final Loader loader = LoaderUtil.getLatestVersion(); + TraversalQuery traversalQuery = new TraversalQuery<>(loader, source); + traversalQuery.limit(1); + traversalQuery.has("propertyKey", "value"); + traversalQuery.has("propertyKey2", "value2"); + traversalQuery.limit(2); + traversalQuery.has("propertyKey3", "value3"); + traversalQuery.has("propertyKey4", "value4"); + traversalQuery.has("propertyKey5", "value5"); + traversalQuery.limit(3); + traversalQuery.limit(4); + + QueryBuilder clonedQuery = traversalQuery.removeQueryStepsBetween(0, 7); + String query = clonedQuery.getQuery().toString(); + assertEquals("[HasStep([propertyKey5.eq(value5)]), RangeGlobalStep(0,3), RangeGlobalStep(0,4)]", query); + } + + @Test + @Ignore("Enable once removeQueryStepsBetween supports a start index > 0") + public void removeQueryStepsBetweenTest27() throws AAIUnknownObjectException { + JanusGraph graph = JanusGraphFactory.build().set("storage.backend", "inmemory").open(); + GraphTraversalSource source = graph.newTransaction().traversal(); + final Loader loader = LoaderUtil.getLatestVersion(); + TraversalQuery traversalQuery = new TraversalQuery<>(loader, source); + traversalQuery.limit(1); + traversalQuery.has("propertyKey", "value"); + traversalQuery.has("propertyKey2", "value2"); + traversalQuery.limit(2); + traversalQuery.has("propertyKey3", "value3"); + traversalQuery.has("propertyKey4", "value4"); + traversalQuery.has("propertyKey5", "value5"); + traversalQuery.limit(3); + traversalQuery.limit(4); + + QueryBuilder clonedQuery = traversalQuery.removeQueryStepsBetween(2, 7); + String query = clonedQuery.getQuery().toString(); + assertEquals("[RangeGlobalStep(0,1), HasStep([propertyKey.eq(value)]), HasStep([propertyKey5.eq(value5)]), RangeGlobalStep(0,3), RangeGlobalStep(0,4)]", query); + } + } -- cgit 1.2.3-korg