Skip to content

Commit 065e5af

Browse files
committed
Tests for DBUtil
This patch adds test for the lock management: - getGlobalLock - releaseGlobalLock Signed-off-by: Laszlo Hornyak <laszlo.hornyak@gmail.com>
1 parent 438cf4e commit 065e5af

3 files changed

Lines changed: 206 additions & 19 deletions

File tree

framework/db/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
<groupId>commons-dbcp</groupId>
3636
<artifactId>commons-dbcp</artifactId>
3737
</dependency>
38+
<dependency>
39+
<groupId>commons-io</groupId>
40+
<artifactId>commons-io</artifactId>
41+
</dependency>
3842
<dependency>
3943
<groupId>commons-pool</groupId>
4044
<artifactId>commons-pool</artifactId>

framework/db/src/com/cloud/utils/db/DbUtil.java

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,14 @@ public static boolean getGlobalLock(String name, int timeoutSeconds) {
208208
}
209209

210210
PreparedStatement pstmt = null;
211+
ResultSet rs = null;
211212
try {
212213
pstmt = conn.prepareStatement("SELECT COALESCE(GET_LOCK(?, ?),0)");
213214

214215
pstmt.setString(1, name);
215216
pstmt.setInt(2, timeoutSeconds);
216217

217-
ResultSet rs = pstmt.executeQuery();
218+
rs = pstmt.executeQuery();
218219
if (rs != null && rs.first()) {
219220
if(rs.getInt(1) > 0) {
220221
return true;
@@ -228,13 +229,8 @@ public static boolean getGlobalLock(String name, int timeoutSeconds) {
228229
} catch (Throwable e) {
229230
s_logger.error("GET_LOCK() throws exception ", e);
230231
} finally {
231-
if (pstmt != null) {
232-
try {
233-
pstmt.close();
234-
} catch (Throwable e) {
235-
s_logger.error("What the heck? ", e);
236-
}
237-
}
232+
closeStatement(pstmt);
233+
closeResultSet(rs);
238234
}
239235

240236
removeConnectionForGlobalLocks(name);
@@ -259,10 +255,11 @@ public static boolean releaseGlobalLock(String name) {
259255
}
260256

261257
PreparedStatement pstmt = null;
258+
ResultSet rs = null;
262259
try {
263260
pstmt = conn.prepareStatement("SELECT COALESCE(RELEASE_LOCK(?), 0)");
264261
pstmt.setString(1, name);
265-
ResultSet rs = pstmt.executeQuery();
262+
rs = pstmt.executeQuery();
266263
if(rs != null && rs.first())
267264
return rs.getInt(1) > 0;
268265
s_logger.error("RELEASE_LOCK() returns unexpected result : " + rs.getInt(1));
@@ -271,13 +268,9 @@ public static boolean releaseGlobalLock(String name) {
271268
} catch (Throwable e) {
272269
s_logger.error("RELEASE_LOCK() throws exception ", e);
273270
} finally {
274-
try {
275-
if (pstmt != null) {
276-
pstmt.close();
277-
}
278-
conn.close();
279-
} catch(SQLException e) {
280-
}
271+
closeResultSet(rs);
272+
closeStatement(pstmt);
273+
closeConnection(conn);
281274
}
282275
return false;
283276
}
@@ -305,7 +298,7 @@ public static void closeResultSet(final ResultSet resultSet) {
305298
resultSet.close();
306299
}
307300

308-
} catch (Exception e) {
301+
} catch (SQLException e) {
309302
s_logger.warn("Ignored exception while closing result set.",e);
310303
}
311304

@@ -319,7 +312,7 @@ public static void closeStatement(final Statement statement) {
319312
statement.close();
320313
}
321314

322-
} catch (Exception e) {
315+
} catch (SQLException e) {
323316
s_logger.warn("Ignored exception while closing statement.",e);
324317
}
325318

@@ -333,7 +326,7 @@ public static void closeConnection(final Connection connection) {
333326
connection.close();
334327
}
335328

336-
} catch (Exception e) {
329+
} catch (SQLException e) {
337330
s_logger.warn("Ignored exception while close connection.",e);
338331
}
339332

