package com.tinkerpop.rexster.rexpro;
import com.tinkerpop.rexster.Tokens;
import com.tinkerpop.rexster.client.RexsterClient;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public abstract class AbstractRexsterClientIntegrationTest extends AbstractRexProIntegrationTest {
/**
* Indicates that the serializer supports primitive
* map key types, not just strings
* @return
*/
public abstract boolean supportsPrimitiveKeys();
@Test
public void shouldOpenAndCloseLotsOfClients() throws Exception {
final int numberOfClientsToOpen = 100;
for (int ix = 0; ix < numberOfClientsToOpen; ix++) {
final RexsterClient client = getClient();
// have to send a script to open a connection
assertEquals(2l, client.execute("1+1").get(0));
client.close();
}
}
@Test
public void shouldOpenAndCloseLotsOfClientsInManyThreads() throws Exception {
final int numberOfClientsToOpen = 1000;
final AtomicBoolean fail = new AtomicBoolean(false);
final CountDownLatch latch = new CountDownLatch(numberOfClientsToOpen);
for (int ix = 0; ix < numberOfClientsToOpen; ix++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
final RexsterClient client = getClient();
// have to send a script to open a connection
client.execute("Thread.sleep(50);1+1");
client.close();
} catch (Exception ex) {
fail.set(true);
} finally {
latch.countDown();
}
}
}).run();
}
latch.await();
assertFalse(fail.get());
}
@Test
public void closeStopsAdditionalSendingOfMessages() throws Exception {
final RexsterClient client = getClient();
client.close();
try {
client.execute("1+1");
fail("Should have thrown an exception because the client is closed");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("The close() method was called on the client and no more messages can be sent"));
}
}
@Test
public void shouldCloseWhileOtherClientIsOpen() throws Exception {
final RexsterClient client1 = getClient();
final RexsterClient client2 = getClient();
final RexsterClient client3 = getClient();
final AtomicBoolean fail2 = new AtomicBoolean(false);
final AtomicBoolean fail3 = new AtomicBoolean(false);
final AtomicBoolean result2 = new AtomicBoolean(false);
final AtomicBoolean result3 = new AtomicBoolean(false);
// send client 2 into a long run operation
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
result2.set((Boolean) client2.execute("Thread.sleep(5000);true").get(0));
} catch (Exception ex) {
fail2.set(true);
ex.printStackTrace();
}
}
});
// make client 3 do a bunch of stuff that runs at least as long at client 2
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int ix = 0; ix < 100; ix++) {
result3.set((Boolean) client3.execute("Thread.sleep(50);true").get(0));
if (!result3.get())
break;
}
} catch (Exception ex) {
fail3.set(true);
ex.printStackTrace();
}
}
});
// close client1 while client 2 + 3 are still busy
t3.run();
t2.run();
client1.close();
// wait for thread doing client 2 work to complete
t2.join();
t3.join();
assertTrue(result2.get());
assertTrue(result3.get());
assertFalse(fail2.get());
assertFalse(fail3.get());
client3.close();
// client 2 should still be valid
final List<Map<String, Object>> vertexResults = client2.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1)", null);
assertEquals(1, vertexResults.size());
client2.close();
}
@Test
public void executeExercise() throws Exception {
final RexsterClient client = getClient();
final List<Object> nullResults = client.execute("null");
assertEquals(1, nullResults.size());
final Object nullResult = nullResults.get(0);
assertEquals(null, nullResult);
final List<Map<String, Object>> mapResults = client.execute("[val:1+1]");
assertEquals(1, mapResults.size());
final Map<String, Object> mapResult = mapResults.get(0);
assertEquals("2", mapResult.get("val").toString());
final List<Long> intResults = client.execute("1+1", null);
assertEquals(1, intResults.size());
final Long intResult = intResults.get(0);
assertEquals("2", intResult.toString());
final List<Map<String, Object>> vertexResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1)", null);
assertEquals(1, vertexResults.size());
final Map<String, Object> vertexResult = vertexResults.get(0);
assertEquals("vertex", vertexResult.get("_type").toString());
assertEquals("1", vertexResult.get("_id").toString());
final Map<String, Object> vertexProperties = (Map<String, Object>) vertexResult.get("_properties");
assertEquals("marko", vertexProperties.get("name"));
assertEquals(29L, vertexProperties.get("age"));
client.close();
}
@Test
public void executeMapValueConversion() throws Exception {
final RexsterClient client = getClient();
// all whole numerics convert to long
// all float go to double
final List<Map<String, Object>> mapResultsObject = client.execute("[n:1+1,b:true,f:1234.56f,s:'string',a:[1,2,3],m:[one:1]]");
assertEquals(1, mapResultsObject.size());
final Map<String, Object> mapResultObject = mapResultsObject.get(0);
assertEquals(2L, mapResultObject.get("n"));
assertEquals(true, mapResultObject.get("b"));
assertEquals(1234.56d, (Double) mapResultObject.get("f"), 0.001d);
assertEquals("string", mapResultObject.get("s"));
assertEquals(3L, ((ArrayList) mapResultObject.get("a")).size());
assertEquals(1L, ((Map) mapResultObject.get("m")).get("one"));
client.close();
}
@Test
public void executeReturnGraphElementsValueConversion() throws Exception {
final RexsterClient client = getClient();
final List<Map<String, Object>> vertexResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1)");
assertEquals(1, vertexResults.size());
final Map<String, Object> vertexResult = vertexResults.get(0);
assertEquals("vertex", vertexResult.get("_type"));
assertEquals("1", vertexResult.get("_id"));
final Map vertexProperties = (Map) vertexResult.get("_properties");
assertEquals("marko", vertexProperties.get("name"));
assertEquals(29L, vertexProperties.get("age"));
client.close();
}
@Test
public void executeReturnGraphElementsAsMapValueConversion() throws Exception {
final RexsterClient client = getClient();
final List<Map<String, Object>> vertexResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1).map");
assertEquals(1, vertexResults.size());
final Map<String, Object> vertexResult = vertexResults.get(0);
assertEquals("marko", vertexResult.get("name"));
assertEquals(29L, vertexResult.get("age"));
client.close();
}
@Test
public void executeReturnGraphElementsAsSelectValueConversion() throws Exception {
final RexsterClient client = getClient();
final List<Map<String,Object>> vertexResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1).as('a').out.as('b').select{it.name}{it.age}");
assertEquals(3, vertexResults.size());
assertEquals("marko", vertexResults.get(0).get("a"));
assertEquals(27L, vertexResults.get(0).get("b"));
assertEquals("marko", vertexResults.get(1).get("a"));
assertEquals(32L, vertexResults.get(1).get("b"));
assertEquals("marko", vertexResults.get(2).get("a"));
Assert.assertNull(vertexResults.get(2).get("b"));
client.close();
}
/*
@Test
public void executeTransactionWithAutoCommitInSessionlessMode() throws Exception {
final Configuration conf = new BaseConfiguration();
conf.setProperty(RexsterClientTokens.CONFIG_GRAPH_NAME, "neo4jsample");
final RexsterClient rexsterClientToNeo4j = RexsterClientFactory.open(conf);
final List<Object> results = rexsterClientToNeo4j.execute("g.addVertex([name:n])",
new HashMap<String,Object>() {{
put("n","vadas");
}});
Assert.assertEquals(1, results.size());
final List<Map<String,Object>> txResults = rexsterClientToNeo4j.execute("g.V");
Assert.assertEquals(1, txResults.size());
final Map<String, Object> vertexResult = txResults.get(0);
Assert.assertEquals("vadas", ((Map<String,Object>)vertexResult.get("_properties")).get("name"));
rexsterClientToNeo4j.close();
}
*/
@Test
public void executeAndReturnMapWithGraphElementKey() throws Exception {
// maps of graph element keys get serialized to nested maps like:
// {elementId : { _element : 1, _contents : { standard vertex/edge serialization } }
final RexsterClient client = getClient();
final List<Map<String, Map<String,Object>>> vertexResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.V.out.groupCount.cap");
assertEquals(1, vertexResults.size());
final Map<String, Map<String,Object>> r = vertexResults.get(0);
assertEquals(3L, r.get("3").get(Tokens._VALUE));
assertEquals(1L, r.get("2").get(Tokens._VALUE));
assertEquals(1L, r.get("5").get(Tokens._VALUE));
assertEquals(1L, r.get("4").get(Tokens._VALUE));
client.close();
}
@Test
public void executeAndReturnMapWithPrimitiveKey() throws Exception {
if (!supportsPrimitiveKeys()) return;
final RexsterClient client = getClient();
final List<Map<Integer, String>> vertexResults = client.execute("[1:'test']");
assertEquals(1, vertexResults.size());
final Map<Integer, String> r = vertexResults.get(0);
assertEquals("test", r.get(1L));
client.close();
}
@Test
public void executeAndReturnTree() throws Exception {
final RexsterClient client = getClient();
final List<Object> treeResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.V.out.tree.cap");
assertEquals(1, treeResults.size());
assertTrue(treeResults.get(0) instanceof Map);
final HashMap<String, Object> map = (HashMap<String, Object>) treeResults.get(0);
for(Map.Entry e : map.entrySet()) {
assertTrue(e.getValue() instanceof Map);
Map m = (Map) e.getValue();
assertTrue(m.containsKey(Tokens._KEY));
assertTrue(m.containsKey(Tokens._VALUE));
}
client.close();
}
@Test
public void executeAndReturnSelect() throws Exception {
final RexsterClient client = getClient();
final List<Object> selectResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1).out.name.as('x').select");
assertEquals(3, selectResults.size());
assertTrue(selectResults.get(0) instanceof Map);
final List<String> names = new ArrayList<String>(){{
add("vadas");
add("josh");
add("lop");
}};
for(Object e : selectResults) {
final Map<String,Object> m = (Map<String, Object>) e;
assertTrue(names.contains(m.get("x")));
}
client.close();
}
@Test
public void executeAndReturnTable() throws Exception {
final RexsterClient client = getClient();
final List<Object> tableResults = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1).out.name.as('x').table.cap.next()");
assertEquals(3, tableResults.size());
assertTrue(tableResults.get(0) instanceof Map);
final List<String> names = new ArrayList<String>(){{
add("vadas");
add("josh");
add("lop");
}};
for(Object e : tableResults) {
final Map<String,Object> m = (Map<String, Object>) e;
assertTrue(names.contains(m.get("x")));
}
client.close();
}
@Test
public void executeForProperties() throws Exception {
final RexsterClient client = getClient();
final List<Map> stuffs = client.execute("g=TinkerGraphFactory.createTinkerGraph();g.v(1).properties");
assertEquals(1, stuffs.size());
Map<String,Object> m = stuffs.get(0);
assertEquals("class com.tinkerpop.blueprints.impls.tg.TinkerVertex", m.get("class"));
assertEquals("1", m.get("id"));
List<String> k = (List<String>) m.get("propertyKeys");
assertEquals(2, k.size());
Collections.sort(k);
assertEquals("age", k.get(0));
assertEquals("name", k.get(1));
}
@Test
public void executeForTextWithBreaks() throws Exception {
final RexsterClient client = getClient();
// note that you have to escape the \r\n for it to be understood as a property value else the script engine
// assumes it is line breaks in the script itself.
final List<String> text = client.execute("g=new TinkerGraph();g.addVertex(['text':'''test1\\r\\ntest2\\r\\ntest3''']);g.v(0).text");
assertEquals(1, text.size());
assertEquals("test1\r\ntest2\r\ntest3", text.get(0));
}
/* this test fails on neo4j given inconsistencies in its blueprints implementation. a failing test
was added to blueprints here:
https://github.com/tinkerpop/blueprints/issues/363
public void executeTransactionWithNoAutoCommitInSessionlessMode() throws Exception {
final Configuration conf = new BaseConfiguration();
conf.setProperty(RexsterClientTokens.CONFIG_GRAPH_NAME, "orientdbsample");
conf.setProperty(RexsterClientTokens.CONFIG_TRANSACTION, false);
final RexsterClient rexsterClientToNeo4j = RexsterClientFactory.open(conf);
final List<Object> results = rexsterClientToNeo4j.execute("g.addVertex([name:n])",
new HashMap<String,Object>() {{
put("n","vadas");
}});
Assert.assertEquals(1, results.size());
final List<Object> txResults = rexsterClientToNeo4j.execute("g.V");
Assert.assertEquals(1, txResults.size());
Assert.assertNull(txResults.get(0));
}
*/
}