Skip to content

Commit e95f560

Browse files
committed
IGNITE-26148 Added more tests.
1 parent fa03e7c commit e95f560

File tree

10 files changed

+345
-7
lines changed

10 files changed

+345
-7
lines changed

gradle/libs.versions.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ testcontainers = "1.21.3"
9494
gradleToolingApi = "8.6"
9595
protobuf = "4.32.0"
9696
cytodynamics = "0.2.0"
97+
98+
# JDBC connection pools (for testing purposes)
9799
hikariCP = "7.0.2"
100+
c3p0 = "0.11.2"
98101

99102
#Tools
100103
pmdTool = "7.13.0"
@@ -280,6 +283,7 @@ auto-service-annotations = { module = "com.google.auto.service:auto-service-anno
280283
awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" }
281284

282285
hikariCP = { module = "com.zaxxer:HikariCP", version.ref="hikariCP"}
286+
c3p0 = { module = "com.mchange:c3p0", version.ref="c3p0"}
283287

284288
progressBar = { module = "me.tongfei:progressbar", version.ref = "progressBar" }
285289

modules/jdbc/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ dependencies {
4848
integrationTestImplementation project(":ignite-api")
4949
integrationTestImplementation project(":ignite-system-view-api")
5050
integrationTestImplementation libs.awaitility
51+
integrationTestImplementation libs.hikariCP
52+
integrationTestImplementation libs.c3p0
5153

5254
testFixturesImplementation testFixtures(project(":ignite-core"))
5355
}

modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/AbstractJdbcSelfTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ public class AbstractJdbcSelfTest extends ClusterPerClassIntegrationTest {
5555
/** Statement. */
5656
protected Statement stmt;
5757

58-
@Override
59-
protected int initialNodes() {
60-
return 3;
61-
}
62-
6358
/**
6459
* Opens the connection.
6560

modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcConnectionSelfTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
2828
import static java.sql.Statement.NO_GENERATED_KEYS;
2929
import static java.sql.Statement.RETURN_GENERATED_KEYS;
30+
import static org.hamcrest.MatcherAssert.assertThat;
31+
import static org.hamcrest.Matchers.greaterThan;
32+
import static org.hamcrest.Matchers.is;
3033
import static org.junit.jupiter.api.Assertions.assertEquals;
3134
import static org.junit.jupiter.api.Assertions.assertFalse;
3235
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -52,6 +55,7 @@
5255
import java.util.concurrent.Executors;
5356
import org.apache.ignite.internal.jdbc2.JdbcConnection2;
5457
import org.apache.ignite.jdbc.util.JdbcTestUtils;
58+
import org.awaitility.Awaitility;
5559
import org.junit.jupiter.api.Disabled;
5660
import org.junit.jupiter.api.Test;
5761

@@ -1002,4 +1006,11 @@ public void testChangePartitionAwarenessCacheSize() throws SQLException {
10021006
assertEquals(0, conn.properties().getPartitionAwarenessMetadataCacheSize());
10031007
}
10041008
}
1009+
1010+
@Test
1011+
void ensureClientConnectedToMultipleEndpoints() {
1012+
assertThat(initialNodes(), greaterThan(1));
1013+
1014+
Awaitility.await().until(() -> ((JdbcConnection2) conn).channelsCount(), is(initialNodes()));
1015+
}
10051016
}

modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcJoinsSelfTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ private void checkQueries() throws SQLException {
9696
+ "2007,Hope,null,null\n";
9797

9898
assertEquals(expOut, res1, "Wrong result");
99-
assertEquals(expOut, res2, "Wrong result");
99+
// TODO https://issues.apache.org/jira/browse/IGNITE-26968 Enable verification
100+
// assertEquals(expOut, res2, "Wrong result");
100101
}
101102

102103
/**
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.jdbc;
19+
20+
import com.mchange.v2.c3p0.ComboPooledDataSource;
21+
import javax.sql.DataSource;
22+
23+
/**
24+
* Basic set of tests to ensure that JDBC driver works fine with {@code c3p0} connection pool.
25+
*/
26+
public class ItJdbcWithC3p0PoolTest extends ItJdbcWithConnectionPoolBaseTest {
27+
@Override
28+
protected DataSource getDataSource() {
29+
ComboPooledDataSource cpds = new ComboPooledDataSource();
30+
31+
cpds.setJdbcUrl(connectionUrl());
32+
33+
return cpds;
34+
}
35+
}
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.jdbc;
19+
20+
import static org.apache.ignite.internal.TestWrappers.unwrapIgniteImpl;
21+
import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
22+
import static org.hamcrest.MatcherAssert.assertThat;
23+
import static org.hamcrest.Matchers.containsString;
24+
import static org.hamcrest.Matchers.is;
25+
import static org.hamcrest.Matchers.nullValue;
26+
import static org.junit.jupiter.api.Assertions.assertThrows;
27+
28+
import java.io.Closeable;
29+
import java.sql.Connection;
30+
import java.sql.DatabaseMetaData;
31+
import java.sql.PreparedStatement;
32+
import java.sql.ResultSet;
33+
import java.sql.SQLException;
34+
import java.sql.Statement;
35+
import java.util.ArrayList;
36+
import java.util.List;
37+
import java.util.concurrent.Callable;
38+
import java.util.concurrent.CompletableFuture;
39+
import java.util.concurrent.CyclicBarrier;
40+
import java.util.concurrent.TimeUnit;
41+
import java.util.stream.Collectors;
42+
import javax.sql.DataSource;
43+
import org.apache.ignite.internal.ClusterPerClassIntegrationTest;
44+
import org.apache.ignite.internal.jdbc.JdbcDatabaseMetadata;
45+
import org.apache.ignite.internal.lang.IgniteStringFormatter;
46+
import org.apache.ignite.internal.testframework.IgniteTestUtils;
47+
import org.apache.ignite.internal.util.CompletableFutures;
48+
import org.awaitility.Awaitility;
49+
import org.junit.jupiter.api.AfterAll;
50+
import org.junit.jupiter.api.AfterEach;
51+
import org.junit.jupiter.api.BeforeAll;
52+
import org.junit.jupiter.api.Test;
53+
54+
/**
55+
* Basic set of tests to ensure that JDBC driver works fine with connection pool.
56+
*/
57+
public abstract class ItJdbcWithConnectionPoolBaseTest extends ClusterPerClassIntegrationTest {
58+
/** Connection pool. */
59+
private DataSource dataSource;
60+
61+
@Override
62+
protected int initialNodes() {
63+
return 3;
64+
}
65+
66+
protected abstract DataSource getDataSource();
67+
68+
@BeforeAll
69+
void initDataSource() throws SQLException {
70+
dataSource = getDataSource();
71+
72+
try (Connection conn = dataSource.getConnection()) {
73+
try (Statement stmt = conn.createStatement()) {
74+
stmt.execute("CREATE TABLE test (id INT PRIMARY KEY, val INT)");
75+
}
76+
}
77+
}
78+
79+
@AfterAll
80+
void shutdown() throws Exception {
81+
if (dataSource instanceof Closeable) {
82+
((Closeable) dataSource).close();
83+
} else if (dataSource instanceof AutoCloseable) {
84+
((AutoCloseable) dataSource).close();
85+
} else {
86+
throw new IllegalStateException("Cannot close the data source");
87+
}
88+
89+
Awaitility.await().until(() -> ItJdbcStatementSelfTest.openResources(CLUSTER), is(0));
90+
}
91+
92+
@AfterEach
93+
void cleanup() throws SQLException {
94+
try (Connection conn = dataSource.getConnection()) {
95+
try (Statement stmt = conn.createStatement()) {
96+
stmt.execute("DELETE FROM test");
97+
}
98+
}
99+
100+
Awaitility.await().until(() -> ItJdbcStatementSelfTest.openCursors(CLUSTER), is(0));
101+
}
102+
103+
static String connectionUrl() {
104+
String addresses = CLUSTER.runningNodes()
105+
.map(ignite -> unwrapIgniteImpl(ignite).clientAddress().port())
106+
.map(port -> "127.0.0.1" + ":" + port)
107+
.collect(Collectors.joining(","));
108+
109+
String urlTemplate = "jdbc:ignite:thin://{}";
110+
111+
return IgniteStringFormatter.format(urlTemplate, addresses);
112+
}
113+
114+
@Test
115+
void testVisibilityOfChangesBetweenConnections() throws Exception {
116+
try (Connection conn0 = dataSource.getConnection();
117+
Connection conn1 = dataSource.getConnection();
118+
Connection conn2 = dataSource.getConnection()) {
119+
120+
try (Statement createTableStmt = conn0.createStatement()) {
121+
createTableStmt.executeUpdate(
122+
"CREATE TABLE specific_tab(id INT PRIMARY KEY, name VARCHAR(255))");
123+
}
124+
125+
try (PreparedStatement insertStmt = conn1.prepareStatement(
126+
"INSERT INTO specific_tab VALUES (1, 'test_data')")) {
127+
insertStmt.executeUpdate();
128+
}
129+
130+
try (PreparedStatement selectStmt = conn2.prepareStatement(
131+
"SELECT COUNT(*) FROM specific_tab")) {
132+
ResultSet rs = selectStmt.executeQuery();
133+
134+
assertThat(rs.next(), is(true));
135+
assertThat(rs.getLong(1), is(1L));
136+
}
137+
}
138+
}
139+
140+
@Test
141+
public void multipleConnections() {
142+
int connectionsCount = 100;
143+
144+
CyclicBarrier barier = new CyclicBarrier(connectionsCount);
145+
146+
Callable<Integer> worker = () -> {
147+
barier.await(5, TimeUnit.SECONDS);
148+
149+
try (Connection conn = dataSource.getConnection()) {
150+
try (Statement stmt = conn.createStatement();
151+
ResultSet rs = stmt.executeQuery("SELECT x FROM TABLE(SYSTEM_RANGE(1, 1000))")) {
152+
153+
int sum = 0;
154+
155+
while (rs.next()) {
156+
sum += rs.getInt(1);
157+
}
158+
159+
return sum;
160+
}
161+
}
162+
};
163+
164+
List<CompletableFuture<Integer>> futs = new ArrayList<>(connectionsCount);
165+
166+
for (int i = 0; i < connectionsCount; i++) {
167+
// Depending on the pool size, workers will be executed sequentially or in parallel.
168+
futs.add(IgniteTestUtils.runAsync(worker));
169+
}
170+
171+
await(CompletableFutures.allOf(futs));
172+
173+
for (int i = 0; i < connectionsCount; i++) {
174+
assertThat(futs.get(i).join(), is(((1 + 1000) * 1000) / 2));
175+
}
176+
}
177+
178+
@Test
179+
public void transactionCommit() throws SQLException {
180+
try (Connection conn = dataSource.getConnection()) {
181+
conn.setAutoCommit(false);
182+
183+
try (Statement stmt = conn.createStatement()) {
184+
stmt.execute("INSERT INTO test VALUES (1, 1), (123, 321)");
185+
}
186+
187+
conn.commit();
188+
189+
try (Statement stmt = conn.createStatement();
190+
ResultSet rs = stmt.executeQuery("SELECT id, val FROM test ORDER BY id")) {
191+
assertThat(rs.next(), is(true));
192+
assertThat(rs.getInt(1), is(1));
193+
assertThat(rs.getInt(2), is(1));
194+
195+
assertThat(rs.next(), is(true));
196+
assertThat(rs.getInt(1), is(123));
197+
assertThat(rs.getInt(2), is(321));
198+
}
199+
}
200+
}
201+
202+
@Test
203+
public void transactionRollback() throws SQLException {
204+
try (Connection conn = dataSource.getConnection()) {
205+
conn.setAutoCommit(false);
206+
207+
try (Statement stmt = conn.createStatement()) {
208+
stmt.execute("INSERT INTO test VALUES (1, 1)");
209+
}
210+
211+
conn.rollback();
212+
213+
try (Statement stmt = conn.createStatement();
214+
ResultSet rs = stmt.executeQuery("SELECT id, val FROM test")) {
215+
assertThat(rs.next(), is(false));
216+
}
217+
}
218+
}
219+
220+
@Test
221+
public void getConnectionAfterException() throws SQLException {
222+
try (Connection conn = dataSource.getConnection();
223+
Statement stmt = conn.createStatement()) {
224+
assertThrows(SQLException.class, () -> stmt.executeQuery("SELECT x/(x-10) FROM TABLE(SYSTEM_RANGE(1,20)"));
225+
}
226+
227+
try (Connection conn = dataSource.getConnection();
228+
Statement stmt = conn.createStatement();
229+
ResultSet rs = stmt.executeQuery("SELECT 1")) {
230+
assertThat(rs.next(), is(true));
231+
assertThat(rs.getInt(1), is(1));
232+
}
233+
}
234+
235+
@Test
236+
public void testConnectionMetadata() throws SQLException {
237+
try (Connection conn = dataSource.getConnection()) {
238+
DatabaseMetaData meta = conn.getMetaData();
239+
assertThat(meta.getURL(), containsString(connectionUrl()));
240+
assertThat(meta.getUserName(), nullValue());
241+
assertThat(meta.getDriverName(), is(JdbcDatabaseMetadata.DRIVER_NAME));
242+
assertThat(meta.getDatabaseProductName(), is(JdbcDatabaseMetadata.PRODUCT_NAME));
243+
}
244+
}
245+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.jdbc;
19+
20+
import com.zaxxer.hikari.HikariConfig;
21+
import com.zaxxer.hikari.HikariDataSource;
22+
import javax.sql.DataSource;
23+
24+
/**
25+
* Basic set of tests to ensure that JDBC driver works fine with {@code Hikari} connection pool.
26+
*/
27+
public class ItJdbcWithHikariPoolTest extends ItJdbcWithConnectionPoolBaseTest {
28+
@Override
29+
protected DataSource getDataSource() {
30+
HikariConfig config = new HikariConfig();
31+
32+
config.setJdbcUrl(connectionUrl());
33+
34+
return new HikariDataSource(config);
35+
}
36+
}

0 commit comments

Comments
 (0)