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