code.onehippo.org is currently readonly. We are migrating to code.bloomreach.com, please continue working there on Monday 14/12. See: https://docs.bloomreach.com/display/engineering/GitLab

Commit 43f17029 authored by Ard Schrijvers's avatar Ard Schrijvers

REPO-1811 Enhance abort tests

parent cc3e10d9
......@@ -23,6 +23,7 @@ import org.junit.Test;
import org.onehippo.cms7.services.lock.LockException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.onehippo.repository.lock.db.DbLockManager.ABORT_STATEMENT;
......@@ -33,7 +34,7 @@ public class LockManagerAbortTest extends AbstractLockManagerTest {
@Test
public void any_thread_can_request_abort_which_results_in_an_interrupt_for_thread_holding_lock() throws Exception {
final String key = "123";
final LockRunnable runnable = new LockRunnable(key, true);
final LockRunnable runnable = new LockRunnable(key, true, false);
final Thread lockThread = new Thread(runnable);
lockThread.start();
......@@ -54,24 +55,96 @@ public class LockManagerAbortTest extends AbstractLockManagerTest {
}
@Test
public void other_cluster_node_has_set_abort() throws Exception {
if (dataSource == null) {
// in memory test
return;
}
// by manually in the database setting status 'ABORT' is the same as if it is done on a different cluster node
// it might only take up to 5 seconds before the LockThreadInterrupter background thread triggers an interrupt
final String key = "123";
final LockRunnable runnable = new LockRunnable(key, true, false);
final Thread lockThread = new Thread(runnable);
lockThread.start();
// give lockThread time to lock
Thread.sleep(100);
// now abort via database : this is as if another cluster node did it
abortDataRowLock(key);
// although keepalive still true, the lockThread should via the LockThreadInterrupter get an interrupt
lockThread.join();
assertTrue("lockThread should be interrupted", runnable.interrupted);
// AFTER the interrupt, the database record should be in state 'FREE' since LockRunnable invoked #unlock
dbRowAssertion(key, "FREE");
}
private void abortDataRowLock(final String key) throws SQLException {
try (Connection connection = dataSource.getConnection()){
connection.setAutoCommit(true);
final PreparedStatement abortStatement = connection.prepareStatement(ABORT_STATEMENT);
abortStatement.setString(1, key);
int changed = abortStatement.executeUpdate();
assertEquals("Abort should had modified 1 row", 1, changed);
}
}
@Test
public void a_lock_set_to_abort_is_still_freed_on_lockmanager_clear_but_not_being_interrupted_any_more() throws Exception {
if (dataSource == null) {
// in memory test
return;
}
final String key = "123";
final LockRunnable runnable = new LockRunnable(key, true, true);
final Thread lockThread = new Thread(runnable);
lockThread.start();
// give lockThread time to lock
Thread.sleep(100);
// now abort via database : this is as if another cluster node did it
abortDataRowLock(key);
lockManager.clear();
lockThread.join();
assertFalse("Since the lock manager has been cleared (destroyed) after the ABORT was set, " +
"the interrupt should never be invoked." ,runnable.interrupted);
}
private class LockRunnable implements Runnable {
private String key;
private volatile boolean keepAlive;
private boolean stopAfter10Seconds;
private boolean interrupted = false;
LockRunnable(final String key, final boolean keepAlive) {
LockRunnable(final String key, final boolean keepAlive, final boolean stopAfter10Seconds) {
this.key = key;
this.keepAlive = keepAlive;
this.stopAfter10Seconds = stopAfter10Seconds;
}
@Override
public void run() {
long start = System.currentTimeMillis();
try {
lockManager.lock(key);
while (keepAlive) {
Thread.sleep(25);
if ((System.currentTimeMillis() - start) > 10000) {
if (stopAfter10Seconds) {
break;
}
fail("Within 10 seconds this thread should had been interrupted");
}
}
} catch (LockException e) {
fail("Unexpected lock exception :" + e.toString());
......@@ -111,13 +184,4 @@ public class LockManagerAbortTest extends AbstractLockManagerTest {
}
}
private static class MsgExceptionPair {
private String msg;
private Exception e;
public MsgExceptionPair(final String msg, final Exception e) {
this.msg = msg;
this.e = e;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment