Skip to content

Commit 677907f

Browse files
ztarvosTotktonada
authored andcommitted
jdbc: fix NPE in update
Updated constants to be in sync with tarantool IPROTO. Added integration tests for the working JDBC functionality. Fixed travis script to use tarantool 2.0 which is required for SQL. Fixed failing user permission calls in tarantool initialization script. Closes #39 ---- Rebase fixes (Alexander Turenko): * Perform cleanup of the test directory once before all tests (move it from the TarantoolControl constructor). * Added starting of jdk-testing instance using TarantoolControl to JDBC tests. * Wait for the instance to be started / stopped in setupEnv() / cleanupEnv().
1 parent 6a77462 commit 677907f

10 files changed

+693
-28
lines changed

src/main/java/org/tarantool/Key.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ public enum Key implements Callable<Integer> {
1818
UPSERT_OPS(0x28),
1919
DATA(0x30), ERROR(0x31),
2020

21-
SQL_FIELD_NAME(0x29),
21+
SQL_FIELD_NAME(0),
2222
SQL_METADATA(0x32),
2323
SQL_TEXT(0x40),
2424
SQL_BIND(0x41),
2525
SQL_OPTIONS(0x42),
26-
SQL_INFO(0x43),
27-
SQL_ROW_COUNT(0x44);
26+
SQL_INFO(0x42),
27+
SQL_ROW_COUNT(0);
2828

2929
int id;
3030

src/test/java/org/tarantool/TarantoolControl.java

+69-21
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,46 @@ public class TarantoolControl {
2222
protected static final String tarantoolCtlConfig = new File("src/test/.tarantoolctl").getAbsolutePath();
2323
protected static final int RESTART_TIMEOUT = 2000;
2424

25+
static {
26+
try {
27+
setupWorkDirectory();
28+
} catch (IOException e) {
29+
throw new RuntimeException("Can't setup test root directory!", e);
30+
}
31+
}
32+
33+
protected static void setupWorkDirectory() throws IOException {
34+
try {
35+
rmdir(tntCtlWorkDir);
36+
} catch (IOException ignored) {
37+
/* No-op. */
38+
}
39+
40+
mkdir(tntCtlWorkDir);
41+
for (File c : new File(instanceDir).listFiles())
42+
if (c.getName().endsWith(".lua"))
43+
copyFile(c, tntCtlWorkDir);
44+
copyFile(tarantoolCtlConfig, tntCtlWorkDir);
45+
}
46+
2547
// Based on https://stackoverflow.com/a/779529
26-
private void rmdir(File f) throws IOException {
48+
private static void rmdir(File f) throws IOException {
2749
if (f.isDirectory()) {
2850
for (File c : f.listFiles())
2951
rmdir(c);
3052
}
3153
f.delete();
3254
}
3355

34-
private void rmdir(String f) throws IOException {
56+
private static void rmdir(String f) throws IOException {
3557
rmdir(new File(f));
3658
}
3759

38-
private void mkdir(File f) throws IOException {
60+
private static void mkdir(File f) throws IOException {
3961
f.mkdirs();
4062
}
4163

42-
private void mkdir(String f) throws IOException {
64+
private static void mkdir(String f) throws IOException {
4365
mkdir(new File(f));
4466
}
4567

@@ -79,23 +101,6 @@ private static String loadStream(InputStream s) throws IOException {
79101
return sb.toString();
80102
}
81103

82-
protected void setupWorkDirectory() throws IOException {
83-
rmdir(tntCtlWorkDir);
84-
mkdir(tntCtlWorkDir);
85-
for (File c : new File(instanceDir).listFiles())
86-
if (c.getName().endsWith(".lua"))
87-
copyFile(c, tntCtlWorkDir);
88-
copyFile(tarantoolCtlConfig, tntCtlWorkDir);
89-
}
90-
91-
TarantoolControl() {
92-
try {
93-
setupWorkDirectory();
94-
} catch (IOException e) {
95-
throw new RuntimeException(e);
96-
}
97-
}
98-
99104
/**
100105
* Control the given tarantool instance via tarantoolctl utility.
101106
*
@@ -163,11 +168,54 @@ public void run() {
163168
}
164169
}
165170

171+
/**
172+
* Wait until the instance will be started.
173+
*
174+
* Test connection using text console (TarantoolTcpConsole) to ensure the
175+
* instance was entirely started or fallback to binary port
176+
* (TarantoolLocalConsole) when the test console was not opened.
177+
*/
178+
public void waitStarted(String instanceName) {
179+
while (true) {
180+
try {
181+
openConsole(instanceName).close();
182+
return;
183+
} catch (Exception ignored) {
184+
/* No-op */
185+
}
186+
}
187+
}
188+
189+
/**
190+
* Wait until the instance will be stopped.
191+
*
192+
* Test connection using binary port (TarantoolLocalConsole) to ensure the
193+
* instance was entirely stopped.
194+
*/
195+
public void waitStopped(String instanceName) {
196+
while (true) {
197+
try {
198+
TarantoolConsole.open(tntCtlWorkDir, instanceName).close();
199+
} catch (Exception ignored) {
200+
return;
201+
}
202+
}
203+
}
204+
166205
public void start(String instanceName) {
167206
executeCommand("start", instanceName);
168207
}
169208

170209
public void stop(String instanceName) {
171210
executeCommand("stop", instanceName);
172211
}
212+
213+
/*
214+
* XXX: This function is planned to use text console (from ADMIN
215+
* environment variable) when it is availiable for the instance and
216+
* fallback to TarantoolLocalConsole.
217+
*/
218+
public TarantoolConsole openConsole(String instanceName) {
219+
return TarantoolConsole.open(tntCtlWorkDir, instanceName);
220+
}
173221
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
package org.tarantool.jdbc;
2+
3+
import org.junit.jupiter.api.AfterAll;
4+
import org.junit.jupiter.api.AfterEach;
5+
import org.junit.jupiter.api.BeforeAll;
6+
import org.junit.jupiter.api.BeforeEach;
7+
import org.tarantool.TarantoolConnection;
8+
9+
import java.io.IOException;
10+
import java.math.BigDecimal;
11+
import java.math.BigInteger;
12+
import java.net.InetSocketAddress;
13+
import java.net.Socket;
14+
import java.sql.Connection;
15+
import java.sql.Date;
16+
import java.sql.DriverManager;
17+
import java.sql.SQLException;
18+
import java.sql.Time;
19+
import java.sql.Timestamp;
20+
import java.util.Arrays;
21+
import java.util.Collections;
22+
import java.util.List;
23+
24+
import static org.junit.jupiter.api.Assertions.assertNotNull;
25+
26+
import org.tarantool.TarantoolControl;
27+
28+
//mvn -DtntHost=localhost -DtntPort=3301 -DtntUser=test -DtntPass=test verify
29+
public abstract class AbstractJdbcIT {
30+
private static final String host = System.getProperty("tntHost", "localhost");
31+
private static final Integer port = Integer.valueOf(System.getProperty("tntPort", "3301"));
32+
private static final String user = System.getProperty("tntUser", "test_admin");
33+
private static final String pass = System.getProperty("tntPass", "4pWBZmLEgkmKK5WP");
34+
private static String URL = String.format("tarantool://%s:%d?user=%s&password=%s", host, port, user, pass);
35+
36+
private static String[] initSql = new String[] {
37+
"DROP TABLE IF EXISTS test",
38+
"DROP TABLE IF EXISTS test_types",
39+
40+
"CREATE TABLE test(id INT PRIMARY KEY, val VARCHAR(100))",
41+
"INSERT INTO test VALUES (1, 'one'), (2, 'two'), (3, 'three')",
42+
43+
"CREATE TABLE test_types(" +
44+
"f1 INT PRIMARY KEY, " +
45+
"f2 CHAR(4), " +
46+
"f3 VARCHAR(100), " +
47+
"f4 LONGVARCHAR(100), " +
48+
"f5 NUMERIC, " +
49+
"f6 DECIMAL, " +
50+
"f7 BIT, " +
51+
"f8 TINYINT, " +
52+
"f9 SMALLINT, " +
53+
"f10 INTEGER, " +
54+
"f11 BIGINT," +
55+
"f12 REAL, " +
56+
"f13 FLOAT, " +
57+
"f14 BINARY(4), " +
58+
"f15 VARBINARY(128), " +
59+
"f16 LONGVARBINARY(2048), " +
60+
"f17 DATE, " +
61+
"f18 TIME, " +
62+
"f19 TIMESTAMP)",
63+
64+
"INSERT INTO test_types VALUES(" +
65+
"1," +
66+
"'abcd'," + //CHAR
67+
"'000000000000000000001'," + //VARCHAR
68+
"'0000000000000000000000000000000001'," + //LONGVARCHAR
69+
"100," + // NUMERIC
70+
"100.1," + // DECIMAL
71+
"1," + //BIT
72+
"7," + //TINYINT
73+
"1000," + //SMALLINT
74+
"100," + //INTEGER
75+
"100000000000000000," + //BIGINT
76+
"-100.2," + //REAL
77+
"100.3," + //FLOAT
78+
"X'01020304'," + //BINARY
79+
"X'0102030405'," +//VARBINARY
80+
"X'010203040506'," + //LONGVARBINARY
81+
"'1983-03-14'," + //DATE
82+
"'12:01:06'," + //TIME
83+
"129479994)" //TIMESTAMP
84+
};
85+
86+
private static String[] cleanSql = new String[] {
87+
"DROP TABLE IF EXISTS test",
88+
"DROP TABLE IF EXISTS test_types"
89+
};
90+
91+
static Object[] testRow = new Object[] {
92+
1,
93+
"abcd",
94+
"000000000000000000001",
95+
"0000000000000000000000000000000001",
96+
BigDecimal.valueOf(100),
97+
BigDecimal.valueOf(100.1),
98+
Boolean.FALSE,
99+
(byte)7,
100+
(short)1000,
101+
100,
102+
100000000000000000L,
103+
-100.2f,
104+
100.3d,
105+
new BigInteger("01020304", 16).toByteArray(),
106+
new BigInteger("0102030405", 16).toByteArray(),
107+
new BigInteger("010203040506", 16).toByteArray(),
108+
Date.valueOf("1983-03-14"),
109+
Time.valueOf("12:01:06"),
110+
new Timestamp(129479994)
111+
};
112+
113+
protected static TarantoolControl control;
114+
Connection conn;
115+
116+
@BeforeAll
117+
public static void setupEnv() throws Exception {
118+
control = new TarantoolControl();
119+
control.start("jdk-testing");
120+
control.waitStarted("jdk-testing");
121+
122+
sqlExec(initSql);
123+
}
124+
125+
@AfterAll
126+
public static void teardownEnv() throws Exception {
127+
try {
128+
sqlExec(cleanSql);
129+
} finally {
130+
control.stop("jdk-testing");
131+
control.waitStopped("jdk-testing");
132+
}
133+
}
134+
135+
@BeforeEach
136+
public void setUpConnection() throws SQLException {
137+
conn = DriverManager.getConnection(URL);
138+
assertNotNull(conn);
139+
}
140+
141+
@AfterEach
142+
public void tearDownConnection() throws SQLException {
143+
if (conn != null && !conn.isClosed())
144+
conn.close();
145+
}
146+
147+
private static void sqlExec(String[] text) throws IOException {
148+
Socket socket = new Socket();
149+
try {
150+
socket.connect(new InetSocketAddress(host, port));
151+
TarantoolConnection con = new TarantoolConnection(user, pass, socket);
152+
try {
153+
for (String cmd : text)
154+
con.eval("box.sql.execute(\"" + cmd + "\")");
155+
}
156+
finally {
157+
con.close();
158+
socket = null;
159+
}
160+
}
161+
finally {
162+
if (socket != null)
163+
socket.close();
164+
}
165+
}
166+
167+
static List<?> getRow(String space, Object key) throws IOException {
168+
Socket socket = new Socket();
169+
try {
170+
socket.connect(new InetSocketAddress(host, port));
171+
TarantoolConnection con = new TarantoolConnection(user, pass, socket);
172+
try {
173+
List<?> l = con.select(281, 2, Arrays.asList(space.toUpperCase()), 0, 1, 0);
174+
Integer spaceId = (Integer) ((List) l.get(0)).get(0);
175+
l = con.select(spaceId, 0, Arrays.asList(key), 0, 1, 0);
176+
return (l == null || l.size() == 0) ? Collections.emptyList() : (List<?>) l.get(0);
177+
}
178+
finally {
179+
con.close();
180+
socket = null;
181+
}
182+
}
183+
finally {
184+
if (socket != null)
185+
socket.close();
186+
}
187+
}
188+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.tarantool.jdbc;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.sql.DatabaseMetaData;
6+
import java.sql.PreparedStatement;
7+
import java.sql.SQLException;
8+
import java.sql.Statement;
9+
10+
import static org.junit.jupiter.api.Assertions.assertFalse;
11+
import static org.junit.jupiter.api.Assertions.assertNotNull;
12+
import static org.junit.jupiter.api.Assertions.assertTrue;
13+
14+
public class JdbcConnectionIT extends AbstractJdbcIT {
15+
@Test
16+
public void testCreateStatement() throws SQLException {
17+
Statement stmt = conn.createStatement();
18+
assertNotNull(stmt);
19+
stmt.close();
20+
}
21+
22+
@Test
23+
public void testPrepareStatement() throws SQLException {
24+
PreparedStatement prep = conn.prepareStatement("INSERT INTO test(id, val) VALUES(?, ?)");
25+
assertNotNull(prep);
26+
prep.close();
27+
}
28+
29+
@Test
30+
public void testCloseIsClosed() throws SQLException {
31+
assertFalse(conn.isClosed());
32+
conn.close();
33+
assertTrue(conn.isClosed());
34+
conn.close();
35+
}
36+
37+
@Test
38+
public void testGetMetaData() throws SQLException {
39+
DatabaseMetaData meta = conn.getMetaData();
40+
assertNotNull(meta);
41+
}
42+
}

0 commit comments

Comments
 (0)