/* * DISCLAIMER * * Copyright 2016 ArangoDB GmbH, Cologne, Germany * * 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. * * Copyright holder is ArangoDB GmbH, Cologne, Germany */ package com.arangodb.async; import com.arangodb.ArangoDBException; import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; import com.arangodb.entity.*; import com.arangodb.entity.AqlParseEntity.AstNode; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; import com.arangodb.model.TraversalOptions.Direction; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackException; import org.junit.Ignore; import org.junit.Test; import java.io.IOException; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; /** * @author Mark Vollmary * @author Michele Rastelli */ public class ArangoDatabaseTest extends BaseTest { private static final String COLLECTION_NAME = "db_test"; private static final String GRAPH_NAME = "graph_test"; @Test public void create() throws InterruptedException, ExecutionException { try { final Boolean result = arangoDB.db(BaseTest.TEST_DB + "_1").create().get(); assertThat(result, is(true)); } finally { arangoDB.db(BaseTest.TEST_DB + "_1").drop().get(); } } @Test public void getVersion() throws InterruptedException, ExecutionException { db.getVersion() .whenComplete((version, ex) -> { assertThat(version, is(notNullValue())); assertThat(version.getServer(), is(notNullValue())); assertThat(version.getVersion(), is(notNullValue())); }) .get(); } @Test public void getEngine() throws ExecutionException, InterruptedException { final ArangoDBEngine engine = db.getEngine().get(); assertThat(engine, is(notNullValue())); assertThat(engine.getName(), is(notNullValue())); } @Test public void exists() throws InterruptedException, ExecutionException { assertThat(db.exists().get(), is(true)); assertThat(arangoDB.db("no").exists().get(), is(false)); } @Test public void getAccessibleDatabases() throws InterruptedException, ExecutionException { db.getAccessibleDatabases() .whenComplete((dbs, ex) -> { assertThat(dbs, is(notNullValue())); assertThat(dbs.size(), greaterThan(0)); assertThat(dbs, hasItem("_system")); }) .get(); } @Test public void createCollection() throws InterruptedException, ExecutionException { db.createCollection(COLLECTION_NAME, null) .whenComplete((result, ex) -> { assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); }) .get(); db.collection(COLLECTION_NAME).drop().get(); } @Test public void createCollectionWithReplicationFactor() throws InterruptedException, ExecutionException { assumeTrue(isCluster()); final CollectionEntity result = db .createCollection(COLLECTION_NAME, new CollectionCreateOptions().replicationFactor(2)).get(); assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor(), is(2)); db.collection(COLLECTION_NAME).drop().get(); } @Test public void createCollectionWithMinReplicationFactor() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isCluster()); final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().replicationFactor(2).minReplicationFactor(2)).get(); assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor(), is(2)); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getMinReplicationFactor(), is(2)); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getSatellite(), is(nullValue())); db.collection(COLLECTION_NAME).drop(); } @Test public void createCollectionWithNumberOfShards() throws InterruptedException, ExecutionException { assumeTrue(isCluster()); final CollectionEntity result = db .createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2)).get(); assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getNumberOfShards(), is(2)); db.collection(COLLECTION_NAME).drop().get(); } @Test public void createCollectionWithNumberOfShardsAndShardKey() throws InterruptedException, ExecutionException { assumeTrue(isCluster()); final CollectionEntity result = db .createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2).shardKeys("a")) .get(); assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); final CollectionPropertiesEntity properties = db.collection(COLLECTION_NAME).getProperties().get(); assertThat(properties.getNumberOfShards(), is(2)); assertThat(properties.getShardKeys().size(), is(1)); db.collection(COLLECTION_NAME).drop().get(); } @Test public void createCollectionWithNumberOfShardsAndShardKeys() throws InterruptedException, ExecutionException { assumeTrue(isCluster()); final CollectionEntity result = db.createCollection(COLLECTION_NAME, new CollectionCreateOptions().numberOfShards(2).shardKeys("a", "b")).get(); assertThat(result, is(notNullValue())); assertThat(result.getId(), is(notNullValue())); final CollectionPropertiesEntity properties = db.collection(COLLECTION_NAME).getProperties().get(); assertThat(properties.getNumberOfShards(), is(2)); assertThat(properties.getShardKeys().size(), is(2)); db.collection(COLLECTION_NAME).drop().get(); } @Test public void deleteCollection() throws InterruptedException, ExecutionException { db.createCollection(COLLECTION_NAME, null).get(); db.collection(COLLECTION_NAME).drop().get(); try { db.collection(COLLECTION_NAME).getInfo().get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); } } @Test public void deleteSystemCollection() throws InterruptedException, ExecutionException { final String name = "_system_test"; db.createCollection(name, new CollectionCreateOptions().isSystem(true)).get(); db.collection(name).drop(true).get(); try { db.collection(name).getInfo().get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); } } @Test public void deleteSystemCollectionFail() throws InterruptedException, ExecutionException { final String name = "_system_test"; db.createCollection(name, new CollectionCreateOptions().isSystem(true)).get(); try { db.collection(name).drop().get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); } db.collection(name).drop(true).get(); try { db.collection(name).getInfo().get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); } } @Test public void getIndex() throws InterruptedException, ExecutionException { db.createCollection(COLLECTION_NAME, null).get(); final Collection<String> fields = new ArrayList<>(); fields.add("a"); final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); db.getIndex(createResult.getId()) .whenComplete((readResult, ex) -> { assertThat(readResult.getId(), is(createResult.getId())); assertThat(readResult.getType(), is(createResult.getType())); }) .get(); db.collection(COLLECTION_NAME).drop().get(); } @Test public void deleteIndex() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); final Collection<String> fields = new ArrayList<>(); fields.add("a"); final IndexEntity createResult = db.collection(COLLECTION_NAME).ensureHashIndex(fields, null).get(); db.deleteIndex(createResult.getId()) .whenComplete((id, ex) -> { assertThat(id, is(createResult.getId())); try { db.getIndex(id).get(); fail(); } catch (InterruptedException e) { fail(); } catch (ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); } }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void getCollections() throws InterruptedException, ExecutionException { try { final Collection<CollectionEntity> systemCollections = db.getCollections(null).get(); db.createCollection(COLLECTION_NAME + "1", null).get(); db.createCollection(COLLECTION_NAME + "2", null).get(); db.getCollections(null) .whenComplete((collections, ex) -> { assertThat(collections.size(), is(2 + systemCollections.size())); assertThat(collections, is(notNullValue())); }) .get(); } finally { db.collection(COLLECTION_NAME + "1").drop().get(); db.collection(COLLECTION_NAME + "2").drop().get(); } } @Test public void getCollectionsExcludeSystem() throws InterruptedException, ExecutionException { try { final CollectionsReadOptions options = new CollectionsReadOptions().excludeSystem(true); final Collection<CollectionEntity> systemCollections = db.getCollections(options).get(); assertThat(systemCollections.size(), is(0)); db.createCollection(COLLECTION_NAME + "1", null).get(); db.createCollection(COLLECTION_NAME + "2", null).get(); db.getCollections(options) .whenComplete((collections, ex) -> { assertThat(collections.size(), is(2)); assertThat(collections, is(notNullValue())); }) .get(); } finally { db.collection(COLLECTION_NAME + "1").drop().get(); db.collection(COLLECTION_NAME + "2").drop().get(); } } @Test public void grantAccess() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234", null).get(); db.grantAccess("user1").get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test public void grantAccessRW() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234", null).get(); db.grantAccess("user1", Permissions.RW).get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test public void grantAccessRO() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234", null).get(); db.grantAccess("user1", Permissions.RO).get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test public void grantAccessNONE() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234", null).get(); db.grantAccess("user1", Permissions.NONE).get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test(expected = ExecutionException.class) public void grantAccessUserNotFound() throws InterruptedException, ExecutionException { db.grantAccess("user1", Permissions.RW).get(); } @Test public void revokeAccess() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234", null).get(); db.revokeAccess("user1").get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test(expected = ExecutionException.class) public void revokeAccessUserNotFound() throws InterruptedException, ExecutionException { db.revokeAccess("user1").get(); } @Test public void resetAccess() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234", null).get(); db.resetAccess("user1").get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test(expected = ExecutionException.class) public void resetAccessUserNotFound() throws InterruptedException, ExecutionException { db.resetAccess("user1").get(); } @Test public void grantDefaultCollectionAccess() throws InterruptedException, ExecutionException { try { arangoDB.createUser("user1", "1234").get(); db.grantDefaultCollectionAccess("user1", Permissions.RW).get(); } finally { arangoDB.deleteUser("user1").get(); } } @Test public void getPermissions() throws InterruptedException, ExecutionException { assertThat(Permissions.RW, is(db.getPermissions("root").get())); } @Test public void query() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } db.query("for i in db_test return i._id", null, null, String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); for (int i = 0; i < 10; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); } }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryForEach() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } db.query("for i in db_test return i._id", null, null, String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); final AtomicInteger i = new AtomicInteger(0); cursor.forEachRemaining(e -> i.incrementAndGet()); assertThat(i.get(), is(10)); }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryStream() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } db.query("for i in db_test return i._id", null, null, String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); final AtomicInteger i = new AtomicInteger(0); cursor.forEachRemaining(e -> i.incrementAndGet()); assertThat(i.get(), is(10)); }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryWithTimeout() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 6)); try { db.query("RETURN SLEEP(1)", null, new AqlQueryOptions().maxRuntime(0.1), String.class).get().next(); fail(); } catch (ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); assertThat(((ArangoDBException) e.getCause()).getResponseCode(), is(410)); } } @Test public void queryWithCount() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } db.query("for i in db_test Limit 6 return i._id", null, new AqlQueryOptions().count(true), String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); for (int i = 0; i < 6; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); } assertThat(cursor.getCount(), is(6)); }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryWithLimitAndFullCount() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } db.query("for i in db_test Limit 5 return i._id", null, new AqlQueryOptions().fullCount(true), String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); for (int i = 0; i < 5; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); } assertThat(cursor.getStats(), is(notNullValue())); assertThat(cursor.getStats().getFullCount(), is(10L)); }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryWithBatchSize() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } final ArangoCursorAsync<String> cursor = db.query("for i in db_test return i._id", null, new AqlQueryOptions().batchSize(5).count(true), String.class).get(); assertThat(cursor, is(notNullValue())); for (int i = 0; i < 10; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); } } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryStreamWithBatchSize() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } final ArangoCursorAsync<String> cursor = db.query("for i in db_test return i._id", null, new AqlQueryOptions().batchSize(5).count(true), String.class).get(); assertThat(cursor, is(notNullValue())); final AtomicInteger i = new AtomicInteger(0); cursor.streamRemaining().forEach(e -> i.incrementAndGet()); assertThat(i.get(), is(10)); } finally { db.collection(COLLECTION_NAME).drop().get(); } } /** * ignored. takes to long */ @Test @Ignore public void queryWithTTL() throws InterruptedException, ExecutionException { // set TTL to 1 seconds and get the second batch after 2 seconds! final int ttl = 1; final int wait = 2; try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } final ArangoCursorAsync<String> cursor = db.query("for i in db_test return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), String.class).get(); assertThat(cursor, is(notNullValue())); for (int i = 0; i < 10; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); if (i == 1) { Thread.sleep(wait * 1000); } } fail(); } catch (final ArangoDBException ex) { assertThat(ex.getResponseCode(), is(404)); assertThat(ex.getErrorNum(), is(1600)); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void changeQueryCache() throws InterruptedException, ExecutionException { try { QueryCachePropertiesEntity properties = db.getQueryCacheProperties().get(); assertThat(properties, is(notNullValue())); assertThat(properties.getMode(), is(CacheMode.off)); assertThat(properties.getMaxResults(), greaterThan(0L)); properties.setMode(CacheMode.on); properties = db.setQueryCacheProperties(properties).get(); assertThat(properties, is(notNullValue())); assertThat(properties.getMode(), is(CacheMode.on)); properties = db.getQueryCacheProperties().get(); assertThat(properties.getMode(), is(CacheMode.on)); } finally { final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); properties.setMode(CacheMode.off); db.setQueryCacheProperties(properties).get(); } } @Test public void queryWithCache() throws InterruptedException, ExecutionException { assumeTrue(isSingleServer()); try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); properties.setMode(CacheMode.on); db.setQueryCacheProperties(properties).get(); final ArangoCursorAsync<String> cursor = db .query("FOR t IN db_test FILTER t.age >= 10 SORT t.age RETURN t._id", null, new AqlQueryOptions().cache(true), String.class) .get(); assertThat(cursor, is(notNullValue())); assertThat(cursor.isCached(), is(false)); final ArangoCursorAsync<String> cachedCursor = db .query("FOR t IN db_test FILTER t.age >= 10 SORT t.age RETURN t._id", null, new AqlQueryOptions().cache(true), String.class) .get(); assertThat(cachedCursor, is(notNullValue())); assertThat(cachedCursor.isCached(), is(true)); } finally { db.collection(COLLECTION_NAME).drop().get(); final QueryCachePropertiesEntity properties = new QueryCachePropertiesEntity(); properties.setMode(CacheMode.off); db.setQueryCacheProperties(properties).get(); } } @Test public void queryCursor() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); final int numbDocs = 10; for (int i = 0; i < numbDocs; i++) { db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null).get(); } final int batchSize = 5; final ArangoCursorAsync<String> cursor = db.query("for i in db_test return i._id", null, new AqlQueryOptions().batchSize(batchSize).count(true), String.class).get(); assertThat(cursor, is(notNullValue())); assertThat(cursor.getCount(), is(numbDocs)); final ArangoCursorAsync<String> cursor2 = db.cursor(cursor.getId(), String.class).get(); assertThat(cursor2, is(notNullValue())); assertThat(cursor2.getCount(), is(numbDocs)); assertThat(cursor2.hasNext(), is(true)); for (int i = 0; i < batchSize; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); } } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void changeQueryTrackingProperties() throws InterruptedException, ExecutionException { try { QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties().get(); assertThat(properties, is(notNullValue())); assertThat(properties.getEnabled(), is(true)); assertThat(properties.getTrackSlowQueries(), is(true)); assertThat(properties.getMaxQueryStringLength(), greaterThan(0L)); assertThat(properties.getMaxSlowQueries(), greaterThan(0L)); assertThat(properties.getSlowQueryThreshold(), greaterThan(0L)); properties.setEnabled(false); properties = db.setQueryTrackingProperties(properties).get(); assertThat(properties, is(notNullValue())); assertThat(properties.getEnabled(), is(false)); properties = db.getQueryTrackingProperties().get(); assertThat(properties.getEnabled(), is(false)); } finally { final QueryTrackingPropertiesEntity properties = new QueryTrackingPropertiesEntity(); properties.setEnabled(true); db.setQueryTrackingProperties(properties).get(); } } @Test public void queryWithBindVars() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { final BaseDocument baseDocument = new BaseDocument(); baseDocument.addAttribute("age", 20 + i); db.collection(COLLECTION_NAME).insertDocument(baseDocument, null).get(); } final Map<String, Object> bindVars = new HashMap<>(); bindVars.put("@coll", COLLECTION_NAME); bindVars.put("age", 25); db.query("FOR t IN @@coll FILTER t.age >= @age SORT t.age RETURN t._id", bindVars, null, String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); for (int i = 0; i < 5; i++, cursor.next()) { assertThat(cursor.hasNext(), is(true)); } }) .get(); } finally { db.collection(COLLECTION_NAME).drop().get(); } } @Test public void queryWithWarning() throws InterruptedException, ExecutionException { arangoDB.db().query("return 1/0", null, null, String.class) .whenComplete((cursor, ex) -> { assertThat(cursor, is(notNullValue())); assertThat(cursor.getWarnings(), is(notNullValue())); assertThat(cursor.getWarnings(), is(not(empty()))); }) .get(); } @Test public void queryClose() throws IOException, InterruptedException, ExecutionException { final ArangoCursorAsync<String> cursor = arangoDB.db() .query("for i in 1..2 return i", null, new AqlQueryOptions().batchSize(1), String.class).get(); cursor.close(); int count = 0; try { for (; cursor.hasNext(); cursor.next(), count++) { } fail(); } catch (final ArangoDBException e) { assertThat(count, is(1)); } } @Test public void explainQuery() throws InterruptedException, ExecutionException { arangoDB.db().explainQuery("for i in 1..1 return i", null, null) .whenComplete((explain, ex) -> { assertThat(explain, is(notNullValue())); assertThat(explain.getPlan(), is(notNullValue())); assertThat(explain.getPlans(), is(nullValue())); final ExecutionPlan plan = explain.getPlan(); assertThat(plan.getCollections().size(), is(0)); assertThat(plan.getEstimatedCost(), greaterThan(0)); assertThat(plan.getEstimatedNrItems(), greaterThan(0)); assertThat(plan.getVariables().size(), is(2)); assertThat(plan.getNodes().size(), is(greaterThan(0))); }) .get(); } @Test public void parseQuery() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); arangoDB.db().parseQuery("for i in _apps return i") .whenComplete((parse, ex) -> { assertThat(parse, is(notNullValue())); assertThat(parse.getBindVars(), is(empty())); assertThat(parse.getCollections().size(), is(1)); assertThat(parse.getCollections().iterator().next(), is("_apps")); assertThat(parse.getAst().size(), is(1)); final AstNode root = parse.getAst().iterator().next(); assertThat(root.getType(), is("root")); assertThat(root.getName(), is(nullValue())); assertThat(root.getSubNodes(), is(notNullValue())); assertThat(root.getSubNodes().size(), is(2)); final Iterator<AstNode> iterator = root.getSubNodes().iterator(); final AstNode for_ = iterator.next(); assertThat(for_.getType(), is("for")); assertThat(for_.getSubNodes(), is(notNullValue())); assertThat(for_.getSubNodes().size(), is(3)); final Iterator<AstNode> iterator2 = for_.getSubNodes().iterator(); final AstNode first = iterator2.next(); assertThat(first.getType(), is("variable")); assertThat(first.getName(), is("i")); final AstNode second = iterator2.next(); assertThat(second.getType(), is("collection")); assertThat(second.getName(), is("_apps")); final AstNode return_ = iterator.next(); assertThat(return_.getType(), is("return")); assertThat(return_.getSubNodes(), is(notNullValue())); assertThat(return_.getSubNodes().size(), is(1)); assertThat(return_.getSubNodes().iterator().next().getType(), is("reference")); assertThat(return_.getSubNodes().iterator().next().getName(), is("i")); }) .get(); } @Test @Ignore public void getAndClearSlowQueries() throws InterruptedException, ExecutionException { final QueryTrackingPropertiesEntity properties = db.getQueryTrackingProperties().get(); final Long slowQueryThreshold = properties.getSlowQueryThreshold(); try { properties.setSlowQueryThreshold(1L); db.setQueryTrackingProperties(properties); db.query("return sleep(1.1)", null, null, Void.class); final Collection<QueryEntity> slowQueries = db.getSlowQueries().get(); assertThat(slowQueries, is(notNullValue())); assertThat(slowQueries.size(), is(1)); final QueryEntity queryEntity = slowQueries.iterator().next(); assertThat(queryEntity.getQuery(), is("return sleep(1.1)")); db.clearSlowQueries().get(); assertThat(db.getSlowQueries().get().size(), is(0)); } finally { properties.setSlowQueryThreshold(slowQueryThreshold); db.setQueryTrackingProperties(properties); } } @Test public void createGetDeleteAqlFunction() throws InterruptedException, ExecutionException { final Collection<AqlFunctionEntity> aqlFunctionsInitial = db.getAqlFunctions(null).get(); assertThat(aqlFunctionsInitial, is(empty())); try { db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit", "function (celsius) { return celsius * 1.8 + 32; }", null).get(); final Collection<AqlFunctionEntity> aqlFunctions = db.getAqlFunctions(null).get(); assertThat(aqlFunctions.size(), is(greaterThan(aqlFunctionsInitial.size()))); } finally { final Integer deleteCount = db.deleteAqlFunction("myfunctions::temperature::celsiustofahrenheit", null) .get(); // compatibility with ArangoDB < 3.4 if (isAtLeastVersion(3, 4)) { assertThat(deleteCount, is(1)); } else { assertThat(deleteCount, is(nullValue())); } final Collection<AqlFunctionEntity> aqlFunctions = db.getAqlFunctions(null).get(); assertThat(aqlFunctions.size(), is(aqlFunctionsInitial.size())); } } @Test public void createGetDeleteAqlFunctionWithNamespace() throws InterruptedException, ExecutionException { final Collection<AqlFunctionEntity> aqlFunctionsInitial = db.getAqlFunctions(null).get(); assertThat(aqlFunctionsInitial, is(empty())); try { db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit1", "function (celsius) { return celsius * 1.8 + 32; }", null).get(); db.createAqlFunction("myfunctions::temperature::celsiustofahrenheit2", "function (celsius) { return celsius * 1.8 + 32; }", null).get(); } finally { db.deleteAqlFunction("myfunctions::temperature", new AqlFunctionDeleteOptions().group(true)).get(); final Collection<AqlFunctionEntity> aqlFunctions = db.getAqlFunctions(null).get(); assertThat(aqlFunctions.size(), is(aqlFunctionsInitial.size())); } } @Test public void createGraph() throws InterruptedException, ExecutionException { try { db.createGraph(GRAPH_NAME, null, null) .whenComplete((result, ex) -> { assertThat(result, is(notNullValue())); assertThat(result.getName(), is(GRAPH_NAME)); }) .get(); } finally { db.graph(GRAPH_NAME).drop().get(); } } @Test public void getGraphs() throws InterruptedException, ExecutionException { try { db.createGraph(GRAPH_NAME, null, null).get(); db.getGraphs() .whenComplete((graphs, ex) -> { assertThat(graphs, is(notNullValue())); assertThat(graphs.size(), is(1)); }) .get(); } finally { db.graph(GRAPH_NAME).drop().get(); } } @Test public void transactionString() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params("test"); db.transaction("function (params) {return params;}", String.class, options) .whenComplete((result, ex) -> assertThat(result, is("test"))) .get(); } @Test public void transactionNumber() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params(5); db.transaction("function (params) {return params;}", Integer.class, options) .whenComplete((result, ex) -> assertThat(result, is(5))) .get(); } @Test public void transactionVPack() throws VPackException, InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); db.transaction("function (params) {return params;}", VPackSlice.class, options) .whenComplete((result, ex) -> { assertThat(result.isString(), is(true)); assertThat(result.getAsString(), is("test")); }) .get(); } @Test public void transactionEmpty() throws InterruptedException, ExecutionException { db.transaction("function () {}", null, null).get(); } @Test public void transactionallowImplicit() throws InterruptedException, ExecutionException { try { db.createCollection("someCollection", null).get(); db.createCollection("someOtherCollection", null).get(); final String action = "function (params) {" + "var db = require('internal').db;" + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()[0]};" + "}"; final TransactionOptions options = new TransactionOptions().readCollections("someCollection"); db.transaction(action, VPackSlice.class, options).get(); try { options.allowImplicit(false); db.transaction(action, VPackSlice.class, options).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); } } finally { db.collection("someCollection").drop().get(); db.collection("someOtherCollection").drop().get(); } } @Test public void transactionPojoReturn() throws ExecutionException, InterruptedException { final String action = "function() { return {'value':'hello world'}; }"; db.transaction(action, TransactionTestEntity.class, new TransactionOptions()) .whenComplete((res, ex) -> { assertThat(res, is(notNullValue())); assertThat(res.value, is("hello world")); }) .get(); } @Test public void getInfo() throws InterruptedException, ExecutionException { final CompletableFuture<DatabaseEntity> f = db.getInfo(); assertThat(f, is(notNullValue())); f.whenComplete((info, ex) -> { assertThat(info, is(notNullValue())); assertThat(info.getId(), is(notNullValue())); assertThat(info.getName(), is(TEST_DB)); assertThat(info.getPath(), is(notNullValue())); assertThat(info.getIsSystem(), is(false)); try { if (isAtLeastVersion(3, 6) && isCluster()) { assertThat(info.getSharding(), notNullValue()); assertThat(info.getWriteConcern(), notNullValue()); assertThat(info.getReplicationFactor(), notNullValue()); } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); fail(); } }); f.get(); } @Test public void executeTraversal() throws InterruptedException, ExecutionException { try { db.createCollection("person", null).get(); db.createCollection("knows", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); for (final String e : new String[]{"Alice", "Bob", "Charlie", "Dave", "Eve"}) { final BaseDocument doc = new BaseDocument(); doc.setKey(e); db.collection("person").insertDocument(doc, null).get(); } for (final String[] e : new String[][]{new String[]{"Alice", "Bob"}, new String[]{"Bob", "Charlie"}, new String[]{"Bob", "Dave"}, new String[]{"Eve", "Alice"}, new String[]{"Eve", "Bob"}}) { final BaseEdgeDocument edge = new BaseEdgeDocument(); edge.setKey(e[0] + "_knows_" + e[1]); edge.setFrom("person/" + e[0]); edge.setTo("person/" + e[1]); db.collection("knows").insertDocument(edge, null).get(); } final TraversalOptions options = new TraversalOptions().edgeCollection("knows").startVertex("person/Alice") .direction(Direction.outbound); db.executeTraversal(BaseDocument.class, BaseEdgeDocument.class, options) .whenComplete((traversal, ex) -> { assertThat(traversal, is(notNullValue())); final Collection<BaseDocument> vertices = traversal.getVertices(); assertThat(vertices, is(notNullValue())); assertThat(vertices.size(), is(4)); final Iterator<BaseDocument> verticesIterator = vertices.iterator(); final Collection<String> v = Arrays.asList("Alice", "Bob", "Charlie", "Dave"); for (; verticesIterator.hasNext(); ) { assertThat(v.contains(verticesIterator.next().getKey()), is(true)); } final Collection<PathEntity<BaseDocument, BaseEdgeDocument>> paths = traversal.getPaths(); assertThat(paths, is(notNullValue())); assertThat(paths.size(), is(4)); assertThat(paths.iterator().hasNext(), is(true)); final PathEntity<BaseDocument, BaseEdgeDocument> first = paths.iterator().next(); assertThat(first, is(notNullValue())); assertThat(first.getEdges().size(), is(0)); assertThat(first.getVertices().size(), is(1)); assertThat(first.getVertices().iterator().next().getKey(), is("Alice")); }) .get(); } finally { db.collection("person").drop().get(); db.collection("knows").drop().get(); } } @Test public void getDocument() throws InterruptedException, ExecutionException { String collectionName = COLLECTION_NAME + "getDocument"; db.createCollection(collectionName).get(); final BaseDocument value = new BaseDocument(); value.setKey("123"); db.collection(collectionName).insertDocument(value).get(); db.getDocument(collectionName + "/123", BaseDocument.class) .whenComplete((document, ex) -> { assertThat(document, is(notNullValue())); assertThat(document.getKey(), is("123")); }) .get(); db.collection(collectionName).drop().get(); } @Test public void shouldIncludeExceptionMessage() throws InterruptedException, ExecutionException { final String exceptionMessage = "My error context"; final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; try { db.transaction(action, VPackSlice.class, null).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause(), instanceOf(ArangoDBException.class)); ArangoDBException cause = ((ArangoDBException) e.getCause()); assertThat(cause.getErrorNum(), is(1650)); if (isAtLeastVersion(3, 4)) { assertThat(cause.getErrorMessage(), is(exceptionMessage)); } } } @Test(expected = ArangoDBException.class) public void getDocumentWrongId() throws InterruptedException, ExecutionException { db.getDocument("123", BaseDocument.class).get(); } @Test public void reloadRouting() throws InterruptedException, ExecutionException { db.reloadRouting().get(); } @SuppressWarnings({"WeakerAccess", "unused"}) protected static class TransactionTestEntity { private String value; public TransactionTestEntity() { super(); } } }