framework/db/test/com/cloud/utils/DbUtilTest.java

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,58 @@
1616
// under the License.
1717
package com.cloud.utils;
1818

19+
import java.io.IOException;
20+
import java.lang.reflect.Field;
21+
import java.sql.Connection;
22+
import java.sql.PreparedStatement;
23+
import java.sql.ResultSet;
24+
import java.sql.SQLException;
25+
import java.sql.Statement;
26+
import java.util.HashMap;
27+
import java.util.Map;
28+
1929
import javax.persistence.Column;
30+
import javax.persistence.Table;
31+
import javax.sql.DataSource;
2032

33+
import org.junit.After;
2134
import org.junit.Assert;
35+
import org.junit.Before;
2236
import org.junit.Ignore;
2337
import org.junit.Test;
38+
import org.junit.runner.RunWith;
39+
import org.mockito.Mock;
40+
import org.mockito.Mockito;
41+
import org.mockito.runners.MockitoJUnitRunner;
2442

2543
import com.cloud.utils.db.DbUtil;
44+
import com.cloud.utils.db.TransactionLegacy;
2645

46+
@RunWith(MockitoJUnitRunner.class)
2747
public class DbUtilTest {
2848

49+
@Mock
50+
Connection connection;
51+
52+
@Mock
53+
PreparedStatement preparedStatement;
54+
55+
@Mock
56+
Statement statement;
57+
58+
@Mock
59+
ResultSet resultSet;
60+
61+
@Mock
62+
DataSource dataSource;
63+
64+
DataSource backup;
65+
66+
Map<String, Connection> connectionMapBackup = null;
67+
68+
Map<String, Connection> connectionMap = null;
69+
70+
@Table(name = "test_table")
2971
static class Testbean {
3072
String noAnnotation;
3173
@Column()
@@ -78,4 +120,152 @@ public void isPersistable() throws SecurityException, NoSuchFieldException {
78120
.getDeclaredField("instanceField")));
79121
}
80122

