ALF-5028: Tagging test mods

- Join onto first-level threads to be sure that first round of tagging has been done
 - Double-checks for transaction leaks (found 1)
 - Some formatting (new test only, but should be applied to file)


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@23015 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-10-11 11:06:18 +00:00
parent 01d9ad5384
commit 4a320906ca
2 changed files with 133 additions and 98 deletions

View File

@@ -167,8 +167,15 @@ public class AVMStoreDAOImpl extends AbstractAVMStoreDAOImpl
Map<String, Object> params = new HashMap<String, Object>(1); Map<String, Object> params = new HashMap<String, Object>(1);
params.put("id", storeId); params.put("id", storeId);
try
{
return (List<AVMStorePropertyEntity>) template.queryForList(SELECT_AVM_STORE_PROPS, params); return (List<AVMStorePropertyEntity>) template.queryForList(SELECT_AVM_STORE_PROPS, params);
} }
catch (Throwable e)
{
throw new RuntimeException("Unable to query for store properties: " + params);
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override

View File

@@ -20,6 +20,7 @@ package org.alfresco.repo.tagging;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -32,6 +33,8 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.ClasspathScriptLocation; import org.alfresco.repo.jscript.ClasspathScriptLocation;
import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ActionTrackingService; import org.alfresco.service.cmr.action.ActionTrackingService;
@@ -99,6 +102,15 @@ public class TaggingServiceImplTest extends TestCase
@Override @Override
protected void setUp() throws Exception protected void setUp() throws Exception
{ {
// Detect any dangling transactions as there is a lot of direct UserTransaction manipulation
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_NONE)
{
throw new IllegalStateException(
"There should not be any transactions when starting test: " +
AlfrescoTransactionSupport.getTransactionId() + " started at " +
new Date(AlfrescoTransactionSupport.getTransactionStartTime()));
}
// Get services // Get services
this.taggingService = (TaggingService)ctx.getBean("TaggingService"); this.taggingService = (TaggingService)ctx.getBean("TaggingService");
this.nodeService = (NodeService) ctx.getBean("NodeService"); this.nodeService = (NodeService) ctx.getBean("NodeService");
@@ -146,8 +158,13 @@ public class TaggingServiceImplTest extends TestCase
} }
@Override @Override
protected void tearDown() throws Exception { protected void tearDown() throws Exception
{
removeTestDocumentsAndFolders(); removeTestDocumentsAndFolders();
if (AlfrescoTransactionSupport.getTransactionReadState() != TxnReadState.TXN_NONE)
{
fail("Test is not transaction-safe. Fix up transaction handling and re-test.");
}
} }
private void createTestDocumentsAndFolders() throws Exception private void createTestDocumentsAndFolders() throws Exception
@@ -1095,13 +1112,16 @@ public class TaggingServiceImplTest extends TestCase
assertEquals(2, ts2.getTag(TAG_1).getCount()); assertEquals(2, ts2.getTag(TAG_1).getCount());
assertEquals(1, ts2.getTag(TAG_2).getCount()); assertEquals(1, ts2.getTag(TAG_2).getCount());
// Force txn commit to prevent test leaks
tx.commit();
} }
/** /**
* Test that when multiple threads do tag updates, the right * Test that when multiple threads do tag updates, the right thing still
* thing still happens * happens
*/ */
public void DISABLEDtestMultiThreaded() throws Exception public void testMultiThreaded() throws Exception
{ {
UserTransaction tx = this.transactionService.getNonPropagatingUserTransaction(); UserTransaction tx = this.transactionService.getNonPropagatingUserTransaction();
tx.begin(); tx.begin();
@@ -1112,63 +1132,78 @@ public class TaggingServiceImplTest extends TestCase
// Prepare a bunch of threads to do tagging // Prepare a bunch of threads to do tagging
final List<Thread> threads = new ArrayList<Thread>(); final List<Thread> threads = new ArrayList<Thread>();
String[] tags = new String[] { TAG_1, TAG_2, TAG_3, TAG_4, TAG_5 }; String[] tags = new String[] { TAG_1, TAG_2, TAG_3, TAG_4, TAG_5 };
for(String tmpTag : tags) for (String tmpTag : tags)
{ {
final String tag = tmpTag; final String tag = tmpTag;
Thread t = new Thread(new Runnable() { Thread t = new Thread(new Runnable()
{
@Override @Override
public void run() { public synchronized void run()
{
// Let everything catch up // Let everything catch up
try { try
Thread.sleep(250); {
} catch(InterruptedException e) {} wait();
System.out.println(Thread.currentThread() + " - About to start tagging"); }
catch (InterruptedException e)
{
}
System.out.println(Thread.currentThread() + " - About to start tagging");
// Do the updates // Do the updates
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
transactionService.getRetryingTransactionHelper().doInTransaction( transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>() { new RetryingTransactionCallback<Void>()
public Void execute() throws Throwable { {
public Void execute() throws Throwable
{
taggingService.addTag(folder, tag); taggingService.addTag(folder, tag);
taggingService.addTag(subFolder, tag); taggingService.addTag(subFolder, tag);
taggingService.addTag(subDocument, tag); taggingService.addTag(subDocument, tag);
System.out.println(Thread.currentThread() + " - Tagging"); System.out.println(Thread.currentThread() + " - Tagging");
return null; return null;
} }
}, false, true }, false, true);
); System.out.println(Thread.currentThread() + " - Done tagging");
System.out.println(Thread.currentThread() + " - Done tagging");
} }
}); });
threads.add(t); threads.add(t);
t.start(); t.start();
} }
// Release the threads // Release the threads
Thread.sleep(50); System.out.println("Releasing tagging threads");
for(Thread t : threads) { for (Thread t : threads)
{
t.interrupt(); t.interrupt();
} }
Thread.sleep(100);
System.out.println("Done waiting, proceeding with multi-threaded test");
// Wait for the threads to finish (and they will finish)
// Wait for all the threads to finish working // The threads will generate further asynchronous actions
try { for (Thread t : threads)
// Wait for a maximum of 10 seconds
for(int i=0; i<1000; i++)
{ {
if(actionTrackingService.getAllExecutingActions().size() > 0) t.join();
}
// Now we wait for the asynchronous tag execution to finish
try
{
// Wait for a maximum of 10 seconds
for (int i = 0; i < 1000; i++)
{
if (actionTrackingService.getAllExecutingActions().size() > 0)
{ {
Thread.sleep(10); Thread.sleep(10);
} }
else { else
{
break; break;
} }
} }
} catch(InterruptedException e) {} }
catch (InterruptedException e)
{
}
// Now check that things ended up as planned // Now check that things ended up as planned
tx = this.transactionService.getUserTransaction(); tx = this.transactionService.getUserTransaction();
@@ -1176,18 +1211,12 @@ System.out.println(Thread.currentThread() + " - Done tagging");
TagScope ts1 = this.taggingService.findTagScope(this.folder); TagScope ts1 = this.taggingService.findTagScope(this.folder);
TagScope ts2 = this.taggingService.findTagScope(this.subFolder); TagScope ts2 = this.taggingService.findTagScope(this.subFolder);
assertEquals( assertEquals("Wrong tags on folder tagscope: " + ts1.getTags(), 5, ts1.getTags().size());
"Wrong tags on folder tagscope: " + ts1.getTags(), assertEquals("Wrong tags on folder tagscope: " + ts1.getTags(), 5, ts2.getTags().size());
5, ts1.getTags().size()
);
assertEquals(
"Wrong tags on folder tagscope: " + ts1.getTags(),
5, ts2.getTags().size()
);
// Each tag should crop up 3 times on the folder // Each tag should crop up 3 times on the folder
// and twice for the subfolder // and twice for the subfolder
for(String tag : tags) for (String tag : tags)
{ {
assertEquals(3, ts1.getTag(tag.toLowerCase()).getCount()); assertEquals(3, ts1.getTag(tag.toLowerCase()).getCount());
assertEquals(2, ts2.getTag(tag.toLowerCase()).getCount()); assertEquals(2, ts2.getTag(tag.toLowerCase()).getCount());
@@ -1197,7 +1226,6 @@ System.out.println(Thread.currentThread() + " - Done tagging");
tx.commit(); tx.commit();
} }
private UserTransaction waitForActionExecution(UserTransaction txn) private UserTransaction waitForActionExecution(UserTransaction txn)
throws Exception throws Exception
{ {