Skip to content

Commit

Permalink
add tests for basic connector functionality
Browse files Browse the repository at this point in the history
Added tests for connector API.

Closes #51
  • Loading branch information
ztarvos authored and Totktonada committed Nov 21, 2018
1 parent a96c8d9 commit d220ca2
Show file tree
Hide file tree
Showing 18 changed files with 1,434 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,3 +3,4 @@
out
target
build
testroot
4 changes: 2 additions & 2 deletions .travis.yml
Expand Up @@ -12,5 +12,5 @@ before_script:
- src/test/travis.pre.sh

script:
- mvn test
- sudo cat /var/log/tarantool/jdk-testing.log
- mvn verify
- cat testroot/jdk-testing.log
31 changes: 31 additions & 0 deletions README.md
Expand Up @@ -58,6 +58,37 @@ Remember that `TarantoolClient` adopts a
[fail-fast](https://en.wikipedia.org/wiki/Fail-fast) policy
when a client is not connected.

The `TarantoolClient` will stop functioning if your implementation of a socket
channel provider raises an exception or returns a null. You will need a new
instance of client to recover. Hence, you should only throw in case you have
met unrecoverable error.

Below is an example of `SocketChannelProvider` implementation that handles short
tarantool restarts.

```java
SocketChannelProvider socketChannelProvider = new SocketChannelProvider() {
@Override
public SocketChannel get(int retryNumber, Throwable lastError) {
long deadline = System.currentTimeMillis() + RESTART_TIMEOUT;
while (!Thread.currentThread().isInterrupted()) {
try {
return SocketChannel.open(new InetSocketAddress("localhost", 3301));
} catch (IOException e) {
if (deadline < System.currentTimeMillis())
throw new RuntimeException(e);
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
}
throw new RuntimeException(new TimeoutException("Connect timed out."));
}
};
```

4. Create a client.

```java
Expand Down
19 changes: 19 additions & 0 deletions pom.xml
Expand Up @@ -50,6 +50,19 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.0</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand All @@ -66,6 +79,12 @@
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.23</version>
<scope>test</scope>
</dependency>
</dependencies>

<parent>
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/tarantool/TarantoolClientImpl.java
Expand Up @@ -503,7 +503,7 @@ public List exec(Code code, Object... args) {

@Override
public void close() {
throw new IllegalStateException("You should close TarantoolClient to make this");
throw new IllegalStateException("You should close TarantoolClient instead.");
}
}

Expand All @@ -525,7 +525,7 @@ public Long exec(Code code, Object... args) {

@Override
public void close() {
throw new IllegalStateException("You should close TarantoolClient to make this");
throw new IllegalStateException("You should close TarantoolClient instead.");
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/test/.tarantoolctl
@@ -0,0 +1,15 @@
-- Options for tarantoolctl.

local workdir = os.getenv('TEST_WORKDIR')
default_cfg = {
pid_file = workdir,
wal_dir = workdir,
memtx_dir = workdir,
vinyl_dir = workdir,
log = workdir,
background = true,
}

instance_dir = workdir

-- vim: set ft=lua :
187 changes: 187 additions & 0 deletions src/test/java/org/tarantool/AbstractTarantoolConnectorIT.java
@@ -0,0 +1,187 @@
package org.tarantool;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* Abstract test. Provides environment control and frequently used functions.
*/
public abstract class AbstractTarantoolConnectorIT {
protected static final String host = System.getProperty("tntHost", "localhost");
protected static final int port = Integer.parseInt(System.getProperty("tntPort", "3301"));
protected static final int consolePort = Integer.parseInt(System.getProperty("tntConsolePort", "3313"));
protected static final String username = System.getProperty("tntUser", "test_admin");
protected static final String password = System.getProperty("tntPass", "4pWBZmLEgkmKK5WP");

protected static final int TIMEOUT = 500;
protected static final int RESTART_TIMEOUT = 2000;

protected static final SocketChannelProvider socketChannelProvider = new TestSocketChannelProvider(host, port,
RESTART_TIMEOUT);

protected static TarantoolControl control;
protected static TarantoolConsole console;

protected static final String SPACE_NAME = "basic_test";
protected static final String MULTIPART_SPACE_NAME = "multipart_test";

protected static int SPACE_ID;
protected static int MULTI_PART_SPACE_ID;

protected static int PK_INDEX_ID;
protected static int MPK_INDEX_ID;
protected static int VIDX_INDEX_ID;

private static final String[] setupScript = new String[] {
"box.schema.space.create('basic_test', { format = " +
"{{name = 'id', type = 'integer'}," +
" {name = 'val', type = 'string'} } })",

"box.space.basic_test:create_index('pk', { type = 'TREE', parts = {'id'} } )",
"box.space.basic_test:create_index('vidx', { type = 'TREE', unique = false, parts = {'val'} } )",

"box.space.basic_test:replace{1, 'one'}",
"box.space.basic_test:replace{2, 'two'}",
"box.space.basic_test:replace{3, 'three'}",

"box.schema.space.create('multipart_test', { format = " +
"{{name = 'id1', type = 'integer'}," +
" {name = 'id2', type = 'string'}," +
" {name = 'val1', type = 'string'} } })",

"box.space.multipart_test:create_index('pk', { type = 'TREE', parts = {'id1', 'id2'} })",
"box.space.multipart_test:create_index('vidx', { type = 'TREE', unique = false, parts = {'val1'} })",

"box.space.multipart_test:replace{1, 'one', 'o n e'}",
"box.space.multipart_test:replace{2, 'two', 't w o'}",
"box.space.multipart_test:replace{3, 'three', 't h r e e'}",

"function echo(...) return ... end"
};

private static final String[] cleanScript = new String[] {
"box.space.basic_test and box.space.basic_test:drop()",
"box.space.multipart_test and box.space.multipart_test:drop()"
};

@BeforeAll
public static void setupEnv() {
control = new TarantoolControl();
control.start("jdk-testing");

console = openConsole();

executeLua(cleanScript);
executeLua(setupScript);

SPACE_ID = console.eval("box.space.basic_test.id");
PK_INDEX_ID = console.eval("box.space.basic_test.index.pk.id");
VIDX_INDEX_ID = console.eval("box.space.basic_test.index.vidx.id");

MULTI_PART_SPACE_ID = console.eval("box.space.multipart_test.id");
MPK_INDEX_ID = console.eval("box.space.multipart_test.index.pk.id");
}

@AfterAll
public static void cleanupEnv() {
executeLua(cleanScript);

console.close();
control.stop("jdk-testing");
}

private static void executeLua(String[] exprs) {
for (String expr : exprs) {
console.exec(expr);
}
}

protected void checkTupleResult(Object res, List tuple) {
assertNotNull(res);
assertTrue(List.class.isAssignableFrom(res.getClass()));
List list = (List)res;
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertTrue(List.class.isAssignableFrom(list.get(0).getClass()));
assertEquals(tuple, list.get(0));
}

protected TarantoolClient makeClient() {
TarantoolClientConfig config = new TarantoolClientConfig();
config.username = username;
config.password = password;
config.initTimeoutMillis = 1000;
config.sharedBufferSize = 128;

return new TarantoolClientImpl(socketChannelProvider, config);
}

protected static TarantoolConsole openConsole() {
return TarantoolConsole.open(host, consolePort);
}

protected static TarantoolConsole openConsole(String instance) {
return TarantoolConsole.open(control.tntCtlWorkDir, instance);
}

protected TarantoolConnection openConnection() {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(host, port));
} catch (IOException e) {
throw new RuntimeException("Test failed due to invalid environment.", e);
}
try {
return new TarantoolConnection(username, password, socket);
} catch (Exception e) {
try {
socket.close();
} catch (IOException ignored) {
// No-op.
}
throw new RuntimeException(e);
}
}

protected List<?> consoleSelect(String spaceName, Object key) {
StringBuilder sb = new StringBuilder("box.space.");
sb.append(spaceName);
sb.append(":select{");
if (List.class.isAssignableFrom(key.getClass())) {
List parts = (List)key;
for (int i = 0; i < parts.size(); i++) {
if (i != 0)
sb.append(", ");
Object k = parts.get(i);
if (k.getClass().isAssignableFrom(String.class)) {
sb.append('\'');
sb.append(k);
sb.append('\'');
} else {
sb.append(k);
}
}
} else {
sb.append(key);
}
sb.append("}");
return console.eval(sb.toString());
}

protected void stopTarantool(String instance) {
control.stop(instance);
}

protected void startTarantool(String instance) {
control.start(instance);
}
}

0 comments on commit d220ca2

Please sign in to comment.