1 /*****************************************************************************
5 * Creation date 12 Oct 2012
8 *****************************************************************************/
9 package test.splat.service;
11 import java.io.FileNotFoundException;
12 import java.io.IOException;
13 import java.sql.SQLException;
14 import java.util.Date;
15 import java.util.HashMap;
16 import java.util.List;
19 import org.splat.dal.bo.kernel.User;
20 import org.splat.dal.bo.som.ContributorRelation;
21 import org.splat.dal.bo.som.DescriptionAttribute;
22 import org.splat.dal.bo.som.Document;
23 import org.splat.dal.bo.som.DocumentType;
24 import org.splat.dal.bo.som.KnowledgeElement;
25 import org.splat.dal.bo.som.KnowledgeElementType;
26 import org.splat.dal.bo.som.ProgressState;
27 import org.splat.dal.bo.som.ProjectElement;
28 import org.splat.dal.bo.som.Publication;
29 import org.splat.dal.bo.som.Scenario;
30 import org.splat.dal.bo.som.SimulationContext;
31 import org.splat.dal.bo.som.Study;
32 import org.splat.dal.bo.som.ValidationCycle;
33 import org.splat.dal.bo.som.ValidationCycleRelation;
34 import org.splat.dal.bo.som.ValidationStep;
35 import org.splat.dal.bo.som.Document.Properties;
36 import org.splat.dal.dao.kernel.UserDAO;
37 import org.splat.dal.dao.som.Database;
38 import org.splat.dal.dao.som.KnowledgeElementDAO;
39 import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
40 import org.splat.dal.dao.som.ScenarioDAO;
41 import org.splat.dal.dao.som.StudyDAO;
42 import org.splat.dal.dao.som.ValidationCycleDAO;
43 import org.splat.exception.BusinessException;
44 import org.splat.exception.InvalidParameterException;
45 import org.splat.kernel.InvalidPropertyException;
46 import org.splat.kernel.MissedPropertyException;
47 import org.splat.kernel.MultiplyDefinedException;
48 import org.splat.log.AppLogger;
49 import org.splat.service.DocumentTypeService;
50 import org.splat.service.PublicationService;
51 import org.splat.service.SimulationContextService;
52 import org.splat.service.StepService;
53 import org.splat.service.StudyService;
54 import org.splat.service.technical.ProjectSettingsService;
55 import org.splat.service.technical.ProjectSettingsService.Step;
56 import org.springframework.beans.factory.annotation.Autowired;
57 import org.springframework.beans.factory.annotation.Qualifier;
58 import org.springframework.orm.hibernate3.HibernateTemplate;
59 import org.testng.Assert;
60 import org.testng.annotations.Test;
62 import test.splat.common.BaseTest;
63 import test.splat.util.TestEntitiesGenerator;
66 * Test class for StudyService.
68 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
71 public class TestStudyService extends BaseTest {
74 * Logger for the class.
76 private static final AppLogger LOG = AppLogger
77 .getLogger(TestStudyService.class);
80 * The StudyDAO. Later injected by Spring.
83 @Qualifier("studyDAO")
84 private transient StudyDAO _studyDAO;
87 * The PublicationService. Later injected by Spring.
90 @Qualifier("publicationService")
91 private transient PublicationService _publicationService;
94 * The StepService. Later injected by Spring.
97 @Qualifier("stepService")
98 private transient StepService _stepService;
101 * The ProjectSettingsService. Later injected by Spring.
104 @Qualifier("projectSettings")
105 private transient ProjectSettingsService _projectSettings;
108 * The DocumentTypeService. Later injected by Spring.
111 @Qualifier("documentTypeService")
112 private transient DocumentTypeService _documentTypeService;
115 * The StudyService. Later injected by Spring.
118 @Qualifier("studyService")
119 private transient StudyService _studyService;
122 * The UserDAO. Later injected by Spring.
125 @Qualifier("userDAO")
126 private transient UserDAO _userDAO;
129 * The KnowledgeElementDAO. Later injected by Spring.
132 @Qualifier("knowledgeElementDAO")
133 private transient KnowledgeElementDAO _knowledgeElementDAO;
136 * The KnowledgeElementTypeDAO. Later injected by Spring.
139 @Qualifier("knowledgeElementTypeDAO")
140 private transient KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
143 * The ScenarioDAO. Later injected by Spring.
146 @Qualifier("scenarioDAO")
147 private transient ScenarioDAO _scenarioDAO;
150 * The SimulationContextService. Later injected by Spring.
153 @Qualifier("simulationContextService")
154 private transient SimulationContextService _simulationContextService;
157 * The ValidationCycleDAO. Later injected by Spring.
160 @Qualifier("validationCycleDAO")
161 private transient ValidationCycleDAO _validationCycleDAO;
164 * Create a persistent scenario for tests.
166 * @return a persistent scenario
167 * @throws InvalidPropertyException
168 * if an invalid property is used when creating objects
169 * @throws MultiplyDefinedException
170 * when trying to create an object with already existing id
171 * @throws MissedPropertyException
172 * if a mandatory property is not defined for an object to be created
173 * @throws IOException
174 * if document creation is failed
175 * @throws SQLException
176 * if project settings loading is failed
178 private Study createStudy() throws InvalidPropertyException,
179 MissedPropertyException, MultiplyDefinedException, IOException,
181 // Create a scenario for tests
182 HibernateTemplate ht = getHibernateTemplate();
184 Database.getInstance().reset();
185 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
186 // Load workflow customization
188 _projectSettings.configure("classpath:test/som.xml");
189 } catch (FileNotFoundException e) {
190 Assert.fail("Can't find som.xml: ", e);
192 List<Step> steps = _projectSettings.getAllSteps();
193 Assert.assertTrue(steps.size() > 0, "No steps are created.");
195 // Create a test user
196 User.Properties uprop = new User.Properties();
197 uprop.setUsername("TST_Username").setName("TST_SimanUnitTestsUser")
198 .setFirstName("TST_FirstName").setDisplayName("TST_test.user")
199 .addRole("TST_user").setMailAddress(
200 "noreply@salome-platform.org");
201 uprop.disableCheck();
202 User anAuthor = new User(uprop);
203 ht.saveOrUpdate(anAuthor);
205 // Create a test study
206 Study.Properties stprops = new Study.Properties().setReference(
207 "TST_SID_01").setTitle("TST_Study").setManager(anAuthor);
208 Study aStudy = new Study(stprops);
209 ht.saveOrUpdate(aStudy);
211 // Create a test scenario
212 Scenario.Properties sprops = new Scenario.Properties().setTitle(
213 "TST_Scenario").setManager(anAuthor).setOwnerStudy(aStudy);
214 Scenario aScenario = new Scenario(sprops);
215 aStudy.getScenariiList().add(aScenario);
216 ht.saveOrUpdate(anAuthor);
217 ht.saveOrUpdate(aStudy);
218 ht.saveOrUpdate(aScenario);
220 // Create documents for each scenario step
221 Document.Properties dprop = new Document.Properties().setAuthor(
222 anAuthor).setDate(new Date());
224 Publication usedPub = null;
225 Map<Long, Long> usedMap = new HashMap<Long, Long>();
226 for (int stepNum = 1; stepNum <= steps.size(); stepNum++) {
227 Step step = _projectSettings.getStep(stepNum);
228 LOG.debug("Create scenario step: " + stepNum);
229 ProjectElement projElem;
231 if (step.appliesTo(Study.class)) {
234 projElem = aScenario;
236 org.splat.som.Step aScStep = new org.splat.som.Step(step, projElem);
237 List<DocumentType> dtypes = _documentTypeService
238 .selectTypesOf(step);
239 if (dtypes.size() > 0) {
240 DocumentType dtype = dtypes.get(0);
241 // Create a document published in the scenario
242 // document<i>: document type[0] - first type used on the step
243 // <source-file>.brep
244 // <attached-file>.med
246 dprop.setName("document" + stepNum).setType(dtype);
247 if (step.getNumber() > 3) {
248 dprop.setFormat("med");
250 dprop.setFormat("py");
252 Publication pub = createDoc(projElem, aScStep, dprop, "med",
254 if (usedPub != null) {
255 pub.addDependency(usedPub);
256 LOG.debug("Add dependency: " + pub.value().getTitle()
257 + " from " + usedPub.value().getTitle());
258 ht.saveOrUpdate(pub.value());
261 usedMap.put(pub.getIndex(), usedPub.getIndex());
265 if (dtypes.size() <= 0) {
266 LOG.debug("No document types are found for scenario step " + i);
270 // Check that the scenario and its documents have been created correctly.
272 Assert.assertNotNull(ht.find("from Document"),
273 "No documents in the database.");
274 Assert.assertTrue(ht.find("from Document").size() > 0,
275 "No documents in the database.");
277 Assert.assertNotNull(ht.find("from Publication where owner="
278 + aScenario.getIndex()), "No publications in the database.");
280 ht.find("from Publication where owner=" + aScenario.getIndex())
281 .size() > 0, "No publications in the database.");
283 for (Publication p : (List<Publication>) ht
284 .find("from Publication where owner=" + aScenario.getIndex())) {
285 LOG.debug("Publication found: [id=" + p.getIndex() + ", owner="
286 + p.getOwner().getIndex() + ", doc=" + p.value().getIndex()
288 Assert.assertEquals(p.getOwner().getIndex(), aScenario.getIndex(),
289 "The publication was not attached to the scenario.");
292 // Remove the scenario from the current hibernate session.
294 // Check that the scenario is created in the database.
295 Scenario aScen = ht.load(Scenario.class, aScenario.getIndex());
296 Assert.assertNotNull(aScen, "Scenario was not saved in the database.");
297 Assert.assertTrue(aScen.getDocums().size() > 0,
298 "No publications in the scenario.");
300 Assert.assertTrue(i > 0,
301 "More then one document must be in the database");
303 // Check created uses relations
305 .assertTrue(usedMap.size() > 0,
306 "Uses relations must be created.");
307 boolean foundAny = false;
308 for (Long usingId : usedMap.keySet()) {
309 for (Publication pub : aScen.getDocums()) {
310 if (pub.getIndex() == usingId) {
311 boolean found = false;
312 for (Publication used : aScen.getDocums()) {
313 found = (used.getIndex() == usedMap.get(usingId));
319 for (Publication used : aStudy.getDocums()) {
320 found = (used.getIndex() == usedMap.get(usingId));
326 Assert.assertTrue(found,
327 "Uses relation was not created in the database.");
328 foundAny = foundAny || found;
332 Assert.assertTrue(foundAny,
333 "No Uses relation was created in the database.");
335 return aScenario.getOwnerStudy();
339 * Create a document published in the scenario. <BR>
341 * document type - type used on the step <BR>
342 * <source-file>.brep <BR>
343 * <attached-file>.med
346 * the scenario to add the document to
348 * scenario step where the document to be published
350 * document properties
351 * @param attachedFileExt
352 * extension of the secon attached (exported) file
354 * outdated document flag
355 * @return the publication of the created document
356 * @throws IOException
357 * @throws MultiplyDefinedException
358 * @throws InvalidPropertyException
359 * @throws MissedPropertyException
361 private Publication createDoc(final ProjectElement aScenario,
362 final org.splat.som.Step aScStep, final Properties dprop,
363 final String attachedFileExt, final boolean isOutdated)
364 throws MissedPropertyException, InvalidPropertyException,
365 MultiplyDefinedException, IOException {
366 // Create a document published in the scenario
367 // document<i>: document type - type used on the step
368 // <source-file>.brep
369 // <attached-file>.med
370 Publication pub = _stepService.createDocument(aScStep, dprop);
371 Assert.assertNotNull(pub.getOwner(),
372 "The publication must be attached to the scenario.");
373 Assert.assertEquals(pub.getOwner().getIndex(), aScenario.getIndex(),
374 "The publication was not attached to the scenario.");
380 HibernateTemplate ht = getHibernateTemplate();
381 ht.saveOrUpdate(pub);
384 ht.save(pub.value());
386 ht.saveOrUpdate(_publicationService.attach(pub, attachedFileExt));
392 * Test of generating a study document index.<BR>
393 * <B>Description :</B> <BR>
394 * <i>Create a study and try to generate the next document index.</i><BR>
395 * <B>Action : </B><BR>
396 * <i>1. call DAO's read method for an existing id.</i><BR>
397 * <B>Test data : </B><BR>
398 * <i>no input parameters</i><BR>
400 * <B>Outcome results:</B><BR>
403 * <li>The new index must be equal to the incremented old one and saved into the database<BR>
408 * @throws InvalidPropertyException
409 * if an invalid property is used when creating objects
410 * @throws MultiplyDefinedException
411 * when trying to create an object with already existing id
412 * @throws MissedPropertyException
413 * if a mandatory property is not defined for an object to be created
414 * @throws SQLException
415 * if test study creation is failed
416 * @throws IOException
417 * if test study creation is failed
421 public void testGenerateLocalIndex() throws InvalidPropertyException,
422 MissedPropertyException, MultiplyDefinedException, IOException,
424 LOG.debug(">>>>> BEGIN testGenerateLocalIndex()");
425 startNestedTransaction();
427 HibernateTemplate ht = getHibernateTemplate();
428 Study aStudy = createStudy();
429 // Call DAO's create method for a good transient study.
430 Long id = aStudy.getIndex();
431 Assert.assertNotNull(id,
432 "Create method returns null instead of a new id.");
433 Assert.assertTrue(id > 0, "The new id is not a positive number.");
435 // Call DAO's get method for an existing id.
437 getHibernateTemplate().evict(aStudy);
438 getHibernateTemplate().clear();
439 Study aStudyFound = _studyDAO.get(id);
441 int oldInd = aStudyFound.getLastLocalIndex();
442 int ind = _studyService.generateLocalIndex(aStudyFound);
445 Assert.assertEquals(ind, oldInd + 1, "Index must be incremented.");
446 Assert.assertEquals(ind, aStudyFound.getLastLocalIndex(),
447 "Index must be incremented.");
448 Assert.assertEquals(ind, ht.get(Study.class, aStudyFound.getIndex())
449 .getLastLocalIndex(),
450 "Incremented index must be saved in the database.");
451 aStudy = (Study) ht.find(
452 "from Study where rid = " + aStudyFound.getIndex()).get(0);
453 Assert.assertEquals(ind, aStudy.getLastLocalIndex(),
454 "Incremented index must be saved in the database.");
456 rollbackNestedTransaction();
457 LOG.debug(">>>>> END testGenerateLocalIndex()");
461 * Test of retrieval of a study description.
463 * @throws BusinessException
464 * if there is something wrong likely unrelated to the tested method
467 public void testGetDescription() throws BusinessException {
468 LOG.debug(">>>>> BEGIN testGetDescription()");
469 startNestedTransaction();
471 User user = TestEntitiesGenerator.getTestUser("GoodUser");
472 _userDAO.create(user);
473 Study study = TestEntitiesGenerator.getTestStudy(user);
474 _studyDAO.create(study);
476 Long studyId = Long.valueOf(study.getIndex());
478 // Empty description:
479 Assert.assertNull(_studyService.getDescription(studyId),
480 "returned value for study without description must be null");
482 // Not empty description:
483 study.setAttribute(new DescriptionAttribute(study, "description"));
484 _studyDAO.update(study);
486 Assert.assertEquals("description", _studyService
487 .getDescription(studyId));
491 _studyService.getDescription(null);
492 Assert.fail("retrieval with null study id must fail");
493 } catch (InvalidParameterException e) {
494 LOG.debug("Expected exception is thrown: "
495 + e.getClass().getSimpleName() + ": " + e.getMessage());
499 Study tmpStudy = TestEntitiesGenerator.getTestStudy(user);
500 _studyDAO.create(tmpStudy);
501 Long nonExistingId = tmpStudy.getIndex();
502 _studyDAO.delete(tmpStudy);
504 _studyService.getDescription(nonExistingId);
505 Assert.fail("retrieval with non-existing study id must fail");
506 } catch (InvalidParameterException e) {
507 LOG.debug("Expected exception is thrown: "
508 + e.getClass().getSimpleName() + ": " + e.getMessage());
511 rollbackNestedTransaction();
512 LOG.debug(">>>>> END testGetDescription()");
516 * Test of setting of a study description.
518 * @throws BusinessException
519 * if there is something wrong likely unrelated to the tested method
522 public void testSetDescription() throws BusinessException {
523 LOG.debug(">>>>> BEGIN testSetDescription()");
524 startNestedTransaction();
526 User user = TestEntitiesGenerator.getTestUser("GoodUser");
527 _userDAO.create(user);
528 Study study = TestEntitiesGenerator.getTestStudy(user);
529 _studyDAO.create(study);
531 Long studyId = Long.valueOf(study.getIndex());
533 // Setting description for study without any
534 _studyService.setDescription(studyId, "description");
536 // Resetting description
537 _studyService.setDescription(studyId, "replaced description");
541 _studyService.setDescription(null, "description");
542 Assert.fail("setting with null study id must fail");
543 } catch (InvalidParameterException e) {
544 LOG.debug("Expected exception is thrown: "
545 + e.getClass().getSimpleName() + ": " + e.getMessage());
549 Study tmpStudy = TestEntitiesGenerator.getTestStudy(user);
550 _studyDAO.create(tmpStudy);
551 Long nonExistingId = tmpStudy.getIndex();
552 _studyDAO.delete(tmpStudy);
555 _studyService.setDescription(nonExistingId, "description");
556 Assert.fail("retrieval with non-existing study id must fail");
557 } catch (InvalidParameterException e) {
558 LOG.debug("Expected exception is thrown: "
559 + e.getClass().getSimpleName() + ": " + e.getMessage());
562 rollbackNestedTransaction();
563 LOG.debug(">>>>> END testSetDescription()");
567 * Test of removal of a study description.
569 * @throws BusinessException
570 * if there is something wrong likely unrelated to the tested method
573 public void testRemoveDescription() throws BusinessException {
574 LOG.debug(">>>>> BEGIN testRemoveDescription()");
575 startNestedTransaction();
577 User user = TestEntitiesGenerator.getTestUser("GoodUser");
578 _userDAO.create(user);
579 Study study = TestEntitiesGenerator.getTestStudy(user);
580 _studyDAO.create(study);
582 Long studyId = Long.valueOf(study.getIndex());
584 // Empty description:
585 Assert.assertFalse(_studyService.removeDescription(studyId),
586 "returned value for study without description must be null");
588 // Not empty description:
589 study.setAttribute(new DescriptionAttribute(study, "description"));
590 _studyDAO.update(study);
592 Assert.assertTrue(_studyService.removeDescription(studyId),
593 "existing description removal must return true");
595 Assert.assertNull(_studyService.getDescription(studyId),
596 "description hasn't been successfully removed");
600 _studyService.removeDescription(null);
601 Assert.fail("removal with null study id must fail");
602 } catch (InvalidParameterException e) {
603 LOG.debug("Expected exception is thrown: "
604 + e.getClass().getSimpleName() + ": " + e.getMessage());
608 Study tmpStudy = TestEntitiesGenerator.getTestStudy(user);
609 _studyDAO.create(tmpStudy);
610 Long nonExistingId = tmpStudy.getIndex();
611 _studyDAO.delete(tmpStudy);
613 _studyService.removeDescription(nonExistingId);
614 Assert.fail("removal with non-existing study id must fail");
615 } catch (InvalidParameterException e) {
616 LOG.debug("Expected exception is thrown: "
617 + e.getClass().getSimpleName() + ": " + e.getMessage());
620 rollbackNestedTransaction();
621 LOG.debug(">>>>> END testGetDescription()");
625 * Test study removal.<BR>
626 * <B>Description :</B> <BR>
627 * <i>Delete a study.</i><BR>
628 * <B>Action : </B><BR>
629 * <i>1. call the method for a not existing study id expecting an exception.</i><BR>
630 * <i>2. call the method for an existing study id.</i><BR>
631 * <B>Test data : </B><BR>
632 * <i>no input parameters</i><BR>
634 * <B>Outcome results:</B><BR>
637 * <li>1: Exception must be thrown.</li>
638 * <li>2: The study and all its objects must be removed.</li>
642 * @throws BusinessException
643 * if test data creation is failed
646 public void testRemoveStudy() throws BusinessException {
647 LOG.debug(">>>>> BEGIN testRemoveStudy()");
648 startNestedTransaction();
650 HibernateTemplate ht = getHibernateTemplate();
652 Database.getInstance().reset();
653 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
654 // Load workflow customization
656 _projectSettings.configure("classpath:test/som.xml");
657 } catch (Exception e) {
658 Assert.fail("Can't load som.xml: ", e);
661 User goodUser = TestEntitiesGenerator.getTestUser("GoodUser");
662 _userDAO.create(goodUser);
663 User otherUser = TestEntitiesGenerator.getTestUser("otherUser");
664 _userDAO.create(otherUser);
665 User thirdUser = TestEntitiesGenerator.getTestUser("thirdUser");
666 _userDAO.create(thirdUser);
667 KnowledgeElementType ktype1 = new KnowledgeElementType("testKType1");
668 KnowledgeElementType ktype2 = new KnowledgeElementType("testKType2");
669 ktype2.setState(ProgressState.inWORK);
670 _knowledgeElementTypeDAO.create(ktype1);
671 _knowledgeElementTypeDAO.create(ktype2);
673 // Create private study
674 Study aStudy = TestEntitiesGenerator.getTestStudy(goodUser);
675 aStudy.setTitle("0.This is private study");
676 Long studyId = _studyDAO.create(aStudy);
678 // Add simulation context to the study
679 SimulationContext.Properties cprop = new SimulationContext.Properties();
680 cprop.setType(_simulationContextService.selectType("product"))
681 .setValue("Test Simulation Context: Product");
682 SimulationContext ctx = _studyService.addProjectContext(aStudy, cprop);
685 // Add a scenario to the study
686 Scenario scen = TestEntitiesGenerator.getTestScenario(aStudy);
687 _scenarioDAO.create(scen);
690 // Add knowledge elements to the scenario
691 KnowledgeElement kelm01 = TestEntitiesGenerator
692 .getTestKnowledgeElement(scen, ktype1, "TestKelm01 title");
693 KnowledgeElement kelm02 = TestEntitiesGenerator
694 .getTestKnowledgeElement(scen, ktype2, "TestKelm02 title");
695 _knowledgeElementDAO.create(kelm01);
696 _knowledgeElementDAO.create(kelm02);
699 // Add contributor relation
700 aStudy.addRelation(new ContributorRelation(aStudy, otherUser));
703 // Add a validation cycle with otherUser as a reviewer
704 ValidationCycle.Properties vprop = new ValidationCycle.Properties();
705 DocumentType type = _documentTypeService.selectType("specification");
706 vprop.setDocumentType(type);
707 vprop.setActor(ValidationStep.REVIEW, otherUser);
708 ValidationCycle cycle = new ValidationCycle(aStudy, vprop);
709 _validationCycleDAO.create(cycle);
710 ValidationCycleRelation link = cycle.getContext();
711 aStudy.addRelation(link);
714 // Add documents to the first study activity
715 // Add a version relation
716 // Add a converts relation
717 // Add documents to the first scenario activity
718 // Add uses relations
721 _studyService.removeStudy(studyId);
724 // Check removal of the study
725 Study foundStudy = ht.get(Study.class, studyId);
726 Assert.assertNull(foundStudy);
727 // Check removal of relations to validation cycle
728 List found = ht.find("from ValidationCycleRelation where owner="
730 Assert.assertEquals(found.size(), 0,
731 "ValidationCycleRelation is not removed");
732 // Check removal of validation cycles
733 found = ht.find("from ValidationCycle where rid=" + cycle.getIndex());
734 Assert.assertEquals(found.size(), 0, "ValidationCycle is not removed");
735 // Check removal of contributors relation
736 found = ht.find("from ContributorRelation where owner=" + studyId);
737 Assert.assertEquals(found.size(), 0,
738 "ContributorRelation is not removed");
739 // Check that contributors are not removed
740 User foundUser = ht.get(User.class, otherUser.getIndex());
741 Assert.assertNotNull(foundUser);
742 // Check removal of the scenario
743 found = ht.find("from Scenario where owner=" + studyId);
744 Assert.assertEquals(found.size(), 0, "Scenario is not removed");
745 // Check removal of publications
747 .find("from Publication pub left join pub.owner as own where own.rid="
748 + studyId + " or own.rid=" + scen.getIndex());
749 Assert.assertEquals(found.size(), 0, "Publication is not removed");
750 // Check removal of documents
751 // Check removal of version relations
752 // Check removal of converts relations
753 // Check removal of files
754 // Check removal of uses relations
755 // Check removal of usedBy relations
757 rollbackNestedTransaction();
758 LOG.debug(">>>>> END testRemoveStudy()");