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,7 +167,14 @@ 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);
return (List<AVMStorePropertyEntity>) template.queryForList(SELECT_AVM_STORE_PROPS, params); try
{
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")

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,109 +1112,120 @@ 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();
this.taggingService.addTagScope(this.folder); this.taggingService.addTagScope(this.folder);
this.taggingService.addTagScope(this.subFolder); this.taggingService.addTagScope(this.subFolder);
tx.commit(); tx.commit();
// Prepare a bunch of threads to do tagging
final List<Thread> threads = new ArrayList<Thread>();
String[] tags = new String[] { TAG_1, TAG_2, TAG_3, TAG_4, TAG_5 };
for(String tmpTag : tags)
{
final String tag = tmpTag;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// Let everything catch up
try {
Thread.sleep(250);
} catch(InterruptedException e) {}
System.out.println(Thread.currentThread() + " - About to start tagging");
// Do the updates
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
taggingService.addTag(folder, tag);
taggingService.addTag(subFolder, tag);
taggingService.addTag(subDocument, tag);
System.out.println(Thread.currentThread() + " - Tagging");
return null;
}
}, false, true
);
System.out.println(Thread.currentThread() + " - Done tagging");
}
});
threads.add(t);
t.start();
}
// Release the threads
Thread.sleep(50);
for(Thread t : threads) {
t.interrupt();
}
Thread.sleep(100);
System.out.println("Done waiting, proceeding with multi-threaded test");
// Prepare a bunch of threads to do tagging
// Wait for all the threads to finish working final List<Thread> threads = new ArrayList<Thread>();
try { String[] tags = new String[] { TAG_1, TAG_2, TAG_3, TAG_4, TAG_5 };
// Wait for a maximum of 10 seconds for (String tmpTag : tags)
for(int i=0; i<1000; i++) {
{ final String tag = tmpTag;
if(actionTrackingService.getAllExecutingActions().size() > 0) Thread t = new Thread(new Runnable()
{ {
Thread.sleep(10); @Override
} public synchronized void run()
else { {
break; // Let everything catch up
} try
} {
} catch(InterruptedException e) {} wait();
}
catch (InterruptedException e)
// Now check that things ended up as planned {
tx = this.transactionService.getUserTransaction(); }
tx.begin(); System.out.println(Thread.currentThread() + " - About to start tagging");
TagScope ts1 = this.taggingService.findTagScope(this.folder); // Do the updates
TagScope ts2 = this.taggingService.findTagScope(this.subFolder); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
assertEquals( transactionService.getRetryingTransactionHelper().doInTransaction(
"Wrong tags on folder tagscope: " + ts1.getTags(), new RetryingTransactionCallback<Void>()
5, ts1.getTags().size() {
); public Void execute() throws Throwable
assertEquals( {
"Wrong tags on folder tagscope: " + ts1.getTags(), taggingService.addTag(folder, tag);
5, ts2.getTags().size() taggingService.addTag(subFolder, tag);
); taggingService.addTag(subDocument, tag);
System.out.println(Thread.currentThread() + " - Tagging");
// Each tag should crop up 3 times on the folder return null;
// and twice for the subfolder }
for(String tag : tags) }, false, true);
{ System.out.println(Thread.currentThread() + " - Done tagging");
assertEquals(3, ts1.getTag(tag.toLowerCase()).getCount()); }
assertEquals(2, ts2.getTag(tag.toLowerCase()).getCount()); });
} threads.add(t);
t.start();
// All done }
tx.commit();
// Release the threads
System.out.println("Releasing tagging threads");
for (Thread t : threads)
{
t.interrupt();
}
// Wait for the threads to finish (and they will finish)
// The threads will generate further asynchronous actions
for (Thread t : threads)
{
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);
}
else
{
break;
}
}
}
catch (InterruptedException e)
{
}
// Now check that things ended up as planned
tx = this.transactionService.getUserTransaction();
tx.begin();
TagScope ts1 = this.taggingService.findTagScope(this.folder);
TagScope ts2 = this.taggingService.findTagScope(this.subFolder);
assertEquals("Wrong tags on folder tagscope: " + ts1.getTags(), 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
// and twice for the subfolder
for (String tag : tags)
{
assertEquals(3, ts1.getTag(tag.toLowerCase()).getCount());
assertEquals(2, ts2.getTag(tag.toLowerCase()).getCount());
}
// All done
tx.commit();
} }
private UserTransaction waitForActionExecution(UserTransaction txn) private UserTransaction waitForActionExecution(UserTransaction txn)
throws Exception throws Exception
{ {