ACS-9259 Improve stability of HazelcastLockStoreTxTest test (#3248)

This commit is contained in:
Gerard Olenski
2025-03-11 11:13:57 +01:00
committed by GitHub
parent 9d25c6dcd5
commit 51395de707

View File

@@ -25,29 +25,30 @@
*/
package org.alfresco.repo.lock.mem;
import java.util.Date;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.util.Date;
import jakarta.transaction.NotSupportedException;
import jakarta.transaction.SystemException;
import jakarta.transaction.UserTransaction;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.ConcurrencyFailureException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
/**
* Integration tests that check transaction related functionality of {@link LockStore} implementations.
*
* @author Matt Ward
*/
public abstract class AbstractLockStoreTxTest<T extends LockStore>
@@ -82,10 +83,10 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
/**
* <ul>
* <li>Start outer txn</li>
* <li>Modify lock in outer txn</li>
* <li>Start inner txn</li>
* <li>Modify lock in inner txn</li>
* <li>Start outer txn</li>
* <li>Modify lock in outer txn</li>
* <li>Start inner txn</li>
* <li>Modify lock in inner txn</li>
* </ul>
* Inner transaction should fail while outer succeeds
*/
@@ -106,11 +107,9 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
Date now = new Date();
Date expires = new Date(now.getTime() + 180000);
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"jbloggs", expires, Lifetime.EPHEMERAL, null);
"jbloggs", expires, Lifetime.EPHEMERAL, null);
Thread txB = new Thread("TxB")
{
Thread txB = new Thread("TxB") {
@Override
public void run()
{
@@ -138,7 +137,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
// txB sets a value, already seen as non-existent lock by txA
lockStore.set(nodeRef2, LockState.createLock(nodeRef2, LockType.WRITE_LOCK,
"csmith", null, Lifetime.EPHEMERAL, null));
"csmith", null, Lifetime.EPHEMERAL, null));
}
finally
{
@@ -152,7 +151,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
finally
{
// Stop 'main' from waiting
synchronized(main)
synchronized (main)
{
main.notifyAll();
}
@@ -166,6 +165,9 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
// txA set lock state 1
lockStore.set(nodeRef, lockState1);
// Perform a read, that we know will retrieve a null value (and null will be cached for this transaction)
assertNull("nodeRef2 LockState", lockStore.get(nodeRef2));
// Wait while txB reads and checks the LockState
txB.setDaemon(true);
txB.start();
@@ -186,13 +188,10 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
// Check we can see the update.
assertEquals("bsmith", lockStore.get(nodeRef).getOwner());
// Perform a read, that we know will retrieve a null value
assertNull("nodeRef2 LockState", lockStore.get(nodeRef2));
// Wait while txB populates the store with a value for nodeRef2
passControl(this, txB);
// Perform the read again - update should not be visible in this transaction
// Perform the read again - update should not be visible in this transaction (was already cached)
assertNull("nodeRef2 LockState", lockStore.get(nodeRef2));
}
finally
@@ -203,16 +202,16 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
protected void passControl(Object from, Object to)
{
synchronized(to)
synchronized (to)
{
to.notifyAll();
}
synchronized(from)
synchronized (from)
{
try
{
// TODO: wait should be called in a loop with repeated wait condition check,
// but what's the condition we're waiting on?
// but what's the condition we're waiting on?
from.wait(10000);
}
catch (InterruptedException error)
@@ -231,11 +230,9 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
Date now = new Date();
Date expires = new Date(now.getTime() + 180000);
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"jbloggs", expires, Lifetime.EPHEMERAL, null);
"jbloggs", expires, Lifetime.EPHEMERAL, null);
Thread txB = new Thread("TxB")
{
Thread txB = new Thread("TxB") {
@Override
public void run()
{
@@ -260,7 +257,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
// when it has been modified by another tx since this tx last inspected it.
AuthenticationUtil.setFullyAuthenticatedUser("jbloggs"); // Current lock owner
lockStore.set(nodeRef, LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"csmith", null, Lifetime.EPHEMERAL, null));
"csmith", null, Lifetime.EPHEMERAL, null));
fail("Exception should have been thrown but was not.");
}
catch (ConcurrencyFailureException e)
@@ -280,7 +277,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
finally
{
// Stop 'main' from waiting
synchronized(main)
synchronized (main)
{
main.notifyAll();
}
@@ -325,12 +322,11 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
final Date now = new Date();
Date expired = new Date(now.getTime() - 180000);
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"jbloggs", expired, Lifetime.EPHEMERAL, null);
"jbloggs", expired, Lifetime.EPHEMERAL, null);
final LockState lockState2 = LockState.createWithOwner(lockState1, "another");
Thread txB = new Thread("TxB")
{
Thread txB = new Thread("TxB") {
@Override
public void run()
{
@@ -351,7 +347,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
// (but not since this tx's initial read)
Date expiresFuture = new Date(now.getTime() + 180000);
final LockState newUserLockState = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"new-user", expiresFuture, Lifetime.EPHEMERAL, null);
"new-user", expiresFuture, Lifetime.EPHEMERAL, null);
lockStore.set(nodeRef, newUserLockState);
// Read
@@ -369,7 +365,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
finally
{
// Stop 'main' from waiting
synchronized(main)
synchronized (main)
{
main.notifyAll();
}
@@ -404,7 +400,6 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
}
}
@Test
public void testNotOnlyCurrentLockOwnerCanChangeInfo() throws NotSupportedException, SystemException
{
@@ -414,7 +409,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
Date now = new Date();
Date expires = new Date(now.getTime() + 180000);
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"jbloggs", expires, Lifetime.EPHEMERAL, null);
"jbloggs", expires, Lifetime.EPHEMERAL, null);
txA.begin();
try
@@ -455,7 +450,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
Date now = new Date();
Date expired = new Date(now.getTime() - 900);
final LockState lockState1 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"jbloggs", expired, Lifetime.EPHEMERAL, null);
"jbloggs", expired, Lifetime.EPHEMERAL, null);
txA.begin();
try
@@ -469,7 +464,7 @@ public abstract class AbstractLockStoreTxTest<T extends LockStore>
AuthenticationUtil.setFullyAuthenticatedUser("csmith");
Date expiresFuture = new Date(now.getTime() + 180000);
final LockState lockState2 = LockState.createLock(nodeRef, LockType.WRITE_LOCK,
"csmith", expiresFuture, Lifetime.EPHEMERAL, null);
"csmith", expiresFuture, Lifetime.EPHEMERAL, null);
lockStore.set(nodeRef, lockState2);
// Updated, since lock had expired.