123+
class Bar {
124+
125+
}
126+
127+
@Test
128+
public void getTableName() {
129+
Assert.assertEquals("test_table", DbUtil.getTableName(Testbean.class));
130+
Assert.assertEquals("Bar", DbUtil.getTableName(Bar.class));
131+
}
132+
133+
@SuppressWarnings("unchecked")
134+
@Before
135+
public void setup() throws SecurityException, NoSuchFieldException,
136+
IllegalArgumentException, IllegalAccessException {
137+
Field globalLocks = DbUtil.class
138+
.getDeclaredField("s_connectionForGlobalLocks");
139+
globalLocks.setAccessible(true);
140+
connectionMapBackup = (Map<String, Connection>) globalLocks.get(null);
141+
connectionMap = new HashMap<String, Connection>();
142+
globalLocks.set(null, connectionMap);
143+
144+
Field dsField = TransactionLegacy.class.getDeclaredField("s_ds");
145+
dsField.setAccessible(true);
146+
backup = (DataSource) dsField.get(null);
147+
dsField.set(null, dataSource);
148+
}
149+
150+
@After
151+
public void cleanup() throws SecurityException, NoSuchFieldException,
152+
IllegalArgumentException, IllegalAccessException {
153+
Field globalLocks = DbUtil.class
154+
.getDeclaredField("s_connectionForGlobalLocks");
155+
globalLocks.setAccessible(true);
156+
globalLocks.set(null, connectionMapBackup);
157+
158+
Field dsField = TransactionLegacy.class.getDeclaredField("s_ds");
159+
dsField.setAccessible(true);
160+
dsField.set(null, backup);
161+
}
162+
163+
@Test
164+
public void getGlobalLock() throws SQLException {
165+
Mockito.when(dataSource.getConnection()).thenReturn(connection);
166+
Mockito.when(connection.prepareStatement(Mockito.anyString()))
167+
.thenReturn(preparedStatement);
168+
Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
169+
Mockito.when(resultSet.first()).thenReturn(true);
170+
Mockito.when(resultSet.getInt(1)).thenReturn(1);
171+
Assert.assertTrue(DbUtil.getGlobalLock("TEST", 600));
172+
173+
Mockito.verify(connection).prepareStatement(Mockito.anyString());
174+
Mockito.verify(preparedStatement).close();
175+
Mockito.verify(resultSet).close();
176+
}
177+
178+
@Test
179+
public void getGlobalLockTimeout() throws SQLException {
180+
Mockito.when(dataSource.getConnection()).thenReturn(connection);
181+
Mockito.when(connection.prepareStatement(Mockito.anyString()))
182+
.thenReturn(preparedStatement);
183+
Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
184+
Mockito.when(resultSet.first()).thenReturn(true);
185+
Mockito.when(resultSet.getInt(1)).thenReturn(0);
186+
Assert.assertFalse(DbUtil.getGlobalLock("TEST", 600));
187+
188+
Mockito.verify(connection).prepareStatement(Mockito.anyString());
189+
Mockito.verify(preparedStatement).close();
190+
Mockito.verify(resultSet).close();
191+
Mockito.verify(connection).close();
192+
193+
// if any error happens, the connection map must be cleared
194+
Assert.assertTrue(connectionMap.isEmpty());
195+
}
196+
197+
@Test
198+
public void closeNull() {
199+
DbUtil.closeStatement((Statement) null);
200+
DbUtil.closeConnection((Connection) null);
201+
DbUtil.closeResultSet((ResultSet) null);
202+
// no exception should be thrown
203+
}
204+
205+
@Test
206+
public void closeConnection() throws IOException, SQLException {
207+
DbUtil.closeConnection(connection);
208+
Mockito.verify(connection).close();
209+
}
210+
211+
@Test
212+
public void closeConnectionFail() throws IOException, SQLException {
213+
Mockito.doThrow(new SQLException("it is all right")).when(connection)
214+
.close();
215+
DbUtil.closeConnection(connection);
216+
Mockito.verify(connection).close();
217+
}
218+
219+
@Test
220+
public void closeStatement() throws IOException, SQLException {
221+
DbUtil.closeStatement(statement);
222+
Mockito.verify(statement).close();
223+
}
224+
225+
@Test
226+
public void closeStatementFail() throws IOException, SQLException {
227+
Mockito.doThrow(new SQLException("it is all right")).when(statement)
228+
.close();
229+
DbUtil.closeStatement(statement);
230+
Mockito.verify(statement).close();
231+
}
232+
233+
@Test
234+
public void closeResultSet() throws IOException, SQLException {
235+
DbUtil.closeResultSet(resultSet);
236+
Mockito.verify(resultSet).close();
237+
}
238+
239+
@Test
240+
public void closeResultSetFail() throws IOException, SQLException {
241+
Mockito.doThrow(new SQLException("it is all right")).when(resultSet)
242+
.close();
243+
DbUtil.closeResultSet(resultSet);
244+
Mockito.verify(resultSet).close();
245+
}
246+
247+
@Test
248+
@Ignore
249+
//can not be performed since assertion embedded in this branch of execution
250+
public void releaseGlobalLockNotexisting() throws SQLException {
251+
Assert.assertFalse(DbUtil.releaseGlobalLock("notexisting"));
252+
Mockito.verify(dataSource, Mockito.never()).getConnection();
253+
}
254+
255+
@Test
256+
public void releaseGlobalLock() throws SQLException {
257+
Mockito.when(connection.prepareStatement(Mockito.anyString()))
258+
.thenReturn(preparedStatement);
259+
Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
260+
Mockito.when(resultSet.first()).thenReturn(true);
261+
Mockito.when(resultSet.getInt(1)).thenReturn(1);
262+
connectionMap.put("testLock", connection);
263+
Assert.assertTrue(DbUtil.releaseGlobalLock("testLock"));
264+
265+
Mockito.verify(resultSet).close();
266+
Mockito.verify(preparedStatement).close();
267+
Mockito.verify(connection).close();
268+
Assert.assertFalse(connectionMap.containsKey("testLock"));
269+
}
270+
81271
}

0 commit comments

Comments
 (0)