Line 0
Link Here
|
|
|
1 |
package org.apache.tomcat.jdbc.test; |
2 |
|
3 |
import java.sql.Connection; |
4 |
import java.sql.DriverManager; |
5 |
import java.sql.DriverPropertyInfo; |
6 |
import java.sql.ResultSet; |
7 |
import java.sql.SQLException; |
8 |
import java.sql.SQLFeatureNotSupportedException; |
9 |
import java.sql.Statement; |
10 |
import java.util.Properties; |
11 |
import java.util.logging.Logger; |
12 |
|
13 |
import junit.framework.Assert; |
14 |
|
15 |
import org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor; |
16 |
import org.junit.After; |
17 |
import org.junit.Before; |
18 |
import org.junit.Test; |
19 |
|
20 |
public class TestValidationQueryTimeout extends DefaultTestCase { |
21 |
|
22 |
private static int TIMEOUT = 10; |
23 |
private static boolean isTimeoutSet; |
24 |
private static final String longQuery = "select * from test as A, test as B, test as C, test as D, test as E"; |
25 |
|
26 |
@Before |
27 |
public void setUp() throws SQLException { |
28 |
DriverManager.registerDriver(new MockDriver()); |
29 |
|
30 |
// use our mock driver |
31 |
this.datasource.setDriverClassName(MockDriver.class.getName()); |
32 |
this.datasource.setUrl(MockDriver.url); |
33 |
|
34 |
// Required to trigger validation query's execution |
35 |
this.datasource.setInitialSize(1); |
36 |
this.datasource.setTestOnBorrow(true); |
37 |
this.datasource.setValidationInterval(-1); |
38 |
this.datasource.setValidationQuery("SELECT 1"); |
39 |
this.datasource.setValidationQueryTimeout(TIMEOUT); |
40 |
|
41 |
TIMEOUT = 10; |
42 |
isTimeoutSet = false; |
43 |
} |
44 |
|
45 |
@After |
46 |
public void tearDown() throws SQLException { |
47 |
DriverManager.deregisterDriver(new MockDriver()); |
48 |
} |
49 |
|
50 |
@Test |
51 |
public void testValidationQueryTimeoutEnabled() throws Exception { |
52 |
// because testOnBorrow is true, this triggers the validation query |
53 |
this.datasource.getConnection(); |
54 |
Assert.assertTrue(isTimeoutSet); |
55 |
} |
56 |
|
57 |
@Test |
58 |
public void testValidationQueryTimeoutDisabled() throws Exception { |
59 |
this.datasource.setValidationQueryTimeout(-1); |
60 |
|
61 |
// because testOnBorrow is true, this triggers the validation query |
62 |
this.datasource.getConnection(); |
63 |
Assert.assertFalse(isTimeoutSet); |
64 |
} |
65 |
|
66 |
@Test |
67 |
public void testValidationQueryTimeoutWithQueryTimeoutInterceptor() throws Exception { |
68 |
int interceptorTimeout = 30; |
69 |
this.datasource.setJdbcInterceptors( |
70 |
QueryTimeoutInterceptor.class.getName()+ |
71 |
"(queryTimeout="+ interceptorTimeout +")"); |
72 |
|
73 |
// because testOnBorrow is true, this triggers the validation query |
74 |
Connection con = this.datasource.getConnection(); |
75 |
Assert.assertTrue(isTimeoutSet); |
76 |
|
77 |
// increase the expected timeout to 30, which is what we set for the interceptor |
78 |
TIMEOUT = 30; |
79 |
|
80 |
// now create a statement, make sure the query timeout is set by the interceptor |
81 |
Statement st = con.createStatement(); |
82 |
Assert.assertEquals(interceptorTimeout, st.getQueryTimeout()); |
83 |
st.close(); |
84 |
st = con.prepareStatement(""); |
85 |
Assert.assertEquals(interceptorTimeout, st.getQueryTimeout()); |
86 |
st.close(); |
87 |
st = con.prepareCall(""); |
88 |
Assert.assertEquals(interceptorTimeout, st.getQueryTimeout()); |
89 |
st.close(); |
90 |
con.close(); |
91 |
|
92 |
// pull another connection and check it |
93 |
TIMEOUT = 10; |
94 |
isTimeoutSet = false; |
95 |
this.datasource.getConnection(); |
96 |
Assert.assertTrue(isTimeoutSet); |
97 |
} |
98 |
|
99 |
// this test depends on the execution time of the validation query |
100 |
// specifically, it needs to run for longer than 1 second to pass |
101 |
// if this fails |
102 |
@Test(expected=SQLException.class) |
103 |
public void testValidationQueryTimeoutOnConnection() throws Exception { |
104 |
// use our mock driver |
105 |
this.datasource.setDriverClassName("org.h2.Driver"); |
106 |
this.datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE"); |
107 |
|
108 |
// Required to trigger validation query's execution |
109 |
this.datasource.setTestOnConnect(true); |
110 |
this.datasource.setValidationInterval(-1); |
111 |
this.datasource.setValidationQuery(longQuery); |
112 |
this.datasource.setValidationQueryTimeout(1); |
113 |
|
114 |
this.datasource.getConnection(); |
115 |
} |
116 |
|
117 |
@Test(expected=SQLException.class) |
118 |
public void testValidationInvalidOnConnection() throws Exception { |
119 |
// use our mock driver |
120 |
this.datasource.setDriverClassName("org.h2.Driver"); |
121 |
this.datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE"); |
122 |
|
123 |
// Required to trigger validation query's execution |
124 |
this.datasource.setTestOnBorrow(true); |
125 |
this.datasource.setInitialSize(1); |
126 |
this.datasource.setTestOnConnect(true); |
127 |
this.datasource.setValidationInterval(-1); |
128 |
this.datasource.setValidationQuery("SELECT"); |
129 |
this.datasource.setValidationQueryTimeout(1); |
130 |
|
131 |
this.datasource.getConnection(); |
132 |
} |
133 |
|
134 |
@Test |
135 |
public void testLongValidationQueryTime() throws Exception { |
136 |
// use our mock driver |
137 |
this.datasource.setDriverClassName("org.h2.Driver"); |
138 |
this.datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE"); |
139 |
Connection con = this.datasource.getConnection(); |
140 |
Statement stmt = null; |
141 |
long start = 0, end = 0; |
142 |
try { |
143 |
stmt = con.createStatement(); |
144 |
// set the query timeout to 2 sec |
145 |
// this keeps this test from slowing things down too much |
146 |
stmt.setQueryTimeout(2); |
147 |
// assert that our long query takes longer than one second to run |
148 |
// this is a requirement for other tests to run properly |
149 |
start = System.currentTimeMillis(); |
150 |
stmt.execute(longQuery); |
151 |
} catch (SQLException ex) {} |
152 |
finally { |
153 |
end = System.currentTimeMillis(); |
154 |
|
155 |
if (stmt != null) { stmt.close(); } |
156 |
if (con != null) { con.close(); } |
157 |
|
158 |
Assert.assertTrue(start != 0 && end != 0); |
159 |
Assert.assertTrue((end - start) > 1000); |
160 |
} |
161 |
} |
162 |
|
163 |
@Test |
164 |
public void testValidationQueryTimeoutOnBorrow() throws Exception { |
165 |
// use our mock driver |
166 |
this.datasource.setDriverClassName("org.h2.Driver"); |
167 |
this.datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE"); |
168 |
|
169 |
// Required to trigger validation query's execution |
170 |
this.datasource.setTestOnBorrow(true); |
171 |
this.datasource.setValidationInterval(-1); |
172 |
this.datasource.setValidationQuery(longQuery); |
173 |
this.datasource.setValidationQueryTimeout(1); |
174 |
|
175 |
// assert that even though the validation query times out, we still get a connection |
176 |
Connection con = this.datasource.getConnection(); |
177 |
Assert.assertNotNull(con); |
178 |
Statement st = con.createStatement(); |
179 |
ResultSet rs = st.executeQuery("SELECT 1"); |
180 |
rs.close(); |
181 |
st.close(); |
182 |
con.close(); |
183 |
} |
184 |
|
185 |
/** |
186 |
* Mock Driver, Connection and Statement implementations use to verify setQueryTimeout was called. |
187 |
*/ |
188 |
public static class MockDriver implements java.sql.Driver { |
189 |
public static final String url = "jdbc:tomcat:mock"; |
190 |
|
191 |
public MockDriver() { |
192 |
} |
193 |
|
194 |
@Override |
195 |
public boolean acceptsURL(String url) throws SQLException { |
196 |
return url!=null && url.equals(MockDriver.url); |
197 |
} |
198 |
|
199 |
@Override |
200 |
public Connection connect(String url, Properties info) throws SQLException { |
201 |
return new MockConnection(info); |
202 |
} |
203 |
|
204 |
@Override |
205 |
public int getMajorVersion() { |
206 |
return 0; |
207 |
} |
208 |
|
209 |
@Override |
210 |
public int getMinorVersion() { |
211 |
return 0; |
212 |
} |
213 |
|
214 |
@Override |
215 |
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { |
216 |
return null; |
217 |
} |
218 |
|
219 |
@Override |
220 |
public boolean jdbcCompliant() { |
221 |
return false; |
222 |
} |
223 |
|
224 |
@Override |
225 |
public Logger getParentLogger() throws SQLFeatureNotSupportedException { |
226 |
return null; |
227 |
} |
228 |
} |
229 |
|
230 |
public static class MockConnection extends org.apache.tomcat.jdbc.test.driver.Connection { |
231 |
public MockConnection(Properties info) { |
232 |
super(info); |
233 |
} |
234 |
|
235 |
@Override |
236 |
public Statement createStatement() throws SQLException { |
237 |
return new MockStatement(); |
238 |
} |
239 |
} |
240 |
|
241 |
public static class MockStatement extends org.apache.tomcat.jdbc.test.driver.Statement { |
242 |
@Override |
243 |
public void setQueryTimeout(int seconds) throws SQLException { |
244 |
super.setQueryTimeout(seconds); |
245 |
Assert.assertEquals(TIMEOUT, seconds); |
246 |
isTimeoutSet = true; |
247 |
} |
248 |
} |
249 |
|
250 |
} |