org.janusgraph.graphdb.JanusGraphTest Maven / Gradle / Ivy
// Copyright 2017 JanusGraph Authors
//
// 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.janusgraph.graphdb;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.github.artsok.RepeatedIfExceptionsTest;
import org.apache.commons.configuration2.MapConfiguration;
import org.apache.commons.lang.NotImplementedException;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.TextP;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
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.filter.HasStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.janusgraph.TestCategory;
import org.janusgraph.core.Cardinality;
import org.janusgraph.core.EdgeLabel;
import org.janusgraph.core.JanusGraph;
import org.janusgraph.core.JanusGraphConfigurationException;
import org.janusgraph.core.JanusGraphEdge;
import org.janusgraph.core.JanusGraphElement;
import org.janusgraph.core.JanusGraphException;
import org.janusgraph.core.JanusGraphFactory;
import org.janusgraph.core.JanusGraphTransaction;
import org.janusgraph.core.JanusGraphVertex;
import org.janusgraph.core.JanusGraphVertexProperty;
import org.janusgraph.core.Multiplicity;
import org.janusgraph.core.PropertyKey;
import org.janusgraph.core.RelationType;
import org.janusgraph.core.SchemaViolationException;
import org.janusgraph.core.VertexLabel;
import org.janusgraph.core.VertexList;
import org.janusgraph.core.attribute.Cmp;
import org.janusgraph.core.attribute.Contain;
import org.janusgraph.core.attribute.Geoshape;
import org.janusgraph.core.log.Change;
import org.janusgraph.core.log.LogProcessorFramework;
import org.janusgraph.core.log.TransactionRecovery;
import org.janusgraph.core.schema.ConsistencyModifier;
import org.janusgraph.core.schema.DisableDefaultSchemaMaker;
import org.janusgraph.core.schema.IgnorePropertySchemaMaker;
import org.janusgraph.core.schema.JanusGraphDefaultSchemaMaker;
import org.janusgraph.core.schema.JanusGraphIndex;
import org.janusgraph.core.schema.JanusGraphManagement;
import org.janusgraph.core.schema.JanusGraphSchemaType;
import org.janusgraph.core.schema.Mapping;
import org.janusgraph.core.schema.RelationTypeIndex;
import org.janusgraph.core.schema.SchemaAction;
import org.janusgraph.core.schema.SchemaStatus;
import org.janusgraph.core.util.ManagementUtil;
import org.janusgraph.diskstorage.Backend;
import org.janusgraph.diskstorage.BackendException;
import org.janusgraph.diskstorage.BackendTransaction;
import org.janusgraph.diskstorage.Entry;
import org.janusgraph.diskstorage.StaticBuffer;
import org.janusgraph.diskstorage.configuration.ConfigElement;
import org.janusgraph.diskstorage.configuration.ConfigOption;
import org.janusgraph.diskstorage.configuration.WriteConfiguration;
import org.janusgraph.diskstorage.keycolumnvalue.scan.ScanJobFuture;
import org.janusgraph.diskstorage.keycolumnvalue.scan.ScanMetrics;
import org.janusgraph.diskstorage.locking.PermanentLockingException;
import org.janusgraph.diskstorage.log.Log;
import org.janusgraph.diskstorage.log.Message;
import org.janusgraph.diskstorage.log.MessageReader;
import org.janusgraph.diskstorage.log.ReadMarker;
import org.janusgraph.diskstorage.log.kcvs.KCVSLog;
import org.janusgraph.diskstorage.util.CacheMetricsAction;
import org.janusgraph.diskstorage.util.HashingUtil;
import org.janusgraph.diskstorage.util.time.TimestampProvider;
import org.janusgraph.example.GraphOfTheGodsFactory;
import org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration;
import org.janusgraph.graphdb.database.EdgeSerializer;
import org.janusgraph.graphdb.database.IndexRecordEntry;
import org.janusgraph.graphdb.database.IndexSerializer;
import org.janusgraph.graphdb.database.StandardJanusGraph;
import org.janusgraph.graphdb.database.cache.CacheInvalidationService;
import org.janusgraph.graphdb.database.index.IndexMutationType;
import org.janusgraph.graphdb.database.index.IndexUpdate;
import org.janusgraph.graphdb.database.log.LogTxMeta;
import org.janusgraph.graphdb.database.log.LogTxStatus;
import org.janusgraph.graphdb.database.log.TransactionLogHeader;
import org.janusgraph.graphdb.database.management.ManagementSystem;
import org.janusgraph.graphdb.database.serialize.Serializer;
import org.janusgraph.graphdb.database.util.IndexRecordUtil;
import org.janusgraph.graphdb.database.util.StaleIndexRecordUtil;
import org.janusgraph.graphdb.internal.ElementCategory;
import org.janusgraph.graphdb.internal.ElementLifeCycle;
import org.janusgraph.graphdb.internal.InternalElement;
import org.janusgraph.graphdb.internal.InternalRelationType;
import org.janusgraph.graphdb.internal.InternalVertex;
import org.janusgraph.graphdb.internal.Order;
import org.janusgraph.graphdb.log.StandardTransactionLogProcessor;
import org.janusgraph.graphdb.olap.job.GhostVertexRemover;
import org.janusgraph.graphdb.olap.job.IndexRemoveJob;
import org.janusgraph.graphdb.olap.job.IndexRepairJob;
import org.janusgraph.graphdb.query.JanusGraphPredicateUtils;
import org.janusgraph.graphdb.query.QueryUtil;
import org.janusgraph.graphdb.query.condition.MultiCondition;
import org.janusgraph.graphdb.query.condition.PredicateCondition;
import org.janusgraph.graphdb.query.index.IndexSelectionUtil;
import org.janusgraph.graphdb.query.profile.QueryProfiler;
import org.janusgraph.graphdb.relations.RelationIdentifier;
import org.janusgraph.graphdb.relations.StandardEdge;
import org.janusgraph.graphdb.relations.StandardVertexProperty;
import org.janusgraph.graphdb.serializer.SpecialInt;
import org.janusgraph.graphdb.serializer.SpecialIntSerializer;
import org.janusgraph.graphdb.tinkerpop.optimize.step.JanusGraphElementMapStep;
import org.janusgraph.graphdb.tinkerpop.optimize.step.JanusGraphHasStep;
import org.janusgraph.graphdb.tinkerpop.optimize.step.JanusGraphPropertiesStep;
import org.janusgraph.graphdb.tinkerpop.optimize.step.JanusGraphPropertyMapStep;
import org.janusgraph.graphdb.tinkerpop.optimize.strategy.MultiQueryHasStepStrategyMode;
import org.janusgraph.graphdb.tinkerpop.optimize.strategy.MultiQueryLabelStepStrategyMode;
import org.janusgraph.graphdb.tinkerpop.optimize.strategy.MultiQueryPropertiesStrategyMode;
import org.janusgraph.graphdb.tinkerpop.optimize.strategy.MultiQueryStrategyRepeatStepMode;
import org.janusgraph.graphdb.transaction.StandardJanusGraphTx;
import org.janusgraph.graphdb.types.CompositeIndexType;
import org.janusgraph.graphdb.types.StandardEdgeLabelMaker;
import org.janusgraph.graphdb.types.StandardPropertyKeyMaker;
import org.janusgraph.graphdb.types.system.BaseVertexLabel;
import org.janusgraph.graphdb.types.system.ImplicitKey;
import org.janusgraph.graphdb.types.vertices.JanusGraphSchemaVertex;
import org.janusgraph.graphdb.vertices.CacheVertex;
import org.janusgraph.testutil.FeatureFlag;
import org.janusgraph.testutil.JanusGraphFeature;
import org.janusgraph.testutil.TestGraphConfigs;
import org.janusgraph.util.IDUtils;
import org.janusgraph.util.stats.MetricManager;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.opentest4j.AssertionFailedError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.tinkerpop.gremlin.process.traversal.Order.asc;
import static org.apache.tinkerpop.gremlin.process.traversal.Order.desc;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasNot;
import static org.apache.tinkerpop.gremlin.structure.Direction.BOTH;
import static org.apache.tinkerpop.gremlin.structure.Direction.IN;
import static org.apache.tinkerpop.gremlin.structure.Direction.OUT;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.ADJUST_LIMIT;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.ALLOW_CUSTOM_VERTEX_ID_TYPES;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.ALLOW_SETTING_VERTEX_ID;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.ALLOW_STALE_CONFIG;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.AUTO_TYPE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.BASIC_METRICS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.CUSTOM_ATTRIBUTE_CLASS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.CUSTOM_SERIALIZER_CLASS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.DB_CACHE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.DB_CACHE_CLEAN_WAIT;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.DB_CACHE_TIME;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.FORCE_INDEX_USAGE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.HARD_MAX_LIMIT;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.HAS_STEP_BATCH_MODE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.IDS_STORE_NAME;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.INITIAL_JANUSGRAPH_VERSION;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.LABEL_STEP_BATCH_MODE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.LIMITED_BATCH;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.LIMITED_BATCH_SIZE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.LOG_BACKEND;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.LOG_READ_INTERVAL;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.LOG_SEND_DELAY;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.MANAGEMENT_LOG;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.MAX_COMMIT_TIME;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.METRICS_MERGE_STORES;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.PARALLEL_BACKEND_OPS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.PROPERTIES_BATCH_MODE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.PROPERTY_PREFETCHING;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.REPEAT_STEP_BATCH_MODE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.REPLACE_INSTANCE_IF_EXISTS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.SCHEMA_CONSTRAINTS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.SCRIPT_EVAL_ENABLED;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.SCRIPT_EVAL_ENGINE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.STORAGE_BACKEND;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.STORAGE_BATCH;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.STORAGE_READONLY;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.SYSTEM_LOG_TRANSACTIONS;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.TRANSACTION_LOG;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.TX_CACHE_SIZE;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.UNIQUE_INSTANCE_ID;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.USER_LOG;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.USE_MULTIQUERY;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.VERBOSE_TX_RECOVERY;
import static org.janusgraph.graphdb.internal.RelationCategory.EDGE;
import static org.janusgraph.graphdb.internal.RelationCategory.PROPERTY;
import static org.janusgraph.graphdb.internal.RelationCategory.RELATION;
import static org.janusgraph.testutil.JanusGraphAssert.assertContains;
import static org.janusgraph.testutil.JanusGraphAssert.assertCount;
import static org.janusgraph.testutil.JanusGraphAssert.assertEmpty;
import static org.janusgraph.testutil.JanusGraphAssert.assertNotEmpty;
import static org.janusgraph.testutil.JanusGraphAssert.getLastStepMetrics;
import static org.janusgraph.testutil.JanusGraphAssert.getStepMetrics;
import static org.janusgraph.testutil.JanusGraphAssert.queryProfilerAnnotationIsPresent;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author Matthias Broecheler ([email protected])
* @author Joshua Shinavier (http://fortytwo.net)
*/
public abstract class JanusGraphTest extends JanusGraphBaseTest {
private final Logger log = LoggerFactory.getLogger(JanusGraphTest.class);
final boolean isLockingOptimistic() {
return features.hasOptimisticLocking();
}
/* ==================================================================================
UPDATE THEN REMOVE IN THE SAME TRANSACTION
==================================================================================*/
private void initializeGraphWithVerticesAndEdges() {
if (mgmt.getEdgeLabel("fork-connect") == null) {
EdgeLabel forkConnect = mgmt.makeEdgeLabel("fork-connect").make();
mgmt.setConsistency(forkConnect, ConsistencyModifier.FORK);
finishSchema();
}
Vertex v = graph.traversal().addV().property("_v", 1).next();
v.property("_v").property("flag", false);
Vertex v2 = graph.traversal().addV().property("_v", 2).property("prop", "old").next();
Edge edge = v.addEdge("connect", v2, "_e", 1);
Edge forkEdge = v.addEdge("fork-connect", v2, "_e", 2);
graph.tx().commit();
}
@Test
public void testUpdateVertexPropThenRemoveProp() {
initializeGraphWithVerticesAndEdges();
Vertex v2 = graph.traversal().V().has("_v", 2).next();
assertEquals("old", v2.property("prop").value());
v2.property("prop", "new");
assertEquals("new", v2.property("prop").value());
v2.property("prop", "new2");
assertEquals("new2", v2.property("prop").value());
v2 = graph.traversal().V().has("_v", 2).next();
v2.property("prop", "new3");
assertEquals("new3", v2.property("prop").value());
v2.property("prop").remove();
graph.tx().commit();
assertFalse(graph.traversal().V(v2).values("prop").hasNext());
}
@Test
public void testNestedAddVertexPropThenRemoveProp() {
// prepare graph with a single vertex
mgmt.makePropertyKey("prop").dataType(String.class).make();
mgmt.commit();
graph.addVertex();
graph.tx().commit();
// open two transactions at the same time
final JanusGraphTransaction tx1 = graph.newTransaction();
final JanusGraphTransaction tx2 = graph.newTransaction();
// tx1: add property
tx1.traversal().V().next().property("prop", "tx1");
// tx2: add property
Vertex v = tx2.traversal().V().next();
v.property("prop", "tx2");
// tx1: commit
tx1.commit();
// tx2: remove property
v.property("prop").remove();
// tx2: commit
tx2.commit();
assertTrue(graph.traversal().V().hasNext());
assertFalse(graph.traversal().V().values("prop").hasNext());
}
@Test
public void testUpdateVertexPropThenRemoveVertex() {
initializeGraphWithVerticesAndEdges();
Vertex v2 = graph.traversal().V().has("_v", 2).next();
assertEquals("old", v2.property("prop").value());
v2.property("prop", "new");
assertEquals("new", v2.property("prop").value());
v2 = graph.traversal().V().has("_v", 2).next();
v2.property("prop", "new2");
assertEquals("new2", v2.property("prop").value());
v2.remove();
graph.tx().commit();
assertFalse(graph.traversal().V(v2).hasNext());
assertFalse(graph.traversal().V().has("prop", "old").hasNext());
assertFalse(graph.traversal().V().has("prop", "new").hasNext());
}
/**
* update property of a vertex property and remove the vertex property
*/
@Test
public void testUpdatePropertyPropThenRemoveProperty() {
for (boolean reload : Arrays.asList(true, false)) {
graph.traversal().V().drop().iterate();
initializeGraphWithVerticesAndEdges();
assertTrue(graph.traversal().V().has("_v", 1).values("_v").hasNext());
VertexProperty p = (VertexProperty) graph.traversal().V().has("_v", 1).properties("_v").next();
assertEquals(false, p.property("flag").value());
p.property("flag", true);
assertEquals(true, p.property("flag").value());
if (!reload) {
p.remove();
} else {
graph.traversal().V().has("_v", 1).properties("_v").next().remove();
}
graph.tx().commit();
assertFalse(graph.traversal().V().has("_v", 1).values("_v").hasNext());
}
}
/**
* update property of a vertex property and remove the property of the vertex property
*/
@Test
public void testUpdatePropertyPropThenRemovePropertyProp() {
initializeGraphWithVerticesAndEdges();
VertexProperty p = (VertexProperty) graph.traversal().V().has("_v", 1).properties("_v").next();
assertTrue(graph.traversal().V().has("_v", 1).properties("_v").values("flag").hasNext());
assertEquals(false, p.property("flag").value());
p.property("flag", true);
assertEquals(true, p.property("flag").value());
p.property("flag").remove();
graph.tx().commit();
assertTrue(graph.traversal().V().has("_v", 1).values("_v").hasNext());
assertFalse(graph.traversal().V().has("_v", 1).properties("_v").values("flag").hasNext());
}
@Test
public void testUpdatePropertyPropThenRemoveVertex() {
initializeGraphWithVerticesAndEdges();
Vertex v = graph.traversal().V().has("_v", 1).next();
VertexProperty p = v.properties("_v").next();
assertEquals(false, p.property("flag").value());
p.property("flag", true);
assertEquals(true, p.property("flag").value());
p.property("flag").remove();
v.remove();
graph.tx().commit();
assertFalse(graph.traversal().V().has("_v", 1).hasNext());
}
@Test
public void testUpdateEdgePropertyThenRemoveEdge() {
initializeGraphWithVerticesAndEdges();
// normal edge
InternalElement edge = (InternalElement) graph.traversal().E().has("_e", 1).next();
assertTrue(ElementLifeCycle.isLoaded(edge.getLifeCycle()));
Object id = edge.id();
for (int val : Arrays.asList(-1, -11)) {
edge.property("_e", val);
// the edge object represents the old edge to be deleted
assertEquals(id, edge.id());
assertTrue(ElementLifeCycle.isRemoved(edge.getLifeCycle()));
// the edge object has a corresponding new edge with same id
assertEquals(id, edge.it().id());
assertTrue(ElementLifeCycle.isNew(edge.it().getLifeCycle()));
assertTrue(edge.isNew());
}
edge.remove();
graph.tx().commit();
assertFalse(graph.traversal().E().has("_e", 1).hasNext());
assertFalse(graph.traversal().E().has("_e", -1).hasNext());
assertFalse(graph.traversal().E().has("_e", -11).hasNext());
assertTrue(graph.traversal().E().has("_e", 2).hasNext());
}
@Test
public void testUpdateForkEdgePropertyThenRemoveEdge() {
initializeGraphWithVerticesAndEdges();
// fork edge
InternalElement edge = (InternalElement) graph.traversal().E().has("_e", 2).next();
assertTrue(ElementLifeCycle.isLoaded(edge.getLifeCycle()));
Object id = edge.id();
edge.property("_e", -2);
// the edge object represents the old edge to be deleted
assertEquals(id, edge.id());
assertTrue(ElementLifeCycle.isRemoved(edge.getLifeCycle()));
// the edge object has a corresponding new (forked) edge with different id
Object forkedId = edge.it().id();
assertNotEquals(id, forkedId);
assertTrue(ElementLifeCycle.isNew(edge.it().getLifeCycle()));
assertTrue(edge.isNew());
edge.property("_e", -3);
assertEquals(id, edge.id());
assertTrue(ElementLifeCycle.isRemoved(edge.getLifeCycle()));
assertEquals(forkedId, edge.it().id());
assertTrue(ElementLifeCycle.isNew(edge.it().getLifeCycle()));
assertTrue(edge.isNew());
edge.remove();
graph.tx().commit();
assertFalse(graph.traversal().E().has("_e", 2).hasNext());
assertFalse(graph.traversal().E().has("_e", -2).hasNext());
assertFalse(graph.traversal().E().has("_e", -3).hasNext());
}
@Test
public void testUpdateForkEdgePropertyThenFindEdgeById() {
initializeGraphWithVerticesAndEdges();
InternalElement edge = (InternalElement) graph.traversal().E().has("_e", 2).next();
Object id = edge.id();
edge.property("_e", -2);
assertTrue(graph.traversal().E(id).hasNext());
}
/* ==================================================================================
INDEXING
==================================================================================*/
/**
* Just opens and closes the graph
*/
@Test
public void testOpenClose() {
}
/**
* Ensure clearing storage actually removes underlying database.
* @throws Exception
*/
@Test
public void testClearStorage() throws Exception {
tearDown();
config.set(ConfigElement.getPath(GraphDatabaseConfiguration.DROP_ON_CLEAR), true);
final Backend backend = getBackend(config, false);
assertTrue(backend.getStoreManager().exists(), "graph should exist before clearing storage");
clearGraph(config);
assertFalse(backend.getStoreManager().exists(), "graph should not exist after clearing storage");
}
/**
* Very simple graph operation to ensure minimal functionality and cleanup
*/
@Test
public void testBasic() throws BackendException {
PropertyKey uid = makeVertexIndexedUniqueKey("name", String.class);
finishSchema();
JanusGraphVertex n1 = tx.addVertex();
uid = tx.getPropertyKey("name");
n1.property(uid.name(), "abcd");
clopen();
long nid = (long) n1.id();
uid = tx.getPropertyKey("name");
assertNotNull(getV(tx, nid));
assertNotNull(getV(tx, uid.id()));
// even though id is long-type, we can use string-type to query and JanusGraph will cast it to long
assertNotNull(getV(tx, uid.id().toString()));
assertMissing(tx, nid + 64);
uid = tx.getPropertyKey(uid.name());
n1 = getV(tx, nid);
assertEquals(n1, getOnlyVertex(tx.query().has(uid.name(), "abcd")));
assertEquals(1, Iterables.size(n1.query().relations())); //TODO: how to expose relations?
assertEquals("abcd", n1.value(uid.name()));
assertCount(1, tx.query().vertices());
close();
JanusGraphFactory.drop(graph);
open(config);
assertEmpty(tx.query().vertices());
}
@Test
public void testVariables() {
assertTrue(graph.variables().asMap().isEmpty());
graph.variables().set("systemAdmins", "stephen, peter, pavel");
graph.variables().set("systemUsers", "matthias, marko, josh");
assertEquals(new HashSet<>(Arrays.asList("systemAdmins", "systemUsers")), graph.variables().keys());
assertEquals("matthias, marko, josh", graph.variables().get("systemUsers").get());
graph.variables().remove("systemAdmins");
assertEquals(new HashSet<>(Arrays.asList("systemUsers")), graph.variables().keys());
}
/**
* Adding a removing a vertex with index
*/
@Test
public void testVertexRemoval() {
final String nameUniqueVertexPropertyName = "name";
makeVertexIndexedUniqueKey(nameUniqueVertexPropertyName, String.class);
finishSchema();
JanusGraphVertex v1 = graph.addVertex(nameUniqueVertexPropertyName, "v1");
JanusGraphVertex v2 = graph.addVertex(nameUniqueVertexPropertyName, "v2");
v1.addEdge("knows", v2);
assertCount(2, graph.query().vertices());
assertCount(1, graph.query().has(nameUniqueVertexPropertyName, "v2").vertices());
clopen();
v1 = getV(graph, v1);
v2 = getV(graph, v2);
assertCount(1, v1.query().direction(BOTH).edges());
assertCount(1, v2.query().direction(Direction.BOTH).edges());
v2.remove();
assertCount(0, v1.query().direction(Direction.BOTH).edges());
final JanusGraphVertex v2Copied = v2;
assertThrows(IllegalStateException.class, ()-> v2Copied.query().direction(Direction.BOTH).edges());
assertCount(1, graph.query().vertices());
assertCount(1, graph.query().has(nameUniqueVertexPropertyName, "v1").vertices());
assertCount(0, graph.query().has(nameUniqueVertexPropertyName, "v2").vertices());
graph.tx().commit();
assertMissing(graph, v2);
assertCount(1, graph.query().vertices());
assertCount(1, graph.query().has(nameUniqueVertexPropertyName, "v1").vertices());
assertCount(0, graph.query().has(nameUniqueVertexPropertyName, "v2").vertices());
}
/**
* Iterating over all vertices and edges in a graph
*/
@Test
public void testGlobalIteration() {
int numV = 50;
int deleteV = 5;
JanusGraphVertex previous = tx.addVertex("count", 0);
for (int i = 1; i < numV; i++) {
JanusGraphVertex next = tx.addVertex("count", i);
previous.addEdge("next", next);
previous = next;
}
int numE = numV - 1;
assertCount(numV, tx.query().vertices());
assertCount(numV, tx.query().vertices());
assertCount(numE, tx.query().edges());
assertCount(numE, tx.query().edges());
clopen();
assertCount(numV, tx.query().vertices());
assertCount(numV, tx.query().vertices());
assertCount(numE, tx.query().edges());
assertCount(numE, tx.query().edges());
//tx.V().range(0,deleteV).remove();
for (JanusGraphVertex v : tx.query().limit(deleteV).vertices()) {
v.remove();
}
for (int i = 0; i < 10; i++) { //Repeated vertex counts
assertCount(numV - deleteV, tx.query().vertices());
assertCount(numV - deleteV, tx.query().has("count", Cmp.GREATER_THAN_EQUAL, 0).vertices());
}
clopen();
for (int i = 0; i < 10; i++) { //Repeated vertex counts
assertCount(numV - deleteV, tx.query().vertices());
assertCount(numV - deleteV, tx.query().has("count", Cmp.GREATER_THAN_EQUAL, 0).vertices());
}
}
@Test
public void testMediumCreateRetrieve() {
//Create schema
makeLabel("connect");
makeVertexIndexedUniqueKey("name", String.class);
PropertyKey weight = makeKey("weight", Double.class);
PropertyKey id = makeVertexIndexedUniqueKey("uid", Integer.class);
((StandardEdgeLabelMaker) mgmt.makeEdgeLabel("knows")).sortKey(id).signature(weight).make();
finishSchema();
//Create Nodes
int noVertices = 500;
String[] names = new String[noVertices];
int[] ids = new int[noVertices];
JanusGraphVertex[] nodes = new JanusGraphVertex[noVertices];
Object[] nodeIds = new Object[noVertices];
List[] nodeEdges = new List[noVertices];
for (int i = 0; i < noVertices; i++) {
names[i] = "vertex" + i;
ids[i] = i;
nodes[i] = tx.addVertex("name", names[i], "uid", ids[i]);
if ((i + 1) % 100 == 0) log.debug("Added 100 nodes");
}
log.debug("Nodes created");
int[] connectOff = {-100, -34, -4, 10, 20};
int[] knowsOff = {-400, -18, 8, 232, 334};
for (int i = 0; i < noVertices; i++) {
JanusGraphVertex n = nodes[i];
nodeEdges[i] = new ArrayList<>(10);
for (int c : connectOff) {
Edge r = n.addEdge("connect", nodes[wrapAround(i + c, noVertices)]);
nodeEdges[i].add(r);
}
for (int k : knowsOff) {
JanusGraphVertex n2 = nodes[wrapAround(i + k, noVertices)];
Edge r = n.addEdge("knows", n2,
"uid", ((Number) n.value("uid")).intValue() + ((Number) n2.value("uid")).intValue(),
"weight", k * 1.5,
"name", i + "-" + k);
nodeEdges[i].add(r);
}
if (i % 100 == 99) log.debug(".");
}
tx.commit();
tx = null;
Set[] nodeEdgeIds = new Set[noVertices];
for (int i = 0; i < noVertices; i++) {
nodeIds[i] = (Long) nodes[i].id();
nodeEdgeIds[i] = new HashSet(10);
for (Object r : nodeEdges[i]) {
nodeEdgeIds[i].add(((JanusGraphEdge) r).id());
}
}
clopen();
nodes = new JanusGraphVertex[noVertices];
for (int i = 0; i < noVertices; i++) {
JanusGraphVertex n = getVertex("uid", ids[i]);
assertEquals(n, getVertex("name", names[i]));
assertEquals(names[i], n.value("name"));
nodes[i] = n;
assertEquals(nodeIds[i], n.id());
}
for (int i = 0; i < noVertices; i++) {
JanusGraphVertex n = nodes[i];
assertCount(connectOff.length + knowsOff.length, n.query().direction(Direction.OUT).edges());
assertCount(connectOff.length, n.query().direction(Direction.OUT).labels("connect").edges());
assertCount(connectOff.length * 2, n.query().direction(Direction.BOTH).labels("connect").edges());
assertCount(knowsOff.length * 2, n.query().direction(Direction.BOTH).labels("knows").edges());
assertCount(connectOff.length + knowsOff.length, n.query().direction(Direction.OUT).edges());
assertCount(2, n.properties());
for (JanusGraphEdge o : n.query().direction(Direction.OUT).labels("knows").edges()) {
JanusGraphEdge r = o;
JanusGraphVertex n2 = r.vertex(Direction.IN);
int idSum = ((Number) n.value("uid")).intValue() + ((Number) n2.value("uid")).intValue();
assertEquals(idSum, ((Number) r.value("uid")).intValue());
double k = ((Number) r.value("weight")).doubleValue() / 1.5;
int ki = (int) k;
assertEquals(i + "-" + ki, r.value("name"));
}
Set edgeIds = new HashSet(10);
for (JanusGraphEdge r : n.query().direction(Direction.OUT).edges()) {
edgeIds.add(r.id());
}
assertEquals(edgeIds, nodeEdgeIds[i], edgeIds + " vs " + nodeEdgeIds[i]);
}
newTx();
//Bulk vertex retrieval
Object[] vertexIdsOne = new Object[noVertices / 10];
System.arraycopy(nodeIds, 0, vertexIdsOne, 0, vertexIdsOne.length);
//All non-cached
verifyVerticesRetrieval(vertexIdsOne, Lists.newArrayList(tx.getVertices(vertexIdsOne)));
//All cached
verifyVerticesRetrieval(vertexIdsOne, Lists.newArrayList(tx.getVertices(vertexIdsOne)));
Object[] vertexIdsTwo = new Object[noVertices / 10 * 2];
System.arraycopy(nodeIds, 0, vertexIdsTwo, 0, vertexIdsTwo.length);
//Partially cached
verifyVerticesRetrieval(vertexIdsTwo, Lists.newArrayList(tx.getVertices(vertexIdsTwo)));
}
private void verifyVerticesRetrieval(Object[] vertexIds, List vs) {
assertEquals(vertexIds.length, vs.size());
final Set
© 2015 - 2024 Weber Informatics LLC | Privacy Policy