/* * Copyright 2015-2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * 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. */ package org.hawkular.inventory.rest; import static org.hawkular.inventory.api.Query.path; import static org.hawkular.inventory.api.Relationships.WellKnown.contains; import static org.hawkular.inventory.api.filters.With.id; import static org.hawkular.inventory.api.filters.With.name; import static org.hawkular.inventory.api.filters.With.type; import static org.hawkular.inventory.paths.SegmentType.m; import static org.hawkular.inventory.paths.SegmentType.r; import static org.junit.Assert.assertEquals; import org.hawkular.inventory.api.Query; import org.hawkular.inventory.api.filters.RecurseFilter; import org.hawkular.inventory.api.filters.Related; import org.hawkular.inventory.api.filters.RelationWith; import org.hawkular.inventory.api.filters.SwitchElementType; import org.hawkular.inventory.api.filters.With; import org.hawkular.inventory.api.model.Metric; import org.hawkular.inventory.api.model.Resource; import org.hawkular.inventory.api.model.ResourceType; import org.hawkular.inventory.api.model.Tenant; import org.hawkular.inventory.paths.CanonicalPath; import org.hawkular.inventory.paths.SegmentType; import org.junit.Test; /** * @author Lukas Krejci * @since 0.16.0.Final */ public class TraverserTest { @Test public void testStartByRelationship_simpleUri() throws Exception { testVariant("/rl;id/relationships", path().with(RelationWith.id("id")).get()); } @Test public void testStartByRelationship_ignoredDirectionIfNotNeeded() throws Exception { testVariant("/rl;id;in/relationships", path().with(RelationWith.id("id")).get()); } @Test public void testStartByRelationship_propertyExistence() throws Exception { testVariant("/rl;id;propertyName=kachna/relationships", path().with(RelationWith.id("id"), RelationWith.property("kachna")).get()); } @Test(expected = IllegalArgumentException.class) public void testStartByRelationship_unmatchedPropertyValueSimple() throws Exception { testVariant("/rl;id;propertyValue=kachna/relationship", null); } @Test public void testStartByRelationship_propertyValue() throws Exception { testVariant("/rl;id;propertyName=kachna;propertyValue=duck/relationships", path().with(RelationWith.id("id"), RelationWith.propertyValue("kachna", "duck")).get()); } @Test(expected = IllegalArgumentException.class) public void testStartByRelationship_umatchedPropertyValueComplex() throws Exception { testVariant("/rl;id;propertyName=kachna;propertyValue=duck;propertyValue=d/relationship", null); } @Test public void testStartByRelationship_jumpToTargets_implicitDirection() throws Exception { testVariant("/rl;id/entities", path().with(RelationWith.id("id"), SwitchElementType.targetEntities()).get()); } @Test public void testStartByRelationship_jumpToTargets_out() throws Exception { testVariant("/rl;id;out/entities", path().with(RelationWith.id("id"), SwitchElementType.targetEntities()).get()); } @Test public void testStartByRelationship_jumpToTargets_in() throws Exception { testVariant("/rl;id;in/entities", path().with(RelationWith.id("id"), SwitchElementType.sourceEntities()).get()); } @Test public void testStartByRelationship_traverseToEntities() throws Exception { testVariant("/rl;id/r;id/entities", path().with(RelationWith.id("id"), SwitchElementType.targetEntities()) .path().with(type(Resource.class), id("id")).get()); } @Test public void testStartByRelationship_traverseToFilter() throws Exception { testVariant("/rl;id;in/type=rt/entities", path().with(RelationWith.id("id"), SwitchElementType.sourceEntities()) .path().with(type(ResourceType.class)).get()); } @Test public void testQueryPrefixUsedForURIsStartingWithEntity() throws Exception { testVariant("/r;id/entities", path().with(id("eee"), Related.by(contains)) .path().with(type(Resource.class), id("id")).get(), Query.builder().path().with(id("eee"))); } @Test public void testSimpleEntityQuery() throws Exception { testVariant("/r;id", path().with(type(Resource.class), id("id")).get()); testVariant("/r;id/entities", path().with(type(Resource.class), id("id")).get()); testVariant("/r;id%20with%20escapes", path().with(type(Resource.class), id("id with escapes")).get()); } @Test public void testSimpleEntityQuery_filters() throws Exception { testVariant("/r;id;name=kachna/entities", path().with(type(Resource.class), id("id")) .filter().with(name("kachna")).get()); } @Test public void testSimpleEntityQuery_returnRelationships_implicitDirection() throws Exception { testVariant("/r;id/relationships", path().with(type(Resource.class), id("id")) .path().with(SwitchElementType.outgoingRelationships()).get()); } @Test public void testSimpleEntityQuery_returnRelationships_in() throws Exception { testVariant("/r;id/relationships;in", path().with(type(Resource.class), id("id")) .path().with(SwitchElementType.incomingRelationships()).get()); } @Test public void testSimpleEntityQuery_returnRelationships_filterRels() throws Exception { testVariant("/r;id/relationships;name=kachna;propertyName=alois", path().with(type(Resource.class), id("id")) .path().with(SwitchElementType.outgoingRelationships(), RelationWith.property("alois"), RelationWith.name("kachna")).get()); } @Test public void testSimpleEntityQuery_returnRelationships_out() throws Exception { testVariant("/r;id/relationships;out", path().with(type(Resource.class), id("id")) .path().with(SwitchElementType.outgoingRelationships()).get()); } @Test public void testEntityQuery_implicitContains() throws Exception { testVariant("/r;id/rt;id", path().with(type(Resource.class), id("id")) .path().with(Related.by(contains)) .path().with(type(ResourceType.class), id("id")).get()); } @Test public void testEntityQuery_implicitContains_cpOptimize() throws Exception { testVariant("/t;id/rt;id/entities", path().with(With.path(CanonicalPath.of().tenant("id").resourceType("id").get())).get()); } @Test public void testEntityQuery_implicitContains_cpOptimize_byPrefix() throws Exception { testVariant("/rt;id/entities", Query.path().with(With.path(CanonicalPath.of().tenant("id").resourceType("id").get())).get(), Query.builder().path().with(With.path(CanonicalPath.of().tenant("id").get())) .with(Related.by(contains))); } @Test public void testEntityQuery_implicitContainsAndFilters() throws Exception { testVariant("/t;id;type=metric/rt;id;name=kachna/entities", path().with(type(Tenant.class), id("id"), type(Metric.class)) .path().with(Related.by(contains)) .path().with(type(ResourceType.class), id("id")) .filter().with(name("kachna")).get()); } @Test public void testEntityQuery_jumpOverExplicitRelationship() throws Exception { testVariant("/t;id/rl;my-rel/rt;id/entities", path().with(type(Tenant.class), id("id")) .path().with(Related.by("my-rel")) .path().with(type(ResourceType.class), id("id")).get()); } @Test public void testEntityQuery_recursive_implicitRel() throws Exception { testVariant("/t;id/recursive;type=r/name=Kacer", path().with(type(Tenant.class), id("id")) .path() .with(RecurseFilter.builder().addChain(Related.by(contains), type(Resource.class)).build()) .filter().with(With.name("Kacer")).get()); } @Test public void testEntityQuery_recursive_explicitRel() throws Exception { testVariant("/t;id/recursive;over=kachna;type=r/entities;name=Kacer", path().with(type(Tenant.class), id("id")) .path() .with(RecurseFilter.builder().addChain(Related.by("kachna"), type(Resource.class)).build()) .filter().with(With.name("Kacer")).get()); } @Test public void testEntityQuery_recursive_noType() throws Exception { testVariant("/t;id/recursive;over=kachna/type=m", path().with(type(Tenant.class), id("id")) .path() .with(RecurseFilter.builder().addChain(Related.by("kachna")).build()) .path().with(type(Metric.class)).get()); } @Test public void testEntityQuery_recursive_noType_implicitRel() throws Exception { testVariant("/t;id/recursive/type=m", path().with(type(Tenant.class), id("id")) .path() .with(RecurseFilter.builder().addChain(Related.by(contains)).build()) .path().with(type(Metric.class)).get()); } @Test public void testFilterQuery_simple() throws Exception { testVariant("/r;id/type=rt/entities", path().with(type(Resource.class), id("id")) .path().with(Related.by(contains)) .path().with(type(ResourceType.class)).get()); } @Test public void testFilterQuery_multipleFilters() throws Exception { testVariant("/r;id/type=resource;name=kachna/entities", path().with(type(Resource.class), id("id")) .path().with(Related.by(contains)).path().with(type(Resource.class)).filter().with(name("kachna")) .get()); } @Test public void testFilterQuery_implicitContains() throws Exception { testVariant("/r;id/type=r/type=m/entities", path().with(type(Resource.class), id("id")) .path().with(Related.by("contains")) .path().with(type(Resource.class)) .path().with(Related.by(contains)) .path().with(type(Metric.class)).get()); } @Test public void testFilterQuery_relatedByToPairs() throws Exception { testVariant("/e;f;relatedTo=%2Ft%3Bid;relatedBy=kachna", path().with(type(SegmentType.e), id("f")) .filter().with(Related.with(CanonicalPath.of().tenant("id").get(), "kachna")) .get()); } @Test public void testFilterQuery_relatedByToWithPairs() throws Exception { testVariant("/e;f;relatedTo=%2Ft%3Bid;relatedBy=kachna;relatedWith=%2Ft%3Bid;relatedBy=drachma", path().with(type(SegmentType.e), id("f")) .filter().with(Related.with(CanonicalPath.of().tenant("id").get(), "kachna"), Related.asTargetWith(CanonicalPath.of().tenant("id").get(), "drachma")) .get()); } @Test public void testPrefixDoesntApplyToStartWithRelationship() throws Exception { testVariant("/rl;id/relationships", path().with(RelationWith.id("id")).get(), Query.builder().with(id("eee"))); } @Test public void testPathEndQuery_entity() throws Exception { testVariant("/entities", Query.empty()); } @Test public void testPathEndQuery_relationships() throws Exception { testVariant("/relationships", Query.path().with(SwitchElementType.outgoingRelationships()).get()); } @Test public void testPathEndQuery_relationships_explicitDirection() throws Exception { testVariant("/relationships;in", Query.path().with(SwitchElementType.incomingRelationships()).get()); } @Test public void testPathEndQuery_relationships_filters() throws Exception { testVariant("/relationships;name=kachna", Query.path().with(SwitchElementType.outgoingRelationships(), RelationWith.name("kachna")).get()); } @Test public void testEscapingInFilterNamesAndValues() throws Exception { testVariant("/name=A%20B", Query.path().filter().with(name("A B")).get()); } @Test public void testIdenticalProgression() throws Exception { testVariant("/r;id/identical/name=Kachna/rl;contains/m;id", Query.path() .with(type(r), id("id"), With.sameIdentityHash()) .filter().with(name("Kachna")).path().with(Related.by(contains), type(m), id("id")).get()); } @Test public void testRecursiveReturnsAllChildrenOfPrefix() throws Exception { testVariant("/recursive", Query.path().with(id("prefix"), RecurseFilter.builder().addChain(Related.by(contains)).build()).get(), Query.path().with(id("prefix")).rawQueryBuilder()); } private void testVariant(String uri, Query expected) throws Exception { testVariant(uri, expected, Query.builder()); } private void testVariant(String uri, Query expected, Query.Builder prefix) throws Exception { Traverser traverser = new Traverser(0, prefix, CanonicalPath::fromString); Query actual = traverser.navigate(uri); assertEquals(expected, actual); } }