1 /*****************************************************************************
5 * Creation date 12 Oct 2012
8 *****************************************************************************/
9 package test.splat.service;
12 import java.io.FileNotFoundException;
13 import java.io.FileWriter;
14 import java.io.IOException;
15 import java.sql.SQLException;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.HashMap;
19 import java.util.List;
23 import org.splat.dal.bo.kernel.Relation;
24 import org.splat.dal.bo.kernel.User;
25 import org.splat.dal.bo.som.ConvertsRelation;
26 import org.splat.dal.bo.som.Document;
27 import org.splat.dal.bo.som.DocumentType;
28 import org.splat.dal.bo.som.KnowledgeElementType;
29 import org.splat.dal.bo.som.Publication;
30 import org.splat.dal.bo.som.Scenario;
31 import org.splat.dal.bo.som.SimulationContext;
32 import org.splat.dal.bo.som.SimulationContextType;
33 import org.splat.dal.bo.som.Study;
34 import org.splat.dal.bo.som.UsedByRelation;
35 import org.splat.dal.bo.som.UsesRelation;
36 import org.splat.dal.bo.som.Document.Properties;
37 import org.splat.dal.dao.kernel.UserDAO;
38 import org.splat.dal.dao.som.Database;
39 import org.splat.dal.dao.som.ScenarioDAO;
40 import org.splat.exception.BusinessException;
41 import org.splat.kernel.InvalidPropertyException;
42 import org.splat.kernel.MismatchException;
43 import org.splat.kernel.MissedPropertyException;
44 import org.splat.kernel.MultiplyDefinedException;
45 import org.splat.kernel.NotApplicableException;
46 import org.splat.log.AppLogger;
47 import org.splat.service.DocumentTypeService;
48 import org.splat.service.KnowledgeElementTypeService;
49 import org.splat.service.PublicationService;
50 import org.splat.service.ScenarioService;
51 import org.splat.service.SimulationContextService;
52 import org.splat.service.StepService;
53 import org.splat.service.StudyService;
54 import org.splat.service.dto.DocumentDTO;
55 import org.splat.service.dto.FileDTO;
56 import org.splat.service.dto.StepDTO;
57 import org.splat.service.technical.ProjectSettingsService;
58 import org.splat.service.technical.RepositoryService;
59 import org.splat.service.technical.StepsConfigService;
60 import org.splat.service.technical.ProjectSettingsService.Step;
61 import org.springframework.beans.factory.annotation.Autowired;
62 import org.springframework.beans.factory.annotation.Qualifier;
63 import org.springframework.orm.hibernate3.HibernateTemplate;
64 import org.testng.Assert;
65 import org.testng.annotations.Test;
66 import org.testng.reporters.Files;
68 import test.splat.common.BaseTest;
69 import test.splat.util.TestEntitiesGenerator;
72 * Test class for ScenarioService.
74 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
77 public class TestScenarioService extends BaseTest {
80 * Logger for the class.
82 private static final AppLogger LOG = AppLogger
83 .getLogger(TestScenarioService.class);
86 * The tested ScenarioService. Later injected by Spring.
89 @Qualifier("scenarioService")
90 private transient ScenarioService _scenarioService;
93 * The RepositoryService. Later injected by Spring.
96 @Qualifier("repositoryService")
97 private transient RepositoryService _repositoryService;
100 * The Scenario DAO. Later injected by Spring.
103 @Qualifier("scenarioDAO")
104 private transient ScenarioDAO _scenarioDAO;
107 * The PublicationService. Later injected by Spring.
110 @Qualifier("publicationService")
111 private transient PublicationService _publicationService;
114 * The StepService. Later injected by Spring.
117 @Qualifier("stepService")
118 private transient StepService _stepService;
121 * The SimulationContextService. Later injected by Spring.
124 @Qualifier("simulationContextService")
125 private transient SimulationContextService _simulationContextService;
128 * The ProjectSettingsService. Later injected by Spring.
131 @Qualifier("projectSettings")
132 private transient ProjectSettingsService _projectSettings;
135 * The StepsConfigService. Later injected by Spring.
138 @Qualifier("stepsConfigService")
139 private transient StepsConfigService _stepsConfigService;
142 * The DocumentTypeService. Later injected by Spring.
145 @Qualifier("documentTypeService")
146 private transient DocumentTypeService _documentTypeService;
149 * The KnowledgeElementTypeService. Later injected by Spring.
152 @Qualifier("knowledgeElementTypeService")
153 private transient KnowledgeElementTypeService _knowledgeElementTypeService;
156 * The UserDAO. Later injected by Spring.
159 @Qualifier("userDAO")
160 private transient UserDAO _userDAO;
163 * The StudyService. Later injected by Spring.
166 @Qualifier("studyService")
167 private transient StudyService _studyService;
170 * Test of getting a scenario content for building siman-salome.conf.<BR>
171 * <B>Description :</B> <BR>
172 * <i>Create a scenario and try to get an info for it.</i><BR>
173 * <B>Action : </B><BR>
174 * <i>1. call the method for an existing scenario id.</i><BR>
175 * <i>2. call the method for a not existing scenario id.</i><BR>
176 * <B>Test data : </B><BR>
177 * <i>no input parameters</i><BR>
178 * <i>no input parameters</i><BR>
180 * <B>Outcome results:</B><BR>
183 * <li>result DTO must contain list of all documents and files<BR>
185 * <li>Exception is thrown<BR>
190 * @throws InvalidPropertyException
191 * if an invalid property is used when creating objects
192 * @throws MultiplyDefinedException
193 * when trying to create an object with already existing id
194 * @throws MissedPropertyException
195 * if a mandatory property is not defined for an object to be created
196 * @throws IOException
197 * if scenario creation is failed
198 * @throws SQLException
199 * if scenario creation is failed
201 @Test(groups = { "checkout", "sevice", "functional", "business" })
202 public void testGetScenarioInfo() throws InvalidPropertyException,
203 MissedPropertyException, MultiplyDefinedException, IOException,
205 LOG.debug(">>>>> BEGIN testGetScenarioInfo()");
206 startNestedTransaction();
208 long scenarioId = createScenario();
209 // Call DAO's create method for a good transient knowledge element.
210 List<StepDTO> steps = _scenarioService.getScenarioInfo(scenarioId);
211 Assert.assertNotNull(steps, "List of steps must not be null.");
212 Assert.assertTrue(steps.size() > 0, "No steps are read.");
214 List<Step> projSteps = _stepsConfigService.getStepsOf(Scenario.class);
215 Assert.assertEquals(steps.size(), projSteps.size(),
216 "Not all steps are listed.");
218 for (StepDTO step : steps) {
219 LOG.debug("check the step " + step.getNumber() + ":\n" + step);
220 Assert.assertNotNull(step, "Step DTO must not be null.");
221 Assert.assertNotNull(step.getKey(), "Step name must not be null.");
222 Assert.assertFalse(step.getKey().isEmpty(),
223 "Step name must not empty.");
224 Assert.assertTrue(step.getNumber() > 0,
225 "Step number must be positive integer.");
226 Assert.assertNotNull(step.getDocs(),
227 "Step documents list must not be null.");
229 Step aProjStep = null;
230 for (Step projStep : projSteps) {
231 if (projStep.getNumber() == step.getNumber()) {
232 aProjStep = projStep;
237 List<DocumentType> dtypes = _documentTypeService
238 .selectTypesOf(aProjStep);
239 for (DocumentType dtype : dtypes) {
240 Assert.assertTrue(step.getDocs().size() > 0,
241 "Step documents list must not be empty.");
242 String docName = "document" + docIndex;
243 for (DocumentDTO doc : step.getDocs()) {
244 if (docName.equals(doc.getTitle())) {
245 Assert.assertTrue(doc.getId() > 0,
246 "Document id must be positive integer.");
247 Assert.assertEquals(doc.getTitle(), docName);
248 Assert.assertNotNull(doc.getFiles(),
249 "Document files list must not be null.");
251 .assertTrue(doc.getFiles().size() > 1,
252 "Document must have more then 1 attached file.");
254 for (FileDTO file : doc.getFiles()) {
255 Assert.assertNotNull(file.getPath(),
256 "File path must not be null.");
257 Assert.assertFalse(file.getPath().isEmpty(),
258 "File path must not be empty.");
260 * <mappings> <document type="geometry"> <import format="brep"/> <!-- Result Shape --> </document> <document
261 * type="model"> <import format="med"/> <!-- Result mesh without input parameters --> </document> <document
262 * type="loads"> <import format="c3m"/> <!-- Input data created interactively --> </document> <document
263 * type="results"> <import format="med"/> <!-- Calculation results source file --> </document> </mappings>
265 // Check state and processing instruction
266 String fileFormat = file.getPath().substring(
267 file.getPath().lastIndexOf('.') + 1);
269 * if (_projectSettings.doImport(dtype.getName(), fileFormat)) { Assert.assertTrue(file.isResult(), "The file
270 * must be a result file."); } else { Assert.assertFalse(file.isResult(), "The file must be a source file."); }
271 */if ((docIndex % 2) == 0) { // New
272 Assert.assertEquals(file.getState(), 'Y',
273 "File state must be actual ('Y').");
274 if (_projectSettings.doImport(dtype.getName(),
276 Assert.assertEquals(file.getProcessing(),
278 "File must be imported.");
280 Assert.assertEquals(file.getProcessing(),
282 "File must be downloaded.");
285 Assert.assertEquals(file.getState(), 'O',
286 "File state must be outdated ('O').");
288 .assertEquals(file.getProcessing(),
290 "Outdated document should not be imported but downloaded.");
299 // Call DAO's get method for a not existing id.
301 steps = _scenarioService.getScenarioInfo(-1L);
302 // getHibernateTemplate().flush();
304 .fail("Getting an object with not existing id must be failed.");
305 } catch (Exception e) {
306 LOG.debug("Expected exception is thrown: "
307 + e.getClass().getSimpleName() + ": " + e.getMessage());
309 rollbackNestedTransaction();
310 LOG.debug(">>>>> END testGetScenarioInfo()");
314 * Test check-in scenario operation to be performed after SALOME session.<BR>
315 * <B>Description :</B> <BR>
316 * <i>Create a scenario and try to check-in it with some simulated SALOME results data.<BR>
317 * After check-in verify following points:
319 * <li>scenario is no more marked as checked out</li>
320 * <li>new document versions are created for checked in documents</li>
321 * <li>presentation of the previous version is removed</li>
322 * <li>uses relations are copied correctly</li>
323 * <li>files are moved correctly</li>
324 * <li>formats of files are new if they are according to the document's type on the study step</li>
325 * <li>new documents are created for new data</li>
326 * <li>new documents have correctly generated names</li>
327 * <li>uses relations are created correctly</li>
328 * <li>files are moved correctly</li>
331 * <B>Action : </B><BR>
332 * <i>1. call the method for an existing scenario id.</i><BR>
333 * <i>2. call the method for a not existing scenario id.</i><BR>
334 * <B>Test data : </B><BR>
335 * <i>no input parameters</i><BR>
336 * <i>no input parameters</i><BR>
338 * <B>Outcome results:</B><BR>
341 * <li>New version of existing documents must be created and new documents must be imported for documents with zero id. Correct
342 * relations must be created.<BR>
344 * <li>Exception is thrown<BR>
349 * @throws InvalidPropertyException
350 * if an invalid property is used when creating objects
351 * @throws MultiplyDefinedException
352 * when trying to create an object with already existing id
353 * @throws MissedPropertyException
354 * if a mandatory property is not defined for an object to be created
355 * @throws IOException
356 * if scenario creation is failed
357 * @throws SQLException
358 * if scenario creation is failed
359 * @throws NotApplicableException
361 * @throws MismatchException
364 @Test(groups = { "checkin", "sevice", "functional", "business" })
365 public void testCheckin() throws InvalidPropertyException,
366 MissedPropertyException, MultiplyDefinedException, IOException,
367 SQLException, MismatchException, NotApplicableException {
368 LOG.debug(">>>>> BEGIN testCheckin()");
369 startNestedTransaction();
371 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
372 _projectSettings.configure("classpath:test/som.xml");
373 getHibernateTemplate().flush();
374 long scenarioId = createScenario();
375 Scenario aScen = _scenarioDAO.get(scenarioId);
376 User user = aScen.getAuthor();
377 long userId = user.getIndex();
379 // ////////////////////////////////////////////////////////
380 // Call checkin method for empty list of modules.
383 List<StepDTO> steps = _scenarioService.getScenarioInfo(scenarioId);
384 _scenarioService.checkout(aScen, user);
385 _scenarioDAO.flush();
386 // Check that scenario is no more marked as checked out
387 aScen = _scenarioDAO.get(scenarioId);
388 Assert.assertTrue(aScen.isCheckedout(),
389 "Scenario is not marked as checked out after checkout.");
391 // Prepare test data for checkin
392 // Checkin only two first steps (geom and mesh)
393 List<StepDTO> stepsToCheckin = new ArrayList<StepDTO>();
395 _scenarioService.checkin(scenarioId, userId, stepsToCheckin);
397 _scenarioDAO.flush();
398 // Check that scenario is no more marked as checked out
399 aScen = _scenarioDAO.get(scenarioId);
400 Assert.assertFalse(aScen.isCheckedout(),
401 "Scenario is still marked as checked out after checkin.");
403 // ////////////////////////////////////////////////////////
404 // Call checkin method for good prepared transient data.
407 steps = _scenarioService.getScenarioInfo(scenarioId);
408 _scenarioService.checkout(aScen, user);
410 // Remember modification dates of all attached files
411 Map<Long, Date> dates = new HashMap<Long, Date>();
412 for (Publication p : aScen.getDocums()) {
413 for (Relation r : p.value().getRelations(ConvertsRelation.class)) {
414 org.splat.dal.bo.som.File attach = ((ConvertsRelation) r)
416 dates.put(attach.getIndex(), attach.getDate());
420 // Prepare test data for checkin
421 // Checkin only two first steps (geom and mesh)
422 for (StepDTO step : steps) {
423 // Prepare GEOM: checkin actual brep
424 StepDTO stepToCheckin = createDocDTOForModule(null, "GEOM", "brep",
425 userId, step, stepsToCheckin);
426 createDocDTOForModule(stepToCheckin, "SMESH", "med", userId, step,
430 _scenarioService.checkin(scenarioId, userId, stepsToCheckin);
432 _scenarioDAO.flush();
433 // Check that scenario is no more marked as checked out
434 aScen = _scenarioDAO.get(scenarioId);
435 Assert.assertFalse(aScen.isCheckedout(),
436 "Scenario is still marked as checked out after checkin.");
437 boolean modifDatesChecked = false;
438 // Check that new document versions are created for checked in documents
439 for (StepDTO step : stepsToCheckin) {
440 for (DocumentDTO docDTO : step.getDocs()) {
441 if ((docDTO.getId() != 0) && (docDTO.getId() != null)) {
442 boolean found = false;
443 Document prevDoc = null;
444 Document curDoc = null;
445 Publication newPub = null;
446 for (Publication pub : aScen.getDocums()) {
447 prevDoc = pub.value().getPreviousVersion();
448 if (prevDoc != null) {
449 found = (prevDoc.getIndex() == docDTO.getId());
450 if (found) { // Found next published version of the checked in document
455 if (pub.value().getIndex() == docDTO.getId()) {
456 // Document version was not changed, old document is still published
457 curDoc = pub.value();
461 Assert.assertTrue(found || (curDoc != null),
462 "New version or new attached file of the existing checked in document \""
463 + docDTO.getTitle() + "\" (id="
465 + ") is not found in the scenario.");
466 // If previous version is found then the format must be the same
467 String newFormat = docDTO.getFiles().get(0).getPath()
469 docDTO.getFiles().get(0).getPath()
470 .lastIndexOf('.') + 1);
472 Assert.assertEquals(prevDoc.getFormat(), newFormat,
473 "Formats of versions must be same");
474 Assert.assertFalse(aScen.publishes(prevDoc));
475 // Check that presentation of the previous version is removed
476 checkFiles(docDTO, newPub);
478 // Formats of files are new if they are according to the document's type on the study step
479 if ("py".equals(prevDoc.getFormat())
480 && "geometry".equals(prevDoc.getType()
482 Assert.assertEquals(newPub.value().getFormat(),
484 Assert.assertEquals(newPub.getSourceFile()
485 .getFormat(), "brep");
486 Assert.assertEquals(newPub.getSourceFile()
487 .getRelativePath().substring(
488 newPub.getSourceFile()
490 .lastIndexOf('.') + 1),
494 // Check that uses relations are copied correctly
496 // 1. Get all uses relations of the previous document version
497 for (Relation rel : prevDoc
498 .getRelations(UsesRelation.class)) {
499 Document used = ((UsesRelation) rel).getTo();
500 // 2.1. Get the latest version of the document published in this scenario
501 Publication toBeUsed = aScen.getPublication(used);
502 if (toBeUsed == null) {
503 // Find the latest published version
504 for (Publication lastPub : aScen.getDocums()) {
505 if ((lastPub.value().getPreviousVersion() != null)
507 .getPreviousVersion()
515 if ((toBeUsed != null) && (!toBeUsed.isOutdated())) {
516 // 2.2. For each used document check that its latest not outdated version
517 // is used by the new checked in document version.
518 checkUsesRelation(newPub, toBeUsed);
521 // 1. Get all usedBy relations of the previous document version
522 for (Relation rel : prevDoc
523 .getRelations(UsedByRelation.class)) {
524 Document using = ((UsedByRelation) rel).getTo();
525 // Check that not checked in dependent documents became outdated
526 Publication usingPub = aScen.getPublication(using);
527 if (usingPub != null) { // if the document using the old version is still published
528 Assert.assertTrue(usingPub.isOutdated(),
529 "Not checked in dependent document "
530 + using.getTitle() + " ("
531 + using.getType().getName()
532 + ") must become outdated.");
536 // Otherwise the new file format must differ from the previous one
537 // and the new file must be attached to the same document
538 org.splat.dal.bo.som.File attFile = curDoc
539 .getAttachedFile(newFormat);
540 Assert.assertNotNull(attFile, "File "
541 + docDTO.getFiles().get(0).getPath()
542 + " must be attached to the document "
543 + docDTO.getTitle() + "#" + docDTO.getId());
544 Assert.assertTrue(attFile.asFile().exists(), "File "
545 + docDTO.getFiles().get(0).getPath()
546 + " attached to the document "
547 + docDTO.getTitle() + "#" + docDTO.getId()
549 LOG.debug("Source format: " + curDoc.getFormat()
550 + ", new format: " + newFormat);
551 // Check that attachment with the same format is not duplicated.
553 for (Relation conv : curDoc
554 .getRelations(ConvertsRelation.class)) {
555 if (newFormat.equals(((ConvertsRelation) conv)
556 .getTo().getFormat())) {
561 .assertEquals(attachNb, 1,
562 "Attachment with the same format must be only one.");
564 // Check that the attached file date is updated
565 if (dates.containsKey(attFile.getIndex())) {
567 .assertTrue(attFile.getDate().compareTo(
568 dates.get(attFile.getIndex())) > 0,
569 "Attachment modification date is not updated.");
570 modifDatesChecked = true;
575 // Check that new documents are created for new data
576 boolean found = false;
577 Publication newPub = null;
578 for (Publication pub : aScen.getDocums()) {
579 if (pub.value().getPreviousVersion() == null) {
580 found = (pub.value().getTitle().startsWith(pub
581 .value().getType().getName()));
582 if (found) { // Found next published version of the checked in document
583 String fcontent = Files.readFile(pub
584 .getSourceFile().asFile());
585 found = fcontent.contains(docDTO.getTitle());
588 .debug("Found new document with generated title: "
589 + pub.value().getTitle());
596 Assert.assertTrue(found,
597 "New document is not created for checked in document \""
598 + docDTO.getTitle() + "\".");
600 // Check that uses relations are created correctly
601 Assert.assertTrue(newPub.value().getTitle().startsWith(
602 newPub.value().getType().getName() + "_"),
603 "Document title newPub.value().getTitle() must start with "
604 + newPub.value().getType().getName() + "_");
606 // 1. Find the document type used by this document type
607 Set<DocumentType> usedTypes = newPub.value().getType()
609 // 2. Find documents of used types in the current study step and previous study steps
610 for (Publication pub : aScen.getDocums()) {
611 if ((pub.getStep().getNumber() <= step.getNumber())
612 && (!pub.isOutdated())
613 && usedTypes.contains(pub.value().getType())) {
614 // 3. Check that there is uses relation to the found document
615 // if it is not outdated.
616 checkUsesRelation(newPub, pub);
620 // Check that files are moved correctly
621 checkFiles(docDTO, newPub);
629 "No modification date is checked because no files were attached when attachment with same extension already exists.");
631 // ///////////////////////////////////////////////////////////
632 // Call checkin method for a not existing id.
634 _scenarioService.checkin(-1, userId, stepsToCheckin);
636 .fail("Check in for scenario with not existing id must be failed.");
637 } catch (Exception e) {
638 LOG.debug("Expected exception is thrown: "
639 + e.getClass().getSimpleName() + ": " + e.getMessage());
642 // Test checkin with empty list of steps
643 stepsToCheckin.clear();
644 _scenarioService.checkin(scenarioId, userId, stepsToCheckin);
646 rollbackNestedTransaction();
647 LOG.debug(">>>>> END testCheckin()");
651 * Check if there is uses relation from the newPub to pub.
654 * the new publication
656 * the publication to be used
658 private void checkUsesRelation(final Publication newPub,
659 final Publication pub) {
660 boolean uses = false;
661 boolean usesExist = false;
662 for (Publication usesPub : newPub.getRelations(UsesRelation.class)) {
664 uses = (usesPub.equals(pub));
669 Assert.assertTrue(usesExist && uses, "The created document "
670 + newPub.value().getTitle() + "("
671 + newPub.value().getType().getName() + ")"
672 + " has no uses relation to the document "
673 + pub.value().getTitle() + "("
674 + pub.value().getType().getName() + ")");
678 * Check that files are moved correctly.
681 * checked in document DTO
683 * the created document publication
685 private void checkFiles(final DocumentDTO docDTO, final Publication newPub) {
686 // Check that original files are deleted
687 for (int j = 0; j < docDTO.getFiles().size(); j++) {
688 FileDTO fileDTO = docDTO.getFiles().get(j);
689 Assert.assertFalse(new File(fileDTO.getPath()).exists(), "File"
691 + " was not removed from downloads directory.");
692 String format = fileDTO.getPath().substring(
693 fileDTO.getPath().lastIndexOf('.') + 1);
695 // TODO: Check file by its internal content
696 Assert.assertTrue(newPub.getSourceFile().exists(), "File "
697 + newPub.getSourceFile().asFile().getAbsolutePath()
698 + " for the document " + docDTO.getTitle()
699 + " was not created.");
703 * Prepare a document with a file for check-in.
706 * step DTO with data for check-in
714 * checked out stepDTO
715 * @param stepsToCheckin
717 * @throws IOException
718 * if file creation failed
719 * @return step DTO with data prepared for check-in (stepTo or new if stepTo is null)
721 private StepDTO createDocDTOForModule(final StepDTO stepTo,
722 final String module, final String format, final long userId,
723 final StepDTO stepFrom, final List<StepDTO> stepsToCheckin)
725 StepDTO stepToCheckin = stepTo;
726 if (stepToCheckin == null) {
727 stepToCheckin = new StepDTO();
729 if (module.equals(stepFrom.getModule())) {
730 stepsToCheckin.add(stepToCheckin);
731 stepToCheckin.setNumber(stepFrom.getNumber());
732 for (DocumentDTO doc : stepFrom.getDocs()) {
733 if (doc.getFiles().get(0).getState() != 'O') {
734 DocumentDTO docToCheckin = stepToCheckin.addDoc(
735 doc.getId(), doc.getTitle());
736 for (FileDTO file : doc.getFiles()) {
737 if (file.getPath().endsWith(format)
738 || (file.getPath().endsWith("py") && (format
739 .equals("brep") || format.equals("med")))) {
740 // Create a file in the download directory
741 docToCheckin.addFile(createDownloadedFile(userId,
742 doc.getTitle() + "_result", format));
748 stepToCheckin.addDoc(0, "newdoc" + stepFrom.getNumber()).addFile(
749 createDownloadedFile(userId, "newdoc"
750 + stepFrom.getNumber(), "brep"));
752 return stepToCheckin;
756 * Create a file in the user's repository downloads directory.
764 * @return created file DTO
765 * @throws IOException
766 * if file creation failed
768 private FileDTO createDownloadedFile(final long userId, final String name,
769 final String format) throws IOException {
770 // Create a file in the download directory
771 return createDownloadedFile(userId, name + "." + format);
775 * Create a file in the user's repository downloads directory.
781 * @return created file DTO
782 * @throws IOException
783 * if file creation failed
785 private FileDTO createDownloadedFile(final long userId, final String fname)
787 // Create a file in the download directory
788 String filePath = getDownloadPath(userId) + fname;
789 FileWriter fw = new FileWriter(filePath);
790 fw.write("Simulation of " + fname + " file for checkin at "
793 return new FileDTO(filePath);
797 * Get path to the user's downloads directory. The directory is created if it is not exist yet.
801 * @return absolute path to downloads directory followed by slash
803 private String getDownloadPath(final long userId) {
804 // Prepare download directory
805 File tmpDir = _repositoryService.getDownloadDirectory(userId);
806 if (!tmpDir.exists()) {
807 Assert.assertTrue(tmpDir.mkdir(),
808 "Can't create temporary directory: "
809 + tmpDir.getAbsolutePath());
812 return tmpDir.getAbsolutePath() + "/";
816 * Create a persistent scenario for tests.
818 * @return a persistent scenario
819 * @throws InvalidPropertyException
820 * if an invalid property is used when creating objects
821 * @throws MultiplyDefinedException
822 * when trying to create an object with already existing id
823 * @throws MissedPropertyException
824 * if a mandatory property is not defined for an object to be created
825 * @throws IOException
826 * if document creation is failed
827 * @throws SQLException
828 * if project settings loading is failed
830 private long createScenario() throws InvalidPropertyException,
831 MissedPropertyException, MultiplyDefinedException, IOException,
833 // Create a scenario for tests
834 HibernateTemplate ht = getHibernateTemplate();
836 Database.getInstance().reset();
837 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
838 // Load workflow customization
840 _projectSettings.configure("classpath:test/som.xml");
841 } catch (FileNotFoundException e) {
842 Assert.fail("Can't find som.xml: ", e);
844 List<Step> steps = _stepsConfigService.getStepsOf(Scenario.class);
845 Assert.assertTrue(steps.size() > 0, "No steps are created.");
847 // Create a test user
848 User.Properties uprop = new User.Properties();
849 uprop.setUsername("TST_Username").setName("TST_SimanUnitTestsUser")
850 .setFirstName("TST_FirstName").setDisplayName("TST_test.user")
851 .addRole("TST_user").setMailAddress(
852 "noreply@salome-platform.org");
853 uprop.disableCheck();
854 User anAuthor = new User(uprop);
855 ht.saveOrUpdate(anAuthor);
857 // Create a test study
858 Study.Properties stprops = new Study.Properties().setReference(
859 "TST_SID_01").setTitle("TST_Study").setManager(anAuthor);
860 Study aStudy = new Study(stprops);
861 ht.saveOrUpdate(aStudy);
863 // Create a test scenario
864 Scenario.Properties sprops = new Scenario.Properties().setTitle(
865 "TST_Scenario").setManager(anAuthor).setOwnerStudy(aStudy);
866 Scenario aScenario = new Scenario(sprops);
867 aStudy.getScenariiList().add(aScenario);
868 ht.saveOrUpdate(anAuthor);
869 ht.saveOrUpdate(aStudy);
870 ht.saveOrUpdate(aScenario);
872 // Create documents for each scenario step
873 Document.Properties dprop = new Document.Properties().setAuthor(
874 anAuthor).setDate(new Date());
876 Publication usedPub = null;
877 Map<Long, Long> usedMap = new HashMap<Long, Long>();
878 for (Step step : steps) {
879 LOG.debug("Create scenario step: " + i);
881 org.splat.som.Step aScStep = new org.splat.som.Step(step, aScenario);
882 List<DocumentType> dtypes = _documentTypeService
883 .selectTypesOf(step);
884 for (DocumentType dtype : dtypes) {
885 // Create a document published in the scenario
886 // document<i>: document type[0] - first type used on the step
887 // <source-file>.brep
888 // <attached-file>.med
889 dprop.setName("document" + i++).setType(dtype);
891 * if (step.getNumber() > 3) { dprop.setFormat("med"); } else {
892 */dprop.setFormat("py");
894 dprop.setLocalPath(dprop.getName() + "." + dprop.getFormat());
895 Publication pub = createDoc(aScenario, aScStep, dprop, "med",
897 if (usedPub != null) {
898 pub.addDependency(usedPub);
899 ht.saveOrUpdate(pub.value());
901 usedMap.put(pub.getIndex(), usedPub.getIndex());
905 // Create another document with outdated publication
906 dprop.setName("document" + i++).setType(dtype).setFormat("py");
907 dprop.setLocalPath(dprop.getName() + "." + dprop.getFormat());
908 createDoc(aScenario, aScStep, dprop, "med", true);
911 if (dtypes.size() <= 0) {
912 LOG.debug("No document types are found for scenario step " + i);
916 // Check that the scenario and its documents have been created correctly.
918 Assert.assertNotNull(ht.find("from Document"),
919 "No documents in the database.");
920 Assert.assertTrue(ht.find("from Document").size() > 0,
921 "No documents in the database.");
923 Assert.assertNotNull(ht.find("from Publication where owner="
924 + aScenario.getIndex()), "No publications in the database.");
926 ht.find("from Publication where owner=" + aScenario.getIndex())
927 .size() > 0, "No publications in the database.");
929 for (Publication p : (List<Publication>) ht
930 .find("from Publication where owner=" + aScenario.getIndex())) {
931 LOG.debug("Publication found: [id=" + p.getIndex() + ", owner="
932 + p.getOwner().getIndex() + ", doc=" + p.value().getIndex()
934 Assert.assertEquals(p.getOwner().getIndex(), aScenario.getIndex(),
935 "The publication was not attached to the scenario.");
938 // Remove the scenario from the current hibernate session.
940 // Check that the scenario is created in the database.
941 Scenario aScen = ht.load(Scenario.class, aScenario.getIndex());
942 Assert.assertNotNull(aScen, "Scenario was not saved in the database.");
943 Assert.assertTrue(aScen.getDocums().size() > 0,
944 "No publications in the scenario.");
946 Assert.assertTrue(i > 0,
947 "More then one document must be in the database");
949 // Check created uses relations
951 .assertTrue(usedMap.size() > 0,
952 "Uses relations must be created.");
953 boolean foundAny = false;
954 for (Long usingId : usedMap.keySet()) {
955 for (Publication pub : aScen.getDocums()) {
956 if (pub.getIndex() == usingId) {
957 boolean found = false;
958 for (Publication used : aScen.getDocums()) {
959 found = (used.getIndex() == usedMap.get(usingId));
964 Assert.assertTrue(found,
965 "Uses relation was not created in the database.");
966 foundAny = foundAny || found;
970 Assert.assertTrue(foundAny,
971 "No Uses relation was created in the database.");
973 return aScenario.getIndex();
977 * Create a document published in the scenario. <BR>
979 * document type[0] - first type used on the step <BR>
980 * <source-file>.brep <BR>
981 * <attached-file>.med
984 * the scenario to add the document to
986 * scenario step where the document to be published
988 * document properties
989 * @param attachedFileExt
990 * extension of the secon attached (exported) file
992 * outdated document flag
993 * @return the publication of the created document
994 * @throws IOException
995 * @throws MultiplyDefinedException
996 * @throws InvalidPropertyException
997 * @throws MissedPropertyException
999 private Publication createDoc(final Scenario aScenario,
1000 final org.splat.som.Step aScStep, final Properties dprop,
1001 final String attachedFileExt, final boolean isOutdated)
1002 throws MissedPropertyException, InvalidPropertyException,
1003 MultiplyDefinedException, IOException {
1004 // Create a document published in the scenario
1005 // document<i>: document type[0] - first type used on the step
1006 // <source-file>.brep
1007 // <attached-file>.med
1008 createDownloadedFile(aScenario.getAuthor().getIndex(), dprop
1010 Publication pub = _stepService.createDocument(aScStep, dprop);
1011 Assert.assertNotNull(pub.getOwner(),
1012 "The publication must be attached to the scenario.");
1013 Assert.assertEquals(pub.getOwner().getIndex(), aScenario.getIndex(),
1014 "The publication was not attached to the scenario.");
1020 HibernateTemplate ht = getHibernateTemplate();
1021 ht.saveOrUpdate(pub);
1024 createDownloadedFile(aScenario.getAuthor().getIndex(), dprop
1025 .getLocalPath().substring(0,
1026 dprop.getLocalPath().lastIndexOf(".") - 1),
1028 ht.save(pub.value());
1029 ht.saveOrUpdate(_publicationService.attach(pub, attachedFileExt));
1035 * Test study creation.<BR>
1036 * <B>Description :</B> <BR>
1037 * <i>Create a study.</i><BR>
1038 * <B>Action : </B><BR>
1039 * <i>1. call the method for a not existing product.</i><BR>
1040 * <i>2. call the method for an existing username and an existing product.</i><BR>
1041 * <i>3. call the method for a not existing username expecting an exception.</i><BR>
1042 * <B>Test data : </B><BR>
1043 * <i>no input parameters</i><BR>
1045 * <B>Outcome results:</B><BR>
1048 * <li>1: The new study must be created. The new product simulation context must be created.</li>
1049 * <li>2: The new study must be created.</li>
1050 * <li>3: The new study must not be created. Exception is thrown.</li>
1054 * @throws IOException
1055 * if application configuration loading is failed
1056 * @throws SQLException
1057 * if application configuration loading is failed
1058 * @throws BusinessException
1059 * if test data creation is failed
1061 @Test(groups = { "study", "sevice", "functional", "business" })
1062 public void testCreateStudy() throws BusinessException, IOException,
1064 LOG.debug(">>>>> BEGIN testCreateStudy()");
1065 startNestedTransaction();
1067 Database.getInstance().reset();
1068 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
1069 _projectSettings.configure("classpath:test/som.xml");
1071 // Create a test user
1072 User.Properties uprop = new User.Properties();
1073 uprop.setUsername("TST_Username").setName("TST_SimanUnitTestsUser")
1074 .setFirstName("TST_FirstName").setDisplayName("TST_test.user")
1075 .addRole("TST_user").setMailAddress(
1076 "noreply@salome-platform.org");
1077 uprop.disableCheck();
1078 User anAuthor = new User(uprop);
1080 getHibernateTemplate().saveOrUpdate(anAuthor);
1081 KnowledgeElementType ucase = _knowledgeElementTypeService
1082 .selectType("usecase");
1083 Assert.assertNotNull(ucase,
1084 "Knowledge type 'usecase' must be created in the database.");
1085 SimulationContextType prodtype = _simulationContextService
1086 .selectType("product");
1088 .assertNotNull(prodtype,
1089 "Simulation context type 'product' must be created in the database.");
1093 uprop.setUsername("TST_Admin").setName("TST_SimanUnitTestsAdmin")
1094 .setFirstName("TST_AdminFirstName").setDisplayName(
1095 "TST_test.admin").addRole("TST_user,sysadmin")
1096 .setMailAddress("noreply@salome-platform.org");
1097 uprop.disableCheck();
1099 getHibernateTemplate().saveOrUpdate(new User(uprop));
1100 getHibernateTemplate().flush();
1102 Study.Properties sprop = new Study.Properties();
1103 sprop.setTitle("Test study creation").setManager(anAuthor);
1104 Scenario.Properties oprop = new Scenario.Properties();
1105 oprop.setTitle("Test scenario for the created study");
1107 // Addition of the entered project context
1108 SimulationContext.Properties cprop = new SimulationContext.Properties();
1109 // Input of new project context
1110 cprop.setType(_simulationContextService.selectType("product"))
1111 .setValue("Test Simulation Context: Product");
1112 Study study = _scenarioService.createStudy(sprop, oprop, cprop);
1114 Assert.assertNotNull(study);
1115 Assert.assertTrue(study.getIndex() > 0);
1117 rollbackNestedTransaction();
1118 LOG.debug(">>>>> END testCreateStudy()");
1122 * Test study creation.<BR>
1123 * <B>Description :</B> <BR>
1124 * <i>Create a study.</i><BR>
1125 * <B>Action : </B><BR>
1126 * <i>1. call the method for a not existing product.</i><BR>
1127 * <i>2. call the method for an existing username and an existing product.</i><BR>
1128 * <i>3. call the method for a not existing username expecting an exception.</i><BR>
1129 * <B>Test data : </B><BR>
1130 * <i>no input parameters</i><BR>
1132 * <B>Outcome results:</B><BR>
1135 * <li>1: The new study must be created. The new product simulation context must be created.</li>
1136 * <li>2: The new study must be created.</li>
1137 * <li>3: The new study must not be created. Exception is thrown.</li>
1141 * @throws IOException
1142 * if application configuration loading is failed
1143 * @throws SQLException
1144 * if application configuration loading is failed
1145 * @throws BusinessException
1146 * if test data creation is failed
1148 @Test(groups = { "study", "sevice", "functional", "business" })
1149 public void testCreateStudyFromPython() throws IOException, SQLException,
1151 LOG.debug(">>>>> BEGIN testCreateStudyFromPython()");
1152 startNestedTransaction();
1154 Database.getInstance().reset();
1155 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
1156 _projectSettings.configure("classpath:test/som.xml");
1158 // Create a test user
1159 User goodUser = TestEntitiesGenerator.getTestUser("goodUser");
1160 _userDAO.create(goodUser);
1161 SimulationContextType prodtype = _simulationContextService
1162 .selectType("product");
1164 .assertNotNull(prodtype,
1165 "Simulation context type 'product' must be created in the database.");
1167 String productName = "New Test Product " + new Date().toString();
1168 long studyId1 = _scenarioService.createStudy("goodUser",
1169 "Test Study 1", productName, "Test description");
1170 Assert.assertTrue(studyId1 > 0);
1173 _scenarioService.createStudy("badbadUser", "Test Study 2",
1174 productName, "Test description");
1175 Assert.fail("Study must not be created for not existing user.");
1176 } catch (InvalidPropertyException ipe) {
1177 LOG.debug("Expected exception: " + ipe.getMessage());
1180 long studyId3 = _scenarioService.createStudy("goodUser",
1181 "Test Study 3", productName, "Test description");
1182 Assert.assertTrue(studyId3 > 0);
1184 // Check that the simulation context is the same
1185 Study study1 = _studyService.selectStudy(studyId1);
1186 Study study3 = _studyService.selectStudy(studyId3);
1187 Assert.assertEquals(study1.SimulationContextIterator().next(),
1188 study3.SimulationContextIterator().next());
1190 rollbackNestedTransaction();
1191 LOG.debug(">>>>> END testCreateStudyFromPython()");