Skip to content
Snippets Groups Projects
Commit d213ad4b authored by felmer's avatar felmer
Browse files

SP-357, BIS-242: Bug fixed. Tests refactored to make them faster.

SVN: 27461
parent d6079a0b
No related branches found
No related tags found
No related merge requests found
Showing
with 785 additions and 590 deletions
......@@ -89,6 +89,7 @@ public class RelationshipService implements IRelationshipService
}
sample.setExperiment(experiment);
RelationshipUtils.updateModificationDateAndModifier(experiment, session);
for (DataPE dataset : sample.getDatasets())
{
......
......@@ -67,15 +67,15 @@ public class RelationshipUtils
{
if (stackTraceElement.getClassName().contains("OptimisticLockingTest"))
{
System.err.println("===== UPDATE modification date and modifier ===== "
System.out.println("===== UPDATE modification date and modifier ===== "
+ stackTraceElement.getMethodName());
System.err.println("bean: " + beanOrNull);
System.err.println("user: " + session.tryGetPerson());
System.err.println("\t" + stackTrace[3]);
System.err.println("\t" + stackTrace[4]);
System.err.println("\t" + stackTrace[5]);
System.err.println("\t...");
System.err.println("\t" + stackTraceElement);
System.out.println("bean: " + beanOrNull);
System.out.println("user: " + session.tryGetPerson());
System.out.println("\t" + stackTrace[3]);
System.out.println("\t" + stackTrace[4]);
System.out.println("\t" + stackTrace[5]);
System.out.println("\t...");
System.out.println("\t" + stackTraceElement);
break;
}
}
......
......@@ -42,11 +42,11 @@ public class TimeIntervalChecker extends AssertJUnit
}
/**
* Creates an instance for now minus specified shift in seconds.
* Creates an instance for now minus specified shift in milliseconds.
*/
public TimeIntervalChecker(long shiftInSeconds)
public TimeIntervalChecker(long shiftInMillisecond)
{
notBeforeDate = new Date(System.currentTimeMillis() - shiftInSeconds * 1000);
notBeforeDate = new Date(System.currentTimeMillis() - shiftInMillisecond);
}
/**
......
......@@ -20,41 +20,25 @@ import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.fail;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.testng.annotations.Test;
import ch.systemsx.cisd.common.concurrent.MessageChannel;
import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder;
import ch.systemsx.cisd.common.exception.UserFailureException;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext;
import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener;
import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker;
import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.SampleTypeBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUpdatesDTO;
import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO;
import ch.systemsx.cisd.openbis.generic.shared.dto.NewDataSet;
import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty;
import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO;
import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat;
import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
......@@ -64,36 +48,13 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFa
*/
public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
{
private static final String DATA_STORE_CODE = "STANDARD";
private static final LocatorType LOCATOR_TYPE = new LocatorType(
LocatorType.DEFAULT_LOCATOR_TYPE_CODE);
private static final FileFormatType FILE_FORMAT_TYPE = new FileFormatType("XML");
private static final DataSetType DATA_SET_TYPE = new DataSetType("UNKNOWN");
private static final List<IEntityProperty> NO_PROPERTIES = Collections
.<IEntityProperty> emptyList();
private static final List<NewAttachment> NO_ATTACHMENTS = Collections
.<NewAttachment> emptyList();
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
ExperimentOptimisticLockingTest.class);
private static final String REGISTERED = "registered";
private static final String FIRST_REGISTERED = "First registered";
protected static final String SAMPLE_TYPE_CODE = "NORMAL";
@Test
public void testRegisterExperiment()
{
NewExperiment experiment = experiment(1);
NewExperiment experiment = toolBox.experiment(1);
logIntoCommonClientService();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1000);
genericClientService.registerExperiment(SESSION_KEY, SESSION_KEY, experiment);
......@@ -110,14 +71,14 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
@Test
public void testChangePropertyOfAnExistingExperiment()
{
Experiment experiment = createAndLoadExperiment(1);
Experiment experiment = toolBox.createAndLoadExperiment(1);
String sessionToken = logIntoCommonClientService().getSessionID();
ExperimentUpdatesDTO updates = new ExperimentUpdatesDTO();
updates.setVersion(experiment.getVersion());
updates.setExperimentId(new TechId(experiment));
updates.setProjectIdentifier(createProjectIdentifier(experiment.getProject()
updates.setProjectIdentifier(toolBox.createProjectIdentifier(experiment.getProject()
.getIdentifier()));
updates.setAttachments(NO_ATTACHMENTS);
updates.setAttachments(ToolBox.NO_ATTACHMENTS);
List<IEntityProperty> properties = new ArrayList<IEntityProperty>();
properties.addAll(experiment.getProperties());
properties.get(0).setValue("testChangePropertyOfAnExistingExperiment");
......@@ -126,7 +87,7 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
genericServer.updateExperiment(sessionToken, updates);
Experiment retrievedExperiment = loadExperiment(experiment);
Experiment retrievedExperiment = toolBox.loadExperiment(experiment);
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, retrievedExperiment,
"test");
assertEquals("DESCRIPTION: testChangePropertyOfAnExistingExperiment", retrievedExperiment
......@@ -136,14 +97,15 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
@Test
public void testChangeProjectOfAnExistingExperiment()
{
Experiment experiment = createAndLoadExperiment(1);
assertEquals(project1.getIdentifier(), experiment.getProject().getIdentifier());
Experiment experiment = toolBox.createAndLoadExperiment(1);
assertEquals(toolBox.project1.getIdentifier(), experiment.getProject().getIdentifier());
String sessionToken = logIntoCommonClientService().getSessionID();
ExperimentUpdatesDTO updates = new ExperimentUpdatesDTO();
updates.setVersion(experiment.getVersion());
updates.setExperimentId(new TechId(experiment));
updates.setProjectIdentifier(createProjectIdentifier(project2.getIdentifier()));
updates.setAttachments(NO_ATTACHMENTS);
updates.setProjectIdentifier(toolBox.createProjectIdentifier(toolBox.project2
.getIdentifier()));
updates.setAttachments(ToolBox.NO_ATTACHMENTS);
updates.setProperties(experiment.getProperties());
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
......@@ -153,19 +115,21 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
commonServer.getExperimentInfo(systemSessionToken, new TechId(experiment));
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, retrievedExperiment,
"test");
assertEquals(project2.getIdentifier(), retrievedExperiment.getProject().getIdentifier());
assertEquals(toolBox.project2.getIdentifier(), retrievedExperiment.getProject()
.getIdentifier());
}
@Test
public void testUpdateExperimentWithOldVersion()
{
Experiment experiment = createAndLoadExperiment(1);
Experiment experiment = toolBox.createAndLoadExperiment(1);
String sessionToken = logIntoCommonClientService().getSessionID();
ExperimentUpdatesDTO updates = new ExperimentUpdatesDTO();
updates.setVersion(experiment.getVersion());
updates.setExperimentId(new TechId(experiment));
updates.setProjectIdentifier(createProjectIdentifier(project2.getIdentifier()));
updates.setAttachments(NO_ATTACHMENTS);
updates.setProjectIdentifier(toolBox.createProjectIdentifier(toolBox.project2
.getIdentifier()));
updates.setAttachments(ToolBox.NO_ATTACHMENTS);
updates.setProperties(experiment.getProperties());
genericServer.updateExperiment(sessionToken, updates);
......@@ -180,98 +144,38 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
}
}
@Test
public void testRegisterSamplesForSameExperimentInTwoThreads()
{
final NewExperiment experiment = experiment(1);
genericServer.registerExperiment(systemSessionToken, experiment, NO_ATTACHMENTS);
final MessageChannel messageChannelMain =
new MessageChannelBuilder(10000).name("samples main").logger(operationLog)
.getChannel();
final MessageChannel messageChannelSecond =
new MessageChannelBuilder(10000).name("samples second").logger(operationLog)
.getChannel();
final IServiceConversationProgressListener listener =
new AbstractServiceConversationProgressListener(operationLog)
{
@Override
public void handleProgress(String phaseName, int totalItemsToProcess,
int numItemsProcessed)
{
logger.info(phaseName + " " + numItemsProcessed + "/"
+ totalItemsToProcess);
if (phaseName.equals("createContainerSamples")
&& numItemsProcessed == 1 && totalItemsToProcess == 2)
{
messageChannelMain.send(FIRST_REGISTERED);
}
}
};
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
new Thread(new Runnable()
{
@Override
public void run()
{
NewSample sample3 = sample(3, experiment);
String sessionToken =
genericServer.tryToAuthenticate("test", "a").getSessionToken();
messageChannelMain.assertNextMessage(FIRST_REGISTERED);
genericServer.registerSample(sessionToken, sample3, NO_ATTACHMENTS);
messageChannelSecond.send(REGISTERED);
}
}).start();
ServiceConversationsThreadContext.setProgressListener(listener);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(USER_ID).batchSize(1);
NewSample sample1 = sample(1, experiment);
NewSample sample2 = sample(2, experiment);
builder.sample(sample1).sample(sample2);
etlService.performEntityOperations(systemSessionToken, builder.getDetails());
messageChannelSecond.assertNextMessage(REGISTERED);
Experiment experimentInfo = loadExperiment(experiment);
List<Sample> samples =
commonServer.listSamples(systemSessionToken,
ListSampleCriteria.createForExperiment(new TechId(experimentInfo)));
assertEquals("[OLT-S1, OLT-S2, OLT-S3]", extractCodes(samples).toString());
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, experimentInfo, "test");
}
@Test
public void testMoveSampleBetweenExperiments()
{
Experiment experiment1 = createAndLoadExperiment(1);
Experiment experiment2 = createAndLoadExperiment(2);
NewSample sample = sample(1, experiment1);
genericServer.registerSample(systemSessionToken, sample, NO_ATTACHMENTS);
Sample loadedSample = loadSample(sample);
Experiment experiment1 = toolBox.createAndLoadExperiment(1);
Experiment experiment2 = toolBox.createAndLoadExperiment(2);
NewSample sample = toolBox.sample(1, experiment1);
genericServer.registerSample(systemSessionToken, sample, ToolBox.NO_ATTACHMENTS);
Sample loadedSample = toolBox.loadSample(sample);
SampleUpdatesDTO sampleUpdate =
new SampleUpdatesDTO(new TechId(loadedSample), NO_PROPERTIES,
new SampleUpdatesDTO(new TechId(loadedSample), ToolBox.NO_PROPERTIES,
ExperimentIdentifierFactory.parse(experiment2.getIdentifier()),
NO_ATTACHMENTS, loadedSample.getModificationDate(),
ToolBox.NO_ATTACHMENTS, loadedSample.getModificationDate(),
SampleIdentifierFactory.parse(sample), null, null);
sampleUpdate.setUpdateExperimentLink(true);
AtomicEntityOperationDetails details =
new AtomicEntityOperationDetailsBuilder().user(USER_ID).sampleUpdate(sampleUpdate)
.getDetails();
new AtomicEntityOperationDetailsBuilder().user(ToolBox.USER_ID)
.sampleUpdate(sampleUpdate).getDetails();
String sessionToken = logIntoCommonClientService().getSessionID();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
etlService.performEntityOperations(sessionToken, details);
Experiment loadedExperiment1 = loadExperiment(experiment1);
Experiment loadedExperiment1 = toolBox.loadExperiment(experiment1);
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment1,
USER_ID);
ToolBox.USER_ID);
List<Sample> samples1 =
commonServer.listSamples(systemSessionToken,
ListSampleCriteria.createForExperiment(new TechId(loadedExperiment1)));
assertEquals("[]", samples1.toString());
Experiment loadedExperiment2 = loadExperiment(experiment2);
Experiment loadedExperiment2 = toolBox.loadExperiment(experiment2);
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment2,
USER_ID);
ToolBox.USER_ID);
List<Sample> samples2 =
commonServer.listSamples(systemSessionToken,
ListSampleCriteria.createForExperiment(new TechId(loadedExperiment2)));
......@@ -281,21 +185,22 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
@Test
public void testRemoveSampleFromExperiment()
{
Experiment experiment = createAndLoadExperiment(1);
NewSample sample = sample(1, experiment);
genericServer.registerSample(systemSessionToken, sample, NO_ATTACHMENTS);
Experiment experiment = toolBox.createAndLoadExperiment(1);
NewSample sample = toolBox.sample(1, experiment);
genericServer.registerSample(systemSessionToken, sample, ToolBox.NO_ATTACHMENTS);
ExperimentUpdatesDTO update = new ExperimentUpdatesDTO();
update.setExperimentId(new TechId(experiment));
update.setSampleCodes(new String[0]);
update.setProperties(NO_PROPERTIES);
update.setAttachments(NO_ATTACHMENTS);
update.setProjectIdentifier(createProjectIdentifier(experiment.getProject().getIdentifier()));
update.setProperties(ToolBox.NO_PROPERTIES);
update.setAttachments(ToolBox.NO_ATTACHMENTS);
update.setProjectIdentifier(toolBox.createProjectIdentifier(experiment.getProject()
.getIdentifier()));
String sessionToken = logIntoCommonClientService().getSessionID();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
genericServer.updateExperiment(sessionToken, update);
Experiment loadedExperiment = loadExperiment(experiment);
Experiment loadedExperiment = toolBox.loadExperiment(experiment);
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment, "test");
List<Sample> samples =
commonServer.listSamples(systemSessionToken,
......@@ -306,10 +211,10 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
@Test
public void testMoveDataSetBetweenExperiments()
{
Experiment exp1 = createAndLoadExperiment(1);
Experiment exp2 = createAndLoadExperiment(2);
Experiment exp1 = toolBox.createAndLoadExperiment(1);
Experiment exp2 = toolBox.createAndLoadExperiment(2);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
NewDataSet dataSet = dataSet("DS-1", exp1);
NewDataSet dataSet = toolBox.dataSet("DS-1", exp1);
builder.dataSet(dataSet);
etlService.performEntityOperations(systemSessionToken, builder.getDetails());
List<ExternalData> dataSets =
......@@ -320,80 +225,25 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
update.setDatasetId(new TechId(loadedDataSet));
update.setVersion(loadedDataSet.getModificationDate());
update.setExperimentIdentifierOrNull(ExperimentIdentifierFactory.parse(exp2.getIdentifier()));
update.setProperties(NO_PROPERTIES);
update.setProperties(ToolBox.NO_PROPERTIES);
update.setFileFormatTypeCode(dataSet.getFileFormatType().getCode());
String sessionToken = logIntoCommonClientService().getSessionID();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
genericServer.updateDataSet(sessionToken, update);
Experiment loadedExperiment1 = loadExperiment(exp1);
Experiment loadedExperiment1 = toolBox.loadExperiment(exp1);
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment1, "test");
List<ExternalData> dataSets1 =
etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(exp1));
assertEquals("[]", dataSets1.toString());
Experiment loadedExperiment2 = loadExperiment(exp2);
Experiment loadedExperiment2 = toolBox.loadExperiment(exp2);
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment2, "test");
List<ExternalData> dataSets2 =
etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(exp2));
assertEquals(dataSet.getCode(), dataSets2.get(0).getCode());
}
@Test
public void testRegisterDataSetsForSameExperimentInTwoThreads()
{
final Experiment experiment = createAndLoadExperiment(1);
final MessageChannel messageChannelMain =
new MessageChannelBuilder(10000).name("data sets main").logger(operationLog)
.getChannel();
final MessageChannel messageChannelSecond =
new MessageChannelBuilder(10000).name("data sets second").logger(operationLog)
.getChannel();
final IServiceConversationProgressListener listener =
new AbstractServiceConversationProgressListener(operationLog)
{
@Override
public void handleProgress(String phaseName, int totalItemsToProcess,
int numItemsProcessed)
{
if (phaseName.equals("createDataSets") && numItemsProcessed == 1
&& totalItemsToProcess == 2)
{
messageChannelMain.send(FIRST_REGISTERED);
System.out.println(loadExperiment(experiment).getModifier()
.getUserId());
}
}
};
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
new Thread(new Runnable()
{
@Override
public void run()
{
messageChannelMain.assertNextMessage(FIRST_REGISTERED);
AtomicEntityOperationDetails details =
new AtomicEntityOperationDetailsBuilder().user("test")
.dataSet(dataSet("DS3", experiment)).getDetails();
etlService.performEntityOperations(systemSessionToken, details);
messageChannelSecond.send(REGISTERED);
}
}).start();
ServiceConversationsThreadContext.setProgressListener(listener);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(USER_ID).batchSize(1);
builder.dataSet(dataSet("DS1", experiment)).dataSet(dataSet("DS2", experiment));
etlService.performEntityOperations(systemSessionToken, builder.getDetails());
messageChannelSecond.assertNextMessage(REGISTERED);
Experiment loadedExperiment = loadExperiment(experiment);
List<ExternalData> dataSets =
etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(experiment));
assertEquals("[DS1, DS2, DS3]", extractCodes(dataSets).toString());
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment, "test");
}
private void checkModifierAndModificationDateOfExperiment(
TimeIntervalChecker timeIntervalChecker, Experiment experiment, String userId)
{
......@@ -401,60 +251,4 @@ public class ExperimentOptimisticLockingTest extends OptimisticLockingTestCase
timeIntervalChecker.assertDateInInterval(experiment.getModificationDate());
}
private Experiment createAndLoadExperiment(int number)
{
NewExperiment experiment = experiment(number);
genericServer.registerExperiment(systemSessionToken, experiment, NO_ATTACHMENTS);
return loadExperiment(experiment);
}
private Experiment loadExperiment(final IIdentifierHolder experiment)
{
return commonServer.getExperimentInfo(systemSessionToken,
ExperimentIdentifierFactory.parse(experiment.getIdentifier()));
}
private NewSample sample(int number, IIdentifierHolder experiment)
{
NewSample sample = sample(number);
sample.setExperimentIdentifier(experiment.getIdentifier());
return sample;
}
private NewSample sample(int number)
{
NewSample sample = new NewSample();
sample.setIdentifier("/" + SPACE_1 + "/OLT-S" + number);
sample.setSampleType(new SampleTypeBuilder().code(SAMPLE_TYPE_CODE).getSampleType());
return sample;
}
private Sample loadSample(IIdentifierHolder sample)
{
return etlService.tryGetSampleWithExperiment(systemSessionToken,
SampleIdentifierFactory.parse(sample.getIdentifier()));
}
private NewDataSet dataSet(String code, Experiment experiment)
{
NewDataSet dataSet = dataSet(code);
dataSet.setExperimentIdentifierOrNull(ExperimentIdentifierFactory.parse(experiment
.getIdentifier()));
return dataSet;
}
private NewDataSet dataSet(String code)
{
NewDataSet dataSet = new NewDataSet();
dataSet.setCode(code);
dataSet.setDataSetType(DATA_SET_TYPE);
dataSet.setFileFormatType(FILE_FORMAT_TYPE);
dataSet.setDataSetProperties(Collections.<NewProperty> emptyList());
dataSet.setLocation("a/b/c/" + code);
dataSet.setLocatorType(LOCATOR_TYPE);
dataSet.setStorageFormat(StorageFormat.PROPRIETARY);
dataSet.setDataStoreCode(DATA_STORE_CODE);
return dataSet;
}
}
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.systemtest.optimistic_locking;
import static org.testng.AssertJUnit.assertEquals;
import java.util.List;
import org.apache.log4j.Logger;
import org.testng.annotations.Test;
import ch.systemsx.cisd.common.concurrent.MessageChannel;
import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext;
import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener;
import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker;
import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder;
/**
* @author Franz-Josef Elmer
*/
public class MultiThreadExperimentOptimisticLockingTest extends
MultiThreadOptimisticLockingTestCase
{
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
MultiThreadExperimentOptimisticLockingTest.class);
@Test
public void testRegisterSamplesForSameExperimentInTwoThreads()
{
final NewExperiment experiment = toolBox.experiment(1);
genericServer.registerExperiment(systemSessionToken, experiment, ToolBox.NO_ATTACHMENTS);
final MessageChannel messageChannelMain =
new MessageChannelBuilder(10000).name("samples main").logger(operationLog)
.getChannel();
final MessageChannel messageChannelSecond =
new MessageChannelBuilder(10000).name("samples second").logger(operationLog)
.getChannel();
final IServiceConversationProgressListener listener =
new AbstractServiceConversationProgressListener(operationLog)
{
@Override
public void handleProgress(String phaseName, int totalItemsToProcess,
int numItemsProcessed)
{
logger.info(phaseName + " " + numItemsProcessed + "/"
+ totalItemsToProcess);
if (phaseName.equals("createContainerSamples")
&& numItemsProcessed == 1 && totalItemsToProcess == 2)
{
messageChannelMain.send(ToolBox.FIRST_REGISTERED);
}
}
};
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
new Thread(new Runnable()
{
@Override
public void run()
{
NewSample sample3 = toolBox.sample(3, experiment);
String sessionToken =
genericServer.tryToAuthenticate("test", "a").getSessionToken();
messageChannelMain.assertNextMessage(ToolBox.FIRST_REGISTERED);
genericServer.registerSample(sessionToken, sample3, ToolBox.NO_ATTACHMENTS);
messageChannelSecond.send(ToolBox.REGISTERED);
}
}).start();
ServiceConversationsThreadContext.setProgressListener(listener);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(ToolBox.USER_ID).batchSize(1);
NewSample sample1 = toolBox.sample(1, experiment);
NewSample sample2 = toolBox.sample(2, experiment);
builder.sample(sample1).sample(sample2);
etlService.performEntityOperations(systemSessionToken, builder.getDetails());
messageChannelSecond.assertNextMessage(ToolBox.REGISTERED);
Experiment experimentInfo = toolBox.loadExperiment(experiment);
List<Sample> samples =
commonServer.listSamples(systemSessionToken,
ListSampleCriteria.createForExperiment(new TechId(experimentInfo)));
assertEquals("[OLT-S1, OLT-S2, OLT-S3]", toolBox.extractCodes(samples).toString());
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, experimentInfo, "test");
}
@Test
public void testRegisterDataSetsForSameExperimentInTwoThreads()
{
final Experiment experiment = toolBox.createAndLoadExperiment(1);
final MessageChannel messageChannelMain =
new MessageChannelBuilder(10000).name("data sets main").logger(operationLog)
.getChannel();
final MessageChannel messageChannelSecond =
new MessageChannelBuilder(10000).name("data sets second").logger(operationLog)
.getChannel();
final IServiceConversationProgressListener listener =
new AbstractServiceConversationProgressListener(operationLog)
{
@Override
public void handleProgress(String phaseName, int totalItemsToProcess,
int numItemsProcessed)
{
if (phaseName.equals("createDataSets") && numItemsProcessed == 1
&& totalItemsToProcess == 2)
{
messageChannelMain.send(ToolBox.FIRST_REGISTERED);
}
}
};
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
new Thread(new Runnable()
{
@Override
public void run()
{
messageChannelMain.assertNextMessage(ToolBox.FIRST_REGISTERED);
AtomicEntityOperationDetails details =
new AtomicEntityOperationDetailsBuilder().user("test")
.dataSet(toolBox.dataSet("DS3", experiment)).getDetails();
etlService.performEntityOperations(systemSessionToken, details);
messageChannelSecond.send(ToolBox.REGISTERED);
}
}).start();
ServiceConversationsThreadContext.setProgressListener(listener);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(ToolBox.USER_ID).batchSize(1);
builder.dataSet(toolBox.dataSet("DS1", experiment)).dataSet(
toolBox.dataSet("DS2", experiment));
etlService.performEntityOperations(systemSessionToken, builder.getDetails());
messageChannelSecond.assertNextMessage(ToolBox.REGISTERED);
Experiment loadedExperiment = toolBox.loadExperiment(experiment);
List<ExternalData> dataSets =
etlService.listDataSetsByExperimentID(systemSessionToken, new TechId(experiment));
assertEquals("[DS1, DS2, DS3]", toolBox.extractCodes(dataSets).toString());
checkModifierAndModificationDateOfExperiment(timeIntervalChecker, loadedExperiment, "test");
}
private void checkModifierAndModificationDateOfExperiment(
TimeIntervalChecker timeIntervalChecker, Experiment experiment, String userId)
{
assertEquals(userId, experiment.getModifier().getUserId());
timeIntervalChecker.assertDateInInterval(experiment.getModificationDate());
}
}
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.systemtest.optimistic_locking;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import ch.systemsx.cisd.openbis.systemtest.PersistentSystemTestCase;
/**
* Super class of system test doing commit after each service operation. Can be used to write tests
* with more than one Thread.
*
* @author Franz-Josef Elmer
*/
public class MultiThreadOptimisticLockingTestCase extends PersistentSystemTestCase
{
protected ToolBox toolBox;
@BeforeMethod
public void createSpacesAndProjects()
{
toolBox = new ToolBox(commonServer, genericServer, etlService, systemSessionToken);
toolBox.createSpacesAndProjects();
}
@AfterMethod
public void deleteSpaces()
{
toolBox.deleteSpaces();
}
}
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.systemtest.optimistic_locking;
import static org.testng.AssertJUnit.assertEquals;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.testng.annotations.Test;
import ch.systemsx.cisd.common.concurrent.MessageChannel;
import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext;
import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener;
import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder;
/**
* @author Franz-Josef Elmer
*/
public class MultiThreadProjectOptimisticLockingTest extends MultiThreadOptimisticLockingTestCase
{
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
MultiThreadProjectOptimisticLockingTest.class);
private static final String CREATE_EXPERIMENTS_PHASE = "createExperiments";
/*
* This test registers three experiments for the same project. Two of them are registered by the
* main thread using performEntityOperations(). A second thread registers an experiment between
* the registration of the two other experiments. This is done by using a
* IServiceConversationProgressListener together with two message channels to coordinate the
* order of actions in both threads.
*/
@Test
public void testRegisterExperimentsInTwoThreads()
{
assertEquals("system", toolBox.project1.getModifier().getUserId());
final StringBuilder stringBuilder = new StringBuilder();
final MessageChannel messageChannelMain =
new MessageChannelBuilder(10000).name("main").logger(operationLog).getChannel();
final MessageChannel messageChannelSecond =
new MessageChannelBuilder(10000).name("second").logger(operationLog).getChannel();
final IServiceConversationProgressListener listener =
new AbstractServiceConversationProgressListener(operationLog)
{
@Override
public void handleProgress(String phaseName, int totalItemsToProcess,
int numItemsProcessed)
{
stringBuilder.append(phaseName).append(" ").append(numItemsProcessed)
.append("/").append(totalItemsToProcess).append("\n");
if (phaseName.equals(CREATE_EXPERIMENTS_PHASE)
&& numItemsProcessed == 1 && totalItemsToProcess == 2)
{
messageChannelMain.send(ToolBox.FIRST_REGISTERED);
}
}
};
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
new Thread(new Runnable()
{
@Override
public void run()
{
NewExperiment experiment3 = toolBox.experiment(3);
String sessionToken =
genericServer.tryToAuthenticate("test", "a").getSessionToken();
messageChannelMain.assertNextMessage(ToolBox.FIRST_REGISTERED);
genericServer.registerExperiment(sessionToken, experiment3,
Collections.<NewAttachment> emptyList());
messageChannelSecond.send(ToolBox.REGISTERED);
}
}).start();
ServiceConversationsThreadContext.setProgressListener(listener);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(ToolBox.USER_ID);
builder.experiment(toolBox.experiment(1)).experiment(toolBox.experiment(2));
AtomicEntityOperationDetails details = builder.getDetails();
etlService.performEntityOperations(systemSessionToken, details);
messageChannelSecond.assertNextMessage(ToolBox.REGISTERED);
List<Experiment> experiments =
commonServer.listExperiments(systemSessionToken,
new ExperimentTypeBuilder().code(ToolBox.EXPERIMENT_TYPE_CODE)
.getExperimentType(), toolBox
.createProjectIdentifier(toolBox.project1.getIdentifier()));
assertEquals("[OLT-E1, OLT-E2, OLT-E3]", toolBox.extractCodes(experiments).toString());
toolBox.checkModifierAndModificationDateOfProject1(timeIntervalChecker);
assertEquals("authorize 1/2\n" + "authorize 2/2\n" + "createExperiments 1/2\n"
+ "createExperiments 2/2\n", stringBuilder.toString());
}
}
......@@ -16,221 +16,23 @@
package ch.systemsx.cisd.openbis.systemtest.optimistic_locking;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import ch.systemsx.cisd.openbis.generic.shared.basic.ICodeHolder;
import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PropertyBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifierFactory;
import ch.systemsx.cisd.openbis.systemtest.PersistentSystemTestCase;
import ch.systemsx.cisd.openbis.systemtest.SystemTestCase;
/**
* Super class of system tests with rollback after each test.
*
* @author Franz-Josef Elmer
*/
public class OptimisticLockingTestCase extends PersistentSystemTestCase
public class OptimisticLockingTestCase extends SystemTestCase
{
protected static final String USER_ID = "optimist";
protected static final String SPACE_1 = "OPTIMISTIC_LOCKING_1";
protected static final String SPACE_2 = "OPTIMISTIC_LOCKING_2";
protected static final String EXPERIMENT_TYPE_CODE = "SIRNA_HCS";
protected Space space1;
protected Space space2;
protected Project project1;
protected Project project2;
protected ToolBox toolBox;
@BeforeMethod
public void createSpacesAndProjects()
{
space1 = findOrCreateSpace(SPACE_1);
space2 = findOrCreateSpace(SPACE_2);
project1 = findOrCreateProject("/" + SPACE_1 + "/P1");
project2 = findOrCreateProject("/" + SPACE_2 + "/P2");
createInstanceAdmin(USER_ID);
}
@AfterMethod
public void deleteSpaces()
{
deleteSpace(space1);
deleteSpace(space2);
}
private void deleteSpace(Space space)
{
trashExperiments(space);
trashSamples(space);
emptyTrashCan();
deleteProjects(space);
commonServer.deleteSpaces(systemSessionToken, Arrays.asList(new TechId(space.getId())),
"cleanup");
}
private void deleteProjects(Space space)
{
List<Project> projects = commonServer.listProjects(systemSessionToken);
List<TechId> projectIds = new ArrayList<TechId>();
for (Project project : projects)
{
if (project.getSpace().getCode().equals(space.getCode()))
{
projectIds.add(new TechId(project));
}
}
commonServer.deleteProjects(systemSessionToken, projectIds, "cleanup");
}
private void emptyTrashCan()
{
List<Deletion> deletions = commonServer.listDeletions(systemSessionToken, false);
commonServer.deletePermanently(systemSessionToken, TechId.createList(deletions));
}
private void trashSamples(Space space)
{
ListSampleCriteria criteria = new ListSampleCriteria();
criteria.setSampleType(SampleType.createAllSampleType(Collections.<SampleType> emptyList(),
false));
criteria.setSpaceCode(space.getCode());
criteria.setIncludeSpace(true);
criteria.setIncludeInstance(false);
criteria.setExcludeWithoutExperiment(false);
List<Sample> samples = commonServer.listSamples(systemSessionToken, criteria);
commonServer.deleteSamples(systemSessionToken, TechId.createList(samples), "cleanup",
DeletionType.TRASH);
}
private void trashExperiments(Space space)
{
List<Experiment> experiments =
commonServer.listExperiments(systemSessionToken,
new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(),
new SpaceIdentifierFactory(space.getIdentifier()).createIdentifier());
commonServer.deleteExperiments(systemSessionToken, TechId.createList(experiments),
"cleanup", DeletionType.TRASH);
toolBox = new ToolBox(commonServer, genericServer, etlService, systemSessionToken);
toolBox.createSpacesAndProjects();
}
private void createInstanceAdmin(String userId)
{
List<Person> persons = commonServer.listPersons(systemSessionToken);
for (Person person : persons)
{
if (person.getUserId().equals(userId))
{
return;
}
}
commonServer.registerPerson(systemSessionToken, userId);
commonServer.registerInstanceRole(systemSessionToken, RoleCode.ADMIN,
Grantee.createPerson(userId));
}
protected Project findOrCreateProject(String projectIdentifier)
{
Project project = tryToFindProject(projectIdentifier);
if (project != null)
{
return project;
}
commonServer.registerProject(systemSessionToken, new ProjectIdentifierFactory(
projectIdentifier).createIdentifier(), "A test project", null, Collections
.<NewAttachment> emptyList());
return tryToFindProject(projectIdentifier);
}
protected Project tryToFindProject(String projectIdentifier)
{
List<Project> projects = commonServer.listProjects(systemSessionToken);
for (Project project : projects)
{
if (project.getIdentifier().equals(projectIdentifier))
{
return project;
}
}
return null;
}
protected Space findOrCreateSpace(String spaceCode)
{
Space space = tryToFindSpace(spaceCode);
if (space != null)
{
return space;
}
commonServer.registerSpace(systemSessionToken, spaceCode, "A test space");
return tryToFindSpace(spaceCode);
}
protected Space tryToFindSpace(String spaceCode)
{
DatabaseInstanceIdentifier identifier = new DatabaseInstanceIdentifier(null);
List<Space> spaces = commonServer.listSpaces(systemSessionToken, identifier);
for (Space space : spaces)
{
if (space.getCode().equals(spaceCode))
{
return space;
}
}
return null;
}
protected NewExperiment experiment(int number)
{
NewExperiment experiment =
new NewExperiment(project1.getIdentifier() + "/OLT-E" + number,
EXPERIMENT_TYPE_CODE);
experiment.setAttachments(Collections.<NewAttachment> emptyList());
experiment.setProperties(new IEntityProperty[]
{ new PropertyBuilder("DESCRIPTION").value("hello " + number).getProperty() });
return experiment;
}
protected List<String> extractCodes(List<? extends ICodeHolder> codeHolders)
{
List<String> result = new ArrayList<String>();
for (ICodeHolder codeHolder : codeHolders)
{
result.add(codeHolder.getCode());
}
Collections.sort(result);
return result;
}
protected ProjectIdentifier createProjectIdentifier(String identifier)
{
return new ProjectIdentifierFactory(identifier).createIdentifier();
}
}
......@@ -22,15 +22,8 @@ import static org.testng.AssertJUnit.fail;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.testng.annotations.Test;
import ch.systemsx.cisd.common.concurrent.MessageChannel;
import ch.systemsx.cisd.common.concurrent.MessageChannelBuilder;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.common.conversation.context.ServiceConversationsThreadContext;
import ch.systemsx.cisd.openbis.common.conversation.progress.IServiceConversationProgressListener;
import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException;
import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker;
import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
......@@ -42,7 +35,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ProjectUpdates;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PropertyBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationDetails;
import ch.systemsx.cisd.openbis.generic.shared.dto.builders.AtomicEntityOperationDetailsBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
......@@ -51,32 +43,23 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
*/
public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase
{
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
ProjectOptimisticLockingTest.class);
private static final String REGISTERED = "registered";
private static final String FIRST_REGISTERED = "First registered";
private static final String CREATE_EXPERIMENTS_PHASE = "createExperiments";
@Test
public void testCreateProject()
{
Project project = new Project();
project.setCode("POLT-1");
String identifier = "/" + space1.getCode() + "/POLT-1";
String identifier = "/" + toolBox.space1.getCode() + "/POLT-1";
project.setIdentifier(identifier);
project.setDescription("ProjectOptimisticLockingTest test");
project.setSpace(space1);
project.setSpace(toolBox.space1);
logIntoCommonClientService();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1);
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1000);
commonClientService.registerProject(SESSION_KEY, project);
Project p =
commonServer
.getProjectInfo(systemSessionToken, createProjectIdentifier(identifier));
commonServer.getProjectInfo(systemSessionToken,
toolBox.createProjectIdentifier(identifier));
assertEquals(project.getDescription(), p.getDescription());
assertEquals("test", p.getRegistrator().getUserId());
assertEquals("test", p.getModifier().getUserId());
......@@ -87,7 +70,8 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase
@Test
public void testUpdateProjectAndCheckModificationDateAndModifier()
{
ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier());
ProjectIdentifier projectIdentifier =
toolBox.createProjectIdentifier(toolBox.project1.getIdentifier());
Project p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier);
ProjectUpdates updates = new ProjectUpdates();
updates.setVersion(p.getVersion());
......@@ -96,12 +80,12 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase
updates.setAttachments(Collections.<NewAttachment> emptyList());
updates.setAttachmentSessionKey(SESSION_KEY);
logIntoCommonClientService();
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1);
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
commonClientService.updateProject(updates);
p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier);
assertEquals(project1.getDescription() + " 2", p.getDescription());
assertEquals(toolBox.project1.getDescription() + " 2", p.getDescription());
assertEquals("system", p.getRegistrator().getUserId());
assertEquals("test", p.getModifier().getUserId());
timeIntervalChecker.assertDateInInterval(p.getModificationDate());
......@@ -111,7 +95,8 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase
@Test
public void testUpdateProjectWithOldVersion()
{
ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier());
ProjectIdentifier projectIdentifier =
toolBox.createProjectIdentifier(toolBox.project1.getIdentifier());
Project currentProject = commonServer.getProjectInfo(systemSessionToken, projectIdentifier);
ProjectUpdates updates = new ProjectUpdates();
updates.setVersion(currentProject.getVersion());
......@@ -138,121 +123,37 @@ public class ProjectOptimisticLockingTest extends OptimisticLockingTestCase
{
String sessionToken = logIntoCommonClientService().getSessionID();
NewExperiment experiment =
new NewExperiment(project1.getIdentifier() + "/POLT-1", EXPERIMENT_TYPE_CODE);
new NewExperiment(toolBox.project1.getIdentifier() + "/POLT-1",
ToolBox.EXPERIMENT_TYPE_CODE);
experiment.setAttachments(Collections.<NewAttachment> emptyList());
experiment.setProperties(new IEntityProperty[]
{ new PropertyBuilder("DESCRIPTION").value("hello").getProperty() });
assertEquals("system", project1.getModifier().getUserId());
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1);
assertEquals("system", toolBox.project1.getModifier().getUserId());
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
genericServer.registerExperiment(sessionToken, experiment,
Collections.<NewAttachment> emptyList());
checkModifierAndModificationDateOfProject1(timeIntervalChecker);
toolBox.checkModifierAndModificationDateOfProject1(timeIntervalChecker);
}
@Test
public void testRegisterExperiments()
{
assertEquals("system", project1.getModifier().getUserId());
assertEquals("system", toolBox.project1.getModifier().getUserId());
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(USER_ID);
builder.experiment(experiment(1)).experiment(experiment(2));
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1);
builder.user(ToolBox.USER_ID);
builder.experiment(toolBox.experiment(1)).experiment(toolBox.experiment(2));
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker();
etlService.performEntityOperations(systemSessionToken, builder.getDetails());
List<Experiment> experiments =
commonServer.listExperiments(systemSessionToken,
new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(),
createProjectIdentifier(project1.getIdentifier()));
assertEquals("[OLT-E1, OLT-E2]", extractCodes(experiments).toString());
checkModifierAndModificationDateOfProject1(timeIntervalChecker, USER_ID);
}
/*
* This test registers three experiments for the same project. Two of them are registered by the
* main thread using performEntityOperations(). A second thread registers an experiment between
* the registration of the two other experiments. This is done by using a
* IServiceConversationProgressListener together with two message channels to coordinate the
* order of actions in both threads.
*/
@Test
public void testRegisterExperimentsInTwoThreads()
{
assertEquals("system", project1.getModifier().getUserId());
final StringBuilder stringBuilder = new StringBuilder();
final MessageChannel messageChannelMain =
new MessageChannelBuilder(10000).name("main").logger(operationLog).getChannel();
final MessageChannel messageChannelSecond =
new MessageChannelBuilder(10000).name("second").logger(operationLog).getChannel();
final IServiceConversationProgressListener listener =
new AbstractServiceConversationProgressListener(operationLog)
{
@Override
public void handleProgress(String phaseName, int totalItemsToProcess,
int numItemsProcessed)
{
stringBuilder.append(phaseName).append(" ").append(numItemsProcessed)
.append("/").append(totalItemsToProcess).append("\n");
if (phaseName.equals(CREATE_EXPERIMENTS_PHASE)
&& numItemsProcessed == 1 && totalItemsToProcess == 2)
{
messageChannelMain.send(FIRST_REGISTERED);
}
}
};
TimeIntervalChecker timeIntervalChecker = new TimeIntervalChecker(1);
new Thread(new Runnable()
{
@Override
public void run()
{
NewExperiment experiment3 = experiment(3);
String sessionToken =
genericServer.tryToAuthenticate("test", "a").getSessionToken();
messageChannelMain.assertNextMessage(FIRST_REGISTERED);
genericServer.registerExperiment(sessionToken, experiment3,
Collections.<NewAttachment> emptyList());
messageChannelSecond.send(REGISTERED);
}
}).start();
ServiceConversationsThreadContext.setProgressListener(listener);
AtomicEntityOperationDetailsBuilder builder = new AtomicEntityOperationDetailsBuilder();
builder.user(USER_ID);
builder.experiment(experiment(1)).experiment(experiment(2));
AtomicEntityOperationDetails details = builder.getDetails();
etlService.performEntityOperations(systemSessionToken, details);
messageChannelSecond.assertNextMessage(REGISTERED);
List<Experiment> experiments =
commonServer.listExperiments(systemSessionToken,
new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(),
createProjectIdentifier(project1.getIdentifier()));
assertEquals("[OLT-E1, OLT-E2, OLT-E3]", extractCodes(experiments).toString());
checkModifierAndModificationDateOfProject1(timeIntervalChecker);
assertEquals("authorize 1/2\n" + "authorize 2/2\n" + "createExperiments 1/2\n"
+ "createExperiments 2/2\n", stringBuilder.toString());
new ExperimentTypeBuilder().code(ToolBox.EXPERIMENT_TYPE_CODE)
.getExperimentType(), toolBox
.createProjectIdentifier(toolBox.project1.getIdentifier()));
assertEquals("[OLT-E1, OLT-E2]", toolBox.extractCodes(experiments).toString());
toolBox.checkModifierAndModificationDateOfProject1(timeIntervalChecker, ToolBox.USER_ID);
}
private void checkModifierAndModificationDateOfProject1(TimeIntervalChecker timeIntervalChecker)
{
checkModifierAndModificationDateOfProject1(timeIntervalChecker, "test");
}
private void checkModifierAndModificationDateOfProject1(
TimeIntervalChecker timeIntervalChecker, String modifier)
{
ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier());
Project p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier);
assertEquals("system", p.getRegistrator().getUserId());
assertEquals(project1.getRegistrationDate(), p.getRegistrationDate());
assertEquals(modifier, p.getModifier().getUserId());
timeIntervalChecker.assertDateInInterval(p.getModificationDate());
}
}
/*
* Copyright 2012 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.systemsx.cisd.openbis.systemtest.optimistic_locking;
import static org.testng.AssertJUnit.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import ch.systemsx.cisd.openbis.generic.server.util.TimeIntervalChecker;
import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
import ch.systemsx.cisd.openbis.generic.shared.basic.ICodeHolder;
import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Deletion;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Experiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentTypeBuilder;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.PropertyBuilder;
import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.SampleTypeBuilder;
import ch.systemsx.cisd.openbis.generic.shared.dto.NewDataSet;
import ch.systemsx.cisd.openbis.generic.shared.dto.NewProperty;
import ch.systemsx.cisd.openbis.generic.shared.dto.StorageFormat;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory;
import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifierFactory;
import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer;
/**
* @author Franz-Josef Elmer
*/
public class ToolBox
{
public static final String USER_ID = "optimist";
public static final String SPACE_1 = "OPTIMISTIC_LOCKING_1";
public static final String SPACE_2 = "OPTIMISTIC_LOCKING_2";
public static final String EXPERIMENT_TYPE_CODE = "SIRNA_HCS";
public static final String SAMPLE_TYPE_CODE = "NORMAL";
public static final String DATA_STORE_CODE = "STANDARD";
public static final String REGISTERED = "registered";
public static final String FIRST_REGISTERED = "First registered";
public static final List<IEntityProperty> NO_PROPERTIES = Collections
.<IEntityProperty> emptyList();
public static final List<NewAttachment> NO_ATTACHMENTS = Collections
.<NewAttachment> emptyList();
private static final LocatorType LOCATOR_TYPE = new LocatorType(
LocatorType.DEFAULT_LOCATOR_TYPE_CODE);
private static final FileFormatType FILE_FORMAT_TYPE = new FileFormatType("XML");
private static final DataSetType DATA_SET_TYPE = new DataSetType("UNKNOWN");
private final ICommonServer commonServer;
private final IGenericServer genericServer;
private final IETLLIMSService etlService;
private final String systemSessionToken;
public Space space1;
public Space space2;
public Project project1;
public Project project2;
public ToolBox(ICommonServer commonServer, IGenericServer genericServer,
IETLLIMSService etlService, String systemSessionToken)
{
this.commonServer = commonServer;
this.genericServer = genericServer;
this.etlService = etlService;
this.systemSessionToken = systemSessionToken;
}
void createSpacesAndProjects()
{
space1 = findOrCreateSpace(SPACE_1);
space2 = findOrCreateSpace(SPACE_2);
project1 = findOrCreateProject("/" + SPACE_1 + "/P1");
project2 = findOrCreateProject("/" + SPACE_2 + "/P2");
createInstanceAdmin(USER_ID);
}
void deleteSpaces()
{
deleteSpace(space1);
deleteSpace(space2);
}
private void deleteSpace(Space space)
{
trashExperiments(space);
trashSamples(space);
emptyTrashCan();
deleteProjects(space);
commonServer.deleteSpaces(systemSessionToken, Arrays.asList(new TechId(space.getId())),
"cleanup");
}
private void deleteProjects(Space space)
{
List<Project> projects = commonServer.listProjects(systemSessionToken);
List<TechId> projectIds = new ArrayList<TechId>();
for (Project project : projects)
{
if (project.getSpace().getCode().equals(space.getCode()))
{
projectIds.add(new TechId(project));
}
}
commonServer.deleteProjects(systemSessionToken, projectIds, "cleanup");
}
private void emptyTrashCan()
{
List<Deletion> deletions = commonServer.listDeletions(systemSessionToken, false);
commonServer.deletePermanently(systemSessionToken, TechId.createList(deletions));
}
private void trashSamples(Space space)
{
ListSampleCriteria criteria = new ListSampleCriteria();
criteria.setSampleType(SampleType.createAllSampleType(Collections.<SampleType> emptyList(),
false));
criteria.setSpaceCode(space.getCode());
criteria.setIncludeSpace(true);
criteria.setIncludeInstance(false);
criteria.setExcludeWithoutExperiment(false);
List<Sample> samples = commonServer.listSamples(systemSessionToken, criteria);
commonServer.deleteSamples(systemSessionToken, TechId.createList(samples), "cleanup",
DeletionType.TRASH);
}
private void trashExperiments(Space space)
{
List<Experiment> experiments =
commonServer.listExperiments(systemSessionToken,
new ExperimentTypeBuilder().code(EXPERIMENT_TYPE_CODE).getExperimentType(),
new SpaceIdentifierFactory(space.getIdentifier()).createIdentifier());
commonServer.deleteExperiments(systemSessionToken, TechId.createList(experiments),
"cleanup", DeletionType.TRASH);
}
public void createInstanceAdmin(String userId)
{
List<Person> persons = commonServer.listPersons(systemSessionToken);
for (Person person : persons)
{
if (person.getUserId().equals(userId))
{
return;
}
}
commonServer.registerPerson(systemSessionToken, userId);
commonServer.registerInstanceRole(systemSessionToken, RoleCode.ADMIN,
Grantee.createPerson(userId));
}
public Project findOrCreateProject(String projectIdentifier)
{
Project project = tryToFindProject(projectIdentifier);
if (project != null)
{
return project;
}
commonServer.registerProject(systemSessionToken, new ProjectIdentifierFactory(
projectIdentifier).createIdentifier(), "A test project", null, Collections
.<NewAttachment> emptyList());
return tryToFindProject(projectIdentifier);
}
public Project tryToFindProject(String projectIdentifier)
{
List<Project> projects = commonServer.listProjects(systemSessionToken);
for (Project project : projects)
{
if (project.getIdentifier().equals(projectIdentifier))
{
return project;
}
}
return null;
}
public Space findOrCreateSpace(String spaceCode)
{
Space space = tryToFindSpace(spaceCode);
if (space != null)
{
return space;
}
commonServer.registerSpace(systemSessionToken, spaceCode, "A test space");
return tryToFindSpace(spaceCode);
}
public Space tryToFindSpace(String spaceCode)
{
DatabaseInstanceIdentifier identifier = new DatabaseInstanceIdentifier(null);
List<Space> spaces = commonServer.listSpaces(systemSessionToken, identifier);
for (Space space : spaces)
{
if (space.getCode().equals(spaceCode))
{
return space;
}
}
return null;
}
NewExperiment experiment(int number)
{
NewExperiment experiment =
new NewExperiment(project1.getIdentifier() + "/OLT-E" + number,
EXPERIMENT_TYPE_CODE);
experiment.setAttachments(Collections.<NewAttachment> emptyList());
experiment.setProperties(new IEntityProperty[]
{ new PropertyBuilder("DESCRIPTION").value("hello " + number).getProperty() });
return experiment;
}
public List<String> extractCodes(List<? extends ICodeHolder> codeHolders)
{
List<String> result = new ArrayList<String>();
for (ICodeHolder codeHolder : codeHolders)
{
result.add(codeHolder.getCode());
}
Collections.sort(result);
return result;
}
public ProjectIdentifier createProjectIdentifier(String identifier)
{
return new ProjectIdentifierFactory(identifier).createIdentifier();
}
public Experiment createAndLoadExperiment(int number)
{
NewExperiment experiment = experiment(number);
genericServer.registerExperiment(systemSessionToken, experiment, NO_ATTACHMENTS);
return loadExperiment(experiment);
}
public Experiment loadExperiment(final IIdentifierHolder experiment)
{
return commonServer.getExperimentInfo(systemSessionToken,
ExperimentIdentifierFactory.parse(experiment.getIdentifier()));
}
public NewSample sample(int number, IIdentifierHolder experiment)
{
NewSample sample = sample(number);
sample.setExperimentIdentifier(experiment.getIdentifier());
return sample;
}
public NewSample sample(int number)
{
NewSample sample = new NewSample();
sample.setIdentifier("/" + ToolBox.SPACE_1 + "/OLT-S" + number);
sample.setSampleType(new SampleTypeBuilder().code(SAMPLE_TYPE_CODE).getSampleType());
return sample;
}
public Sample loadSample(IIdentifierHolder sample)
{
return etlService.tryGetSampleWithExperiment(systemSessionToken,
SampleIdentifierFactory.parse(sample.getIdentifier()));
}
public NewDataSet dataSet(String code, Experiment experiment)
{
NewDataSet dataSet = dataSet(code);
dataSet.setExperimentIdentifierOrNull(ExperimentIdentifierFactory.parse(experiment
.getIdentifier()));
return dataSet;
}
private NewDataSet dataSet(String code)
{
NewDataSet dataSet = new NewDataSet();
dataSet.setCode(code);
dataSet.setDataSetType(DATA_SET_TYPE);
dataSet.setFileFormatType(FILE_FORMAT_TYPE);
dataSet.setDataSetProperties(Collections.<NewProperty> emptyList());
dataSet.setLocation("a/b/c/" + code);
dataSet.setLocatorType(LOCATOR_TYPE);
dataSet.setStorageFormat(StorageFormat.PROPRIETARY);
dataSet.setDataStoreCode(DATA_STORE_CODE);
return dataSet;
}
public void checkModifierAndModificationDateOfProject1(TimeIntervalChecker timeIntervalChecker)
{
checkModifierAndModificationDateOfProject1(timeIntervalChecker, "test");
}
public void checkModifierAndModificationDateOfProject1(TimeIntervalChecker timeIntervalChecker,
String modifier)
{
ProjectIdentifier projectIdentifier = createProjectIdentifier(project1.getIdentifier());
Project p = commonServer.getProjectInfo(systemSessionToken, projectIdentifier);
assertEquals("system", p.getRegistrator().getUserId());
assertEquals(project1.getRegistrationDate(), p.getRegistrationDate());
assertEquals(modifier, p.getModifier().getUserId());
timeIntervalChecker.assertDateInInterval(p.getModificationDate());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment