/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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.apache.atlas.catalog.query; import com.thinkaurelius.titan.core.TitanGraph; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.gremlin.java.GremlinPipeline; import com.tinkerpop.pipes.Pipe; import org.apache.atlas.catalog.Request; import org.apache.atlas.catalog.VertexWrapper; import org.apache.atlas.catalog.definition.ResourceDefinition; import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.easymock.Capture; import org.testng.annotations.Test; import java.util.*; import static org.easymock.EasyMock.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; /** * Unit tests for AtlasEntityQuery. */ @SuppressWarnings("unchecked") public class AtlasEntityQueryTest { //todo: add tests for instance query and getInitialPipeline() @Test public void testExecute_Collection() throws Exception { AtlasGraph graph = createStrictMock(AtlasGraph.class); QueryExpression expression = createStrictMock(QueryExpression.class); ResourceDefinition resourceDefinition = createStrictMock(ResourceDefinition.class); Request request = createStrictMock(Request.class); GremlinPipeline initialPipeline = createStrictMock(GremlinPipeline.class); Pipe queryPipe = createStrictMock(Pipe.class); Pipe expressionPipe = createStrictMock(Pipe.class); Pipe notDeletedPipe = createStrictMock(Pipe.class); GremlinPipeline rootPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline queryPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline expressionPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline notDeletedPipeline = createStrictMock(GremlinPipeline.class); Vertex vertex1 = createStrictMock(Vertex.class); VertexWrapper vertex1Wrapper = createStrictMock(VertexWrapper.class); List<Vertex> results = new ArrayList<>(); results.add(vertex1); Map<String, Object> vertex1PropertyMap = new HashMap<>(); vertex1PropertyMap.put("prop1", "prop1.value1"); vertex1PropertyMap.put("prop2", "prop2.value1"); Map<String, Object> filteredVertex1PropertyMap = new HashMap<>(); filteredVertex1PropertyMap.put("prop1", "prop1.value1"); // mock expectations expect(initialPipeline.add(queryPipe)).andReturn(queryPipeline); expect(initialPipeline.add(notDeletedPipe)).andReturn(notDeletedPipeline); expect(initialPipeline.as("root")).andReturn(rootPipeline); expect(expression.asPipe()).andReturn(expressionPipe); expect(rootPipeline.add(expressionPipe)).andReturn(expressionPipeline); expect(expressionPipeline.back("root")).andReturn(rootPipeline); expect(rootPipeline.toList()).andReturn(results); graph.commit(); expect(vertex1Wrapper.getPropertyMap()).andReturn(vertex1PropertyMap); expect(resourceDefinition.filterProperties(request, vertex1PropertyMap)).andReturn(filteredVertex1PropertyMap); expect(resourceDefinition.resolveHref(filteredVertex1PropertyMap)).andReturn("/foo/bar"); expect(request.getCardinality()).andReturn(Request.Cardinality.COLLECTION); replay(graph, expression, resourceDefinition, request, initialPipeline, queryPipe, expressionPipe, notDeletedPipe, rootPipeline, queryPipeline, expressionPipeline, notDeletedPipeline, vertex1, vertex1Wrapper); // end mock expectations AtlasEntityQuery query = new TestAtlasEntityQuery(expression, resourceDefinition, request, initialPipeline, queryPipe, notDeletedPipe, graph, vertex1Wrapper); // invoke method being tested Collection<Map<String, Object>> queryResults = query.execute(); assertEquals(queryResults.size(), 1); Map<String, Object> queryResultMap = queryResults.iterator().next(); assertEquals(queryResultMap.size(), 2); assertEquals(queryResultMap.get("prop1"), "prop1.value1"); assertEquals(queryResultMap.get("href"), "/foo/bar"); verify(graph, expression, resourceDefinition, request, initialPipeline, queryPipe, expressionPipe, notDeletedPipe, rootPipeline, queryPipeline, expressionPipeline, notDeletedPipeline, vertex1, vertex1Wrapper); } @Test public void testExecute_Collection_rollbackOnException() throws Exception { AtlasGraph graph = createStrictMock(AtlasGraph.class); QueryExpression expression = createStrictMock(QueryExpression.class); ResourceDefinition resourceDefinition = createStrictMock(ResourceDefinition.class); Request request = createStrictMock(Request.class); GremlinPipeline initialPipeline = createStrictMock(GremlinPipeline.class); Pipe queryPipe = createStrictMock(Pipe.class); Pipe expressionPipe = createStrictMock(Pipe.class); Pipe notDeletedPipe = createStrictMock(Pipe.class); GremlinPipeline rootPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline queryPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline expressionPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline notDeletedPipeline = createStrictMock(GremlinPipeline.class); // mock expectations expect(initialPipeline.add(queryPipe)).andReturn(queryPipeline); expect(initialPipeline.add(notDeletedPipe)).andReturn(notDeletedPipeline); expect(initialPipeline.as("root")).andReturn(rootPipeline); expect(expression.asPipe()).andReturn(expressionPipe); expect(rootPipeline.add(expressionPipe)).andReturn(expressionPipeline); expect(expressionPipeline.back("root")).andReturn(rootPipeline); expect(rootPipeline.toList()).andThrow(new RuntimeException("something bad happened")); graph.rollback(); replay(graph, expression, resourceDefinition, request, initialPipeline, queryPipe, expressionPipe, notDeletedPipe, rootPipeline, queryPipeline, expressionPipeline, notDeletedPipeline); // end mock expectations AtlasEntityQuery query = new TestAtlasEntityQuery(expression, resourceDefinition, request, initialPipeline, queryPipe, notDeletedPipe, graph, null); try { // invoke method being tested query.execute(); fail("expected exception"); } catch (RuntimeException e) { assertEquals(e.getMessage(), "something bad happened"); } verify(graph, expression, resourceDefinition, request, initialPipeline, queryPipe, expressionPipe, notDeletedPipe, rootPipeline, queryPipeline, expressionPipeline, notDeletedPipeline); } @Test public void testExecute_Collection_update() throws Exception { AtlasGraph graph = createStrictMock(AtlasGraph.class); QueryExpression expression = createStrictMock(QueryExpression.class); ResourceDefinition resourceDefinition = createStrictMock(ResourceDefinition.class); Request request = createStrictMock(Request.class); GremlinPipeline initialPipeline = createStrictMock(GremlinPipeline.class); Pipe queryPipe = createStrictMock(Pipe.class); Pipe expressionPipe = createStrictMock(Pipe.class); Pipe notDeletedPipe = createStrictMock(Pipe.class); GremlinPipeline rootPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline queryPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline expressionPipeline = createStrictMock(GremlinPipeline.class); GremlinPipeline notDeletedPipeline = createStrictMock(GremlinPipeline.class); Vertex vertex1 = createStrictMock(Vertex.class); VertexWrapper vertex1Wrapper = createStrictMock(VertexWrapper.class); Capture<Long> modifiedTimestampCapture = newCapture(); List<Vertex> results = new ArrayList<>(); results.add(vertex1); Map<String, Object> vertex1PropertyMap = new HashMap<>(); vertex1PropertyMap.put("prop1", "prop1.value1"); vertex1PropertyMap.put("prop2", "prop2.value1"); Map<String, Object> filteredVertex1PropertyMap = new HashMap<>(); filteredVertex1PropertyMap.put("prop1", "prop1.value1"); Map<String, Object> updateProperties = new HashMap<>(); updateProperties.put("prop3", "newValue"); // mock expectations expect(initialPipeline.add(queryPipe)).andReturn(queryPipeline); expect(initialPipeline.add(notDeletedPipe)).andReturn(notDeletedPipeline); expect(initialPipeline.as("root")).andReturn(rootPipeline); expect(expression.asPipe()).andReturn(expressionPipe); expect(rootPipeline.add(expressionPipe)).andReturn(expressionPipeline); expect(expressionPipeline.back("root")).andReturn(rootPipeline); expect(rootPipeline.toList()).andReturn(results); graph.commit(); vertex1Wrapper.setProperty("prop3", "newValue"); vertex1Wrapper.setProperty(eq(Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY), capture(modifiedTimestampCapture)); expect(vertex1Wrapper.getPropertyMap()).andReturn(vertex1PropertyMap); expect(resourceDefinition.filterProperties(request, vertex1PropertyMap)).andReturn(filteredVertex1PropertyMap); expect(resourceDefinition.resolveHref(filteredVertex1PropertyMap)).andReturn("/foo/bar"); expect(request.getCardinality()).andReturn(Request.Cardinality.COLLECTION); replay(graph, expression, resourceDefinition, request, initialPipeline, queryPipe, expressionPipe, notDeletedPipe, rootPipeline, queryPipeline, expressionPipeline, notDeletedPipeline, vertex1, vertex1Wrapper); // end mock expectations AtlasEntityQuery query = new TestAtlasEntityQuery(expression, resourceDefinition, request, initialPipeline, queryPipe, notDeletedPipe, graph, vertex1Wrapper); long startTime = System.currentTimeMillis(); // invoke method being tested Collection<Map<String, Object>> queryResults = query.execute(updateProperties); long endTime = System.currentTimeMillis(); assertEquals(queryResults.size(), 1); Map<String, Object> queryResultMap = queryResults.iterator().next(); assertEquals(queryResultMap.size(), 2); assertEquals(queryResultMap.get("prop1"), "prop1.value1"); assertEquals(queryResultMap.get("href"), "/foo/bar"); long modifiedTimestamp = modifiedTimestampCapture.getValue(); assertTrue(modifiedTimestamp >= startTime && modifiedTimestamp <= endTime); verify(graph, expression, resourceDefinition, request, initialPipeline, queryPipe, expressionPipe, notDeletedPipe, rootPipeline, queryPipeline, expressionPipeline, notDeletedPipeline, vertex1, vertex1Wrapper); } private class TestAtlasEntityQuery extends AtlasEntityQuery { private final GremlinPipeline initialPipeline; private final Pipe queryPipe; private final Pipe notDeletedPipe; private final AtlasGraph graph; private final VertexWrapper vWrapper; public TestAtlasEntityQuery(QueryExpression queryExpression, ResourceDefinition resourceDefinition, Request request, GremlinPipeline initialPipeline, Pipe queryPipe, Pipe notDeletedPipe, AtlasGraph graph, VertexWrapper vWrapper) { super(queryExpression, resourceDefinition, request); this.initialPipeline = initialPipeline; this.queryPipe = queryPipe; this.notDeletedPipe = notDeletedPipe; this.graph = graph; this.vWrapper = vWrapper; } @Override protected GremlinPipeline getRootVertexPipeline() { return initialPipeline; } @Override protected Pipe getQueryPipe() { return queryPipe; } @Override protected Pipe getNotDeletedPipe() { return notDeletedPipe; } @Override protected AtlasGraph getGraph() { return graph; } @Override protected VertexWrapper wrapVertex(Vertex v) { return vWrapper; } } }