/*- * ============LICENSE_START======================================================= * org.openecomp.aai * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. 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.openecomp.aai.parsers.query; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; import java.util.List; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.openecomp.aai.db.props.AAIProperties; import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.LoaderFactory; import org.openecomp.aai.introspection.ModelType; import org.openecomp.aai.introspection.Version; import org.openecomp.aai.serialization.engines.QueryStyle; import org.openecomp.aai.serialization.engines.TitanDBEngine; import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; import org.openecomp.aai.serialization.queryformats.QueryFormatTestHelper; import org.openecomp.aai.util.AAIConstants; public class GraphTraversalTest { private static TransactionalGraphEngine dbEngine; private static TransactionalGraphEngine dbEnginev9; @Rule public ExpectedException thrown = ExpectedException.none(); /** * Configure. * @throws Exception * @throws SecurityException * @throws NoSuchFieldException */ @BeforeClass public static void configure() throws NoSuchFieldException, SecurityException, Exception { System.setProperty("AJSC_HOME", "./src/test/resources/"); System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local"); QueryFormatTestHelper.setFinalStatic(AAIConstants.class.getField("AAI_HOME_ETC_OXM"), "src/test/resources/org/openecomp/aai/introspection/"); dbEngine = new TitanDBEngine(QueryStyle.TRAVERSAL, LoaderFactory.createLoaderForVersion(ModelType.MOXY, AAIProperties.LATEST), false); dbEnginev9 = new TitanDBEngine(QueryStyle.TRAVERSAL, LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v9), false); } /** * Parent query. * * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void parentQuery() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start().has("physical-location-id", "key1").has("aai-node-type", "complex"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal to normal query", expected.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be complex", "complex", query.getResultType()); assertEquals( "result type should be empty", "", query.getParentResultType()); assertEquals("dependent",false, query.isDependent()); } /** * Child query. * * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void childQuery() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1/ctag-pools/ctag-pool/key2/key3").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start() .has("physical-location-id", "key1").has("aai-node-type", "complex") .out("hasCtagPool") .has("aai-node-type", "ctag-pool") .has("target-pe", "key2").has("availability-zone-name", "key3"); GraphTraversal expectedParent = __.start() .has("physical-location-id", "key1").has("aai-node-type", "complex"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for complex", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be complex", "complex", query.getParentResultType()); assertEquals( "result type should be ctag-pool", "ctag-pool", query.getResultType()); assertEquals("dependent",true, query.isDependent()); } /** * Naming exceptions. * * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void namingExceptions() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start() .has("vnf-id", "key1").has("aai-node-type", "vce") .out("hasPortGroup") .has("aai-node-type", "port-group") .has("interface-id", "key2").out("hasCTag") .has("aai-node-type", "cvlan-tag") .has("cvlan-tag", 655); GraphTraversal expectedParent = __.start() .has("vnf-id", "key1").has("aai-node-type", "vce") .out("hasPortGroup") .has("aai-node-type", "port-group") .has("interface-id", "key2"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for port group", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be cvlan-tag", "cvlan-tag", query.getResultType()); assertEquals( "result type should be port-group", "port-group", query.getParentResultType()); assertEquals( "contaner type should be empty", "", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } /** * Gets the all. * * @return the all * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void getAll() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start() .has("vnf-id", "key1").has("aai-node-type", "vce") .out("hasPortGroup") .has("aai-node-type", "port-group") .has("interface-id", "key2").out("hasCTag") .has("aai-node-type", "cvlan-tag"); GraphTraversal expectedParent = __.start() .has("vnf-id", "key1").has("aai-node-type", "vce") .out("hasPortGroup") .has("aai-node-type", "port-group") .has("interface-id", "key2"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for port group", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be port-group", "port-group", query.getParentResultType()); assertEquals( "result type should be cvlan-tag", "cvlan-tag", query.getResultType()); assertEquals( "container type should be cvlan-tags", "cvlan-tags", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } @Test public void getAllParent() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start() .has("aai-node-type", "pserver"); GraphTraversal expectedParent = __.start() .has("aai-node-type", "pserver"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for pserver", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "parent result type should be empty", "", query.getParentResultType()); assertEquals( "result type should be pserver", "pserver", query.getResultType()); assertEquals( "container type should be pservers", "pservers", query.getContainerType()); assertEquals("dependent",false, query.isDependent()); } /** * Gets the via query param. * * @return the via query param * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void getViaQueryParam() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/cloud-regions/cloud-region/mycloudowner/mycloudregionid/tenants/tenant").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("tenant-name", "Tenant1"); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("cloud-owner", "mycloudowner").has("cloud-region-id", "mycloudregionid") .has("aai-node-type", "cloud-region") .out("has") .has("aai-node-type", "tenant") .has("tenant-name", "Tenant1"); GraphTraversal expectedParent = __.start() .has("cloud-owner", "mycloudowner").has("cloud-region-id", "mycloudregionid") .has("aai-node-type", "cloud-region"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for cloud-region", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be cloud-region", "cloud-region", query.getParentResultType()); assertEquals( "result type should be tenant", "tenant", query.getResultType()); assertEquals( "container type should be empty", "", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } @Test public void getViaDuplicateQueryParam() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/cloud-regions/cloud-region/mycloudowner/mycloudregionid/tenants/tenant").build(); MultivaluedMap map = new MultivaluedHashMap<>(); List values = new ArrayList<>(); values.add("Tenant1"); values.add("Tenant2"); map.put("tenant-name", values); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("cloud-owner", "mycloudowner").has("cloud-region-id", "mycloudregionid") .has("aai-node-type", "cloud-region") .out("has") .has("aai-node-type", "tenant") .has("tenant-name", P.within(values)); GraphTraversal expectedParent = __.start() .has("cloud-owner", "mycloudowner").has("cloud-region-id", "mycloudregionid") .has("aai-node-type", "cloud-region"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for cloud-region", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be cloud-region", "cloud-region", query.getParentResultType()); assertEquals( "result type should be tenant", "tenant", query.getResultType()); assertEquals( "container type should be empty", "", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } /** * Gets the plural via query param. * * @return the plural via query param * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void getPluralViaQueryParam() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vnfcs").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("prov-status", "up"); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("aai-node-type", "vnfc") .has("prov-status", "up"); GraphTraversal expectedParent = __.start() .has("aai-node-type", "vnfc"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "parent result type should be empty", "", query.getParentResultType()); assertEquals( "result type should be vnfc", "vnfc", query.getResultType()); assertEquals( "container type should be empty", "vnfcs", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } /** * Gets the all query param naming exception. * * @return the all query param naming exception * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void getAllQueryParamNamingException() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("cvlan-tag", "333"); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("vnf-id", "key1").has("aai-node-type", "vce") .out("hasPortGroup") .has("aai-node-type", "port-group") .has("interface-id", "key2").out("hasCTag") .has("aai-node-type", "cvlan-tag") .has("cvlan-tag", 333); GraphTraversal expectedParent = __.start() .has("vnf-id", "key1").has("aai-node-type", "vce") .out("hasPortGroup") .has("aai-node-type", "port-group") .has("interface-id", "key2"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for port group", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be port-group", "port-group", query.getParentResultType()); assertEquals( "result type should be cvlan-tag", "cvlan-tag", query.getResultType()); assertEquals( "container type should be cvlan-tags", "cvlan-tags", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } /** * Abstract type. * * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void abstractType() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("vnf/key1").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start() .has("vnf-id", "key1").or( __.has(AAIProperties.NODE_TYPE, "vce"), __.has(AAIProperties.NODE_TYPE, "vpe"), __.has(AAIProperties.NODE_TYPE, "generic-vnf")); GraphTraversal expectedParent = expected; assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for port group", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be empty", "", query.getParentResultType()); assertEquals( "result type should be vnf", "vnf", query.getResultType()); assertEquals("dependent",false, query.isDependent()); } /** * Non parent abstract type. * * @throws UnsupportedEncodingException the unsupported encoding exception * @throws AAIException the AAI exception */ @Test public void nonParentAbstractType() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key2/vnf/key1").build(); thrown.expect(AAIException.class); thrown.expectMessage(containsString("not a valid path")); dbEngine.getQueryBuilder().createQueryFromURI(uri); } @Test public void parentAbstractTypeWithNesting() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("vnf/key1/vf-modules/vf-module/key2").build(); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri); GraphTraversal expected = __.start() .has("vnf-id", "key1").or( __.has(AAIProperties.NODE_TYPE, "vce"), __.has(AAIProperties.NODE_TYPE, "vpe"), __.has(AAIProperties.NODE_TYPE, "generic-vnf")) .filter(x -> true).outE().has("isParent", true).inV().has("vf-module-id", "key2"); GraphTraversal expectedParent = __.start() .has("vnf-id", "key1").or( __.has(AAIProperties.NODE_TYPE, "vce"), __.has(AAIProperties.NODE_TYPE, "vpe"), __.has(AAIProperties.NODE_TYPE, "generic-vnf")); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent gremlin query should be equal the query for ", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be vnf", "vnf", query.getParentResultType()); assertEquals( "result type should be vf-module", "vf-module", query.getResultType()); assertEquals("dependent",true, query.isDependent()); } @Test public void getViaBadQueryParam() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/cloud-regions/cloud-region/a/b/tenants/tenant").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("tenant-n231ame", "Tenant1"); thrown.expect(AAIException.class); thrown.expect(hasProperty("code", is("AAI_3000"))); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); } @Test public void getPluralViaBadQueryParam() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("cloud-infrastructure/cloud-regions/cloud-region/a/b/tenants").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("tenant-n231ame", "Tenant1"); thrown.expect(AAIException.class); thrown.expect(hasProperty("code", is("AAI_3000"))); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); } @Test public void getPluralViaDuplicateQueryParam() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vnfcs").build(); MultivaluedMap map = new MultivaluedHashMap<>(); List values = new ArrayList<>(); values.add("up"); values.add("down"); values.add("left"); values.add("right"); values.add("start"); map.put("prov-status", values); QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("aai-node-type", "vnfc") .has("prov-status", P.within(values)); GraphTraversal expectedParent = __.start() .has("aai-node-type", "vnfc"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "parent result type should be empty", "", query.getParentResultType()); assertEquals( "result type should be vnfc", "vnfc", query.getResultType()); assertEquals( "container type should be empty", "vnfcs", query.getContainerType()); assertEquals("dependent",true, query.isDependent()); } @Test public void dbAliasedSearch() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/test-objects").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("persona-model-customization-id", "key2"); QueryParser query = dbEnginev9.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("aai-node-type", "test-object") .has("model-customization-id", "key2"); GraphTraversal expectedParent = __.start() .has("aai-node-type", "test-object"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be", "test-object", query.getResultType()); assertEquals( "result type should be empty", "", query.getParentResultType()); assertEquals("dependent",true, query.isDependent()); } @Test public void dataLinkedSearch() throws UnsupportedEncodingException, AAIException { URI uri = UriBuilder.fromPath("network/vpn-bindings").build(); MultivaluedMap map = new MultivaluedHashMap<>(); map.putSingle("global-route-target", "key2"); QueryParser query = dbEnginev9.getQueryBuilder().createQueryFromURI(uri, map); GraphTraversal expected = __.start() .has("aai-node-type", "vpn-binding") .where(__.out("has").has(AAIProperties.NODE_TYPE, "route-target").has("global-route-target", "key2")); GraphTraversal expectedParent = __.start() .has("aai-node-type", "vpn-binding"); assertEquals( "gremlin query should be " + expected.toString(), expected.toString(), query.getQueryBuilder().getQuery().toString()); assertEquals( "parent", expectedParent.toString(), query.getQueryBuilder().getParentQuery().getQuery().toString()); assertEquals( "result type should be", "vpn-binding", query.getResultType()); assertEquals( "result type should be empty", "", query.getParentResultType()); assertEquals("dependent",true, query.isDependent()); } }