From a428a093531a253c860c7c859ddeb448c43f5eb7 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Wed, 4 Mar 2020 11:57:15 +0300 Subject: [PATCH 01/17] Reject Creation with specified ID --- .../main/controllers/AuditController.java | 2 +- src/main/java/main/model/db/dao/DAO.java | 67 +++++++++++++++---- .../main/model/db/imports/BaseImporter.java | 2 +- src/main/java/main/model/dto/BaseDto.java | 47 ++++++++++++- src/main/java/main/model/email/Emails.java | 2 +- .../java/main/model/email/TestRunEmails.java | 2 +- src/main/java/main/utils/Daily.java | 2 +- .../java/tests/workers/dto/BaseDtoTest.java | 2 +- 8 files changed, 105 insertions(+), 21 deletions(-) diff --git a/src/main/java/main/controllers/AuditController.java b/src/main/java/main/controllers/AuditController.java index d1581c3..3a7c8af 100644 --- a/src/main/java/main/controllers/AuditController.java +++ b/src/main/java/main/controllers/AuditController.java @@ -292,7 +292,7 @@ private List completeComments(List comments) t private UserDto getUser(UserDto template) throws AqualityUserException { try { - return userDao.getEntityById(template); + return userDao.getEntityById(template.getId()); } catch (AqualityException e) { throw new AqualityUserException("Cannot get Author for the audit comment."); } diff --git a/src/main/java/main/model/db/dao/DAO.java b/src/main/java/main/model/db/dao/DAO.java index 0d28c29..dad18d6 100644 --- a/src/main/java/main/model/db/dao/DAO.java +++ b/src/main/java/main/model/db/dao/DAO.java @@ -1,6 +1,7 @@ package main.model.db.dao; import com.mysql.cj.core.conf.url.ConnectionUrlParser.Pair; +import main.exceptions.AqualityParametersException; import main.exceptions.AqualitySQLException; import main.exceptions.AqualityException; import main.model.db.RS_Converter; @@ -82,30 +83,46 @@ public List searchAll(T entity) throws AqualityException { /** * Get single entity by id - * @param entity entity id + * @param id entity id * @return entity */ - public T getEntityById(T entity) throws AqualityException { - List all = searchAll(entity); - if(all.size() > 0) { + public T getEntityById(Integer id) throws AqualityException { + T entity; + try { + entity = type.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new AqualityException("Cannot Create new Instance of entity"); + } + + List> parameters = entity.getIdSearchParameters(id); + List all = dtoMapper.mapObjects(CallStoredProcedure(select, parameters).toString()); + if(!all.isEmpty()) { return all.get(0); } else{ - throw new AqualityException("No Entities was found by %s", entity.getIDParameters()); + throw new AqualityException("No Entities was found by id"); } } - /** * Update entity * @param entity with fields that should be updated (id is required) * @return Updated entity */ public T update(T entity) throws AqualityException { - if(entity.getIDParameters().size() > 0){ - return create(entity); + try { + getEntityById(entity.getId()); + } catch (AqualityException e) { + throw new AqualityParametersException("Entity with specified id does not exist!"); } - throw new AqualityException("Cannot update entity without id!"); + + List> parameters = entity.getParameters(); + List results = dtoMapper.mapObjects(CallStoredProcedure(insert, parameters).toString()); + if (!results.isEmpty()) { + return results.get(0); + } + + throw new AqualityException("Was not able to update entity!"); } /** @@ -114,7 +131,7 @@ public T update(T entity) throws AqualityException { * @return true if was able to remove entity */ public boolean delete(T entity) throws AqualityException { - List> parameters = entity.getIDParameters(); + List> parameters = entity.getDataBaseIDParameters(); CallStoredProcedure(remove, parameters); return true; @@ -126,10 +143,22 @@ public boolean delete(T entity) throws AqualityException { * @return created entity */ public T create(T entity) throws AqualityException { - List> parameters = entity.getParameters(); - List results = dtoMapper.mapObjects(CallStoredProcedure(insert, parameters).toString()); - if(results.size() > 0){ - return results.get(0); + Integer id = null; + try { + id = entity.getId(); + } catch (AqualityException e) { + // entity has no id + } + + if(id == null){ + List> parameters = entity.getParameters(); + List results = dtoMapper.mapObjects(CallStoredProcedure(insert, parameters).toString()); + if(!results.isEmpty()){ + return results.get(0); + } + } + else { + return update(entity); } throw new AqualitySQLException(new SQLException("Possible duplicate error.", "23505")); @@ -261,4 +290,14 @@ private String getSqlName(String storedProcedure){ } return ""; } + + private boolean areParametersEmpty(List> parameters) { + for (Pair pair : parameters) { + if(!pair.right.equals("")){ + return false; + } + } + + return true; + } } diff --git a/src/main/java/main/model/db/imports/BaseImporter.java b/src/main/java/main/model/db/imports/BaseImporter.java index 9e03a75..f0f9cf1 100644 --- a/src/main/java/main/model/db/imports/BaseImporter.java +++ b/src/main/java/main/model/db/imports/BaseImporter.java @@ -229,7 +229,7 @@ private void updateResultWithSimilarError(TestResultDto result) throws AqualityE try{ ProjectDto project = new ProjectDto(); project.setId(result.getProject_id()); - project = projectDao.getEntityById(project); + project = projectDao.getEntityById(project.getId()); TestResultDto testResultTemplate = new TestResultDto(); testResultTemplate.setProject_id(result.getProject_id()); diff --git a/src/main/java/main/model/dto/BaseDto.java b/src/main/java/main/model/dto/BaseDto.java index 6137c80..98f2d0c 100644 --- a/src/main/java/main/model/dto/BaseDto.java +++ b/src/main/java/main/model/dto/BaseDto.java @@ -57,7 +57,7 @@ public List> getSearchParameters() throws AqualityException return list; } - public List> getIDParameters() throws AqualityException { + public List> getDataBaseIDParameters() throws AqualityException { List> list = new ArrayList<>(); List classFields = this.getClassFields(); boolean hasIdAnnotation = hasIdAnnotation(DataBaseID.class); @@ -80,6 +80,51 @@ public List> getIDParameters() throws AqualityException { return list; } + public List> getIdSearchParameters(Integer id) throws AqualityException { + List> list = new ArrayList<>(); + List classFields = this.getClassFields(); + for (Field field: classFields) { + DataBaseName nameAnnotation = field.getAnnotation(DataBaseName.class); + DataBaseSearchable searchAnnotation = field.getAnnotation(DataBaseSearchable.class); + if(nameAnnotation != null && searchAnnotation != null){ + field.setAccessible(true); + String value = ""; + if(Objects.equals(field.getName(), "id")) { + value = id.toString(); + } + if(nameAnnotation.name().equals("request_limit") && (value.equals("0") || value.equals(""))){ + value = "100000"; + } + Pair pair = new Pair<>(nameAnnotation.name(), value); + list.add(pair); + } + } + + if(list.isEmpty()){ + throw new AqualityException("Entity has no id parameter"); + } + + return list; + } + + public Integer getId() throws AqualityException { + List classFields = this.getClassFields(); + for (Field field: classFields) { + field.setAccessible(true); + if(Objects.equals(field.getName(), "id")) { + Object value; + try { + value = field.get(this); + } catch (IllegalAccessException e) { + throw new AqualityException(String.format("Cannot read Field: %s", field.getName())); + } + return Integer.valueOf(getStringValue(value)); + } + } + + throw new AqualityException("Entity has no id parameter"); + } + public void getSearchTemplateFromRequestParameters(@NotNull HttpServletRequest req) throws AqualityException { getTemplate(req, DataBaseSearchable.class); } diff --git a/src/main/java/main/model/email/Emails.java b/src/main/java/main/model/email/Emails.java index 5eff863..f68cd69 100644 --- a/src/main/java/main/model/email/Emails.java +++ b/src/main/java/main/model/email/Emails.java @@ -13,7 +13,7 @@ abstract class Emails { Emails() throws AqualityException { EmailSettingsDao emailSettingsDao = new EmailSettingsDao(); - EmailSettingsDto settings = emailSettingsDao.getEntityById(new EmailSettingsDto()); + EmailSettingsDto settings = emailSettingsDao.getEntityById(1); baseURL = settings.getBase_url(); } diff --git a/src/main/java/main/model/email/TestRunEmails.java b/src/main/java/main/model/email/TestRunEmails.java index 113ef77..59bac1f 100644 --- a/src/main/java/main/model/email/TestRunEmails.java +++ b/src/main/java/main/model/email/TestRunEmails.java @@ -105,7 +105,7 @@ private ProjectDto getProject(Integer id) throws AqualityException { ProjectDao projectDao = new ProjectDao(); ProjectDto projectDto = new ProjectDto(); projectDto.setId(id); - return projectDao.getEntityById(projectDto); + return projectDao.getEntityById(projectDto.getId()); } private List getProjectMemberRecipients(List users) { diff --git a/src/main/java/main/utils/Daily.java b/src/main/java/main/utils/Daily.java index 7ee9155..7687630 100644 --- a/src/main/java/main/utils/Daily.java +++ b/src/main/java/main/utils/Daily.java @@ -16,7 +16,7 @@ public class Daily implements Job { public void execute(final JobExecutionContext ctx) { EmailSettingsDao emailSettingsDao = new EmailSettingsDao(); try { - EmailSettingsDto settings = emailSettingsDao.getEntityById(new EmailSettingsDto()); + EmailSettingsDto settings = emailSettingsDao.getEntityById(1); settings.setPassword(emailSettingsDao.getAdminSecret(settings.getPassword())); AuditEmails emailWorker = new AuditEmails(); EmailUtil emailUtil = new EmailUtil(settings); diff --git a/src/test/java/tests/workers/dto/BaseDtoTest.java b/src/test/java/tests/workers/dto/BaseDtoTest.java index e0bff8e..eeb346d 100644 --- a/src/test/java/tests/workers/dto/BaseDtoTest.java +++ b/src/test/java/tests/workers/dto/BaseDtoTest.java @@ -58,7 +58,7 @@ public void getSearchParametersTest(){ @Test public void getIdParametersTest(){ try { - List> actual = testDto.getIDParameters(); + List> actual = testDto.getDataBaseIDParameters(); List> expected = new ArrayList<>(); expected.add(new Pair<>("request_id", "10")); From 90bab6bf962ad32e68797477475c0959d8bb17da Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Wed, 4 Mar 2020 11:57:56 +0300 Subject: [PATCH 02/17] update version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4138b49..e01f82c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ unifi_reporting_api api war - 0.3.7 + 0.3.8 UTF-8 From ff3c2b57d7d2a313afc4e96b255a33b356a27444 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Wed, 4 Mar 2020 13:05:13 +0300 Subject: [PATCH 03/17] Fix for settings --- src/main/java/main/model/db/dao/DAO.java | 2 +- .../model/db/dao/settings/AppSettingsDao.java | 2 +- .../main/model/db/dao/settings/LdapDao.java | 2 +- .../java/main/model/dto/AppSettingsDto.java | 1 + src/main/java/main/model/dto/LdapDto.java | 1 + src/main/resources/db_changelog/changelog.xml | 1 + .../db_changelog/db.changelog-0.3.8.xml | 163 ++++++++++++++++++ 7 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/db_changelog/db.changelog-0.3.8.xml diff --git a/src/main/java/main/model/db/dao/DAO.java b/src/main/java/main/model/db/dao/DAO.java index dad18d6..68a35c2 100644 --- a/src/main/java/main/model/db/dao/DAO.java +++ b/src/main/java/main/model/db/dao/DAO.java @@ -113,7 +113,7 @@ public T update(T entity) throws AqualityException { try { getEntityById(entity.getId()); } catch (AqualityException e) { - throw new AqualityParametersException("Entity with specified id does not exist!"); + throw new AqualityParametersException("Entity with specified '%s' id does not exist!", entity.getId()); } List> parameters = entity.getParameters(); diff --git a/src/main/java/main/model/db/dao/settings/AppSettingsDao.java b/src/main/java/main/model/db/dao/settings/AppSettingsDao.java index 90b6381..d9da02c 100644 --- a/src/main/java/main/model/db/dao/settings/AppSettingsDao.java +++ b/src/main/java/main/model/db/dao/settings/AppSettingsDao.java @@ -8,6 +8,6 @@ public class AppSettingsDao extends DAO { public AppSettingsDao(){ super(AppSettingsDto.class); insert = "{call INSERT_APP_SETTINGS(?,?,?,?)}"; - select = "{call SELECT_APP_SETTINGS()}"; + select = "{call SELECT_APP_SETTINGS(?)}"; } } diff --git a/src/main/java/main/model/db/dao/settings/LdapDao.java b/src/main/java/main/model/db/dao/settings/LdapDao.java index 29008c8..cb0e5fa 100644 --- a/src/main/java/main/model/db/dao/settings/LdapDao.java +++ b/src/main/java/main/model/db/dao/settings/LdapDao.java @@ -6,7 +6,7 @@ public class LdapDao extends DAO{ public LdapDao() { super(LdapDto.class); - select = "{call SELECT_LDAP_SETTING()}"; + select = "{call SELECT_LDAP_SETTING(?)}"; insert = "{call INSERT_LDAP_SETTING(?,?,?,?,?,?,?,?,?,?,?,?)}"; } } diff --git a/src/main/java/main/model/dto/AppSettingsDto.java b/src/main/java/main/model/dto/AppSettingsDto.java index e1c135b..fb19bc3 100644 --- a/src/main/java/main/model/dto/AppSettingsDto.java +++ b/src/main/java/main/model/dto/AppSettingsDto.java @@ -8,6 +8,7 @@ public class AppSettingsDto extends BaseDto{ @DataBaseName(name = "request_id") @DataBaseInsert + @DataBaseSearchable private Integer id; @DataBaseName(name = "request_ldap_auth") @DataBaseInsert diff --git a/src/main/java/main/model/dto/LdapDto.java b/src/main/java/main/model/dto/LdapDto.java index 97ed7e7..176fb41 100644 --- a/src/main/java/main/model/dto/LdapDto.java +++ b/src/main/java/main/model/dto/LdapDto.java @@ -40,6 +40,7 @@ public class LdapDto extends BaseDto { @DataBaseInsert private String adminSecret; @DataBaseName(name="request_id") + @DataBaseSearchable @DataBaseInsert private Integer id; } diff --git a/src/main/resources/db_changelog/changelog.xml b/src/main/resources/db_changelog/changelog.xml index 1b3344d..f34f22c 100644 --- a/src/main/resources/db_changelog/changelog.xml +++ b/src/main/resources/db_changelog/changelog.xml @@ -30,4 +30,5 @@ + diff --git a/src/main/resources/db_changelog/db.changelog-0.3.8.xml b/src/main/resources/db_changelog/db.changelog-0.3.8.xml new file mode 100644 index 0000000..bb53cfd --- /dev/null +++ b/src/main/resources/db_changelog/db.changelog-0.3.8.xml @@ -0,0 +1,163 @@ + + + + + + + + DROP procedure IF EXISTS `SELECT_LDAP_SETTING`; + + # + + CREATE PROCEDURE `SELECT_LDAP_SETTING`( + IN request_id VARCHAR(10) + ) + BEGIN + SELECT * FROM ldap_settings where empty_or_equal(request_id, id); + END + + + DROP procedure IF EXISTS `SELECT_LDAP_SETTING`; + # + CREATE PROCEDURE `SELECT_LDAP_SETTING`() + BEGIN + SELECT * FROM ldap_settings; + END + + + + + + + DROP procedure IF EXISTS `SELECT_APP_SETTINGS`; + + # + + CREATE PROCEDURE `SELECT_APP_SETTINGS`( + IN request_id VARCHAR(10) + ) + BEGIN + SELECT * FROM app_settings where empty_or_equal(request_id, id); + END + + + DROP procedure IF EXISTS `SELECT_APP_SETTINGS`; + # + CREATE PROCEDURE `SELECT_APP_SETTINGS`() + BEGIN + SELECT * FROM app_settings; + END + + + + + + + DROP procedure IF EXISTS `INSERT_LDAP_SETTING`; + + # + + CREATE PROCEDURE `INSERT_LDAP_SETTING`( + In request_ldapAdServer varchar(300), + IN request_ldapSearchBaseUsers VARCHAR(300), + IN request_security_auntification VARCHAR(45), + IN request_userSearchFilter VARCHAR(300), + IN request_domain VARCHAR(300), + IN request_mailAttribute VARCHAR(45), + IN request_firstNameAttribute VARCHAR(45), + IN request_lastNameAttribute VARCHAR(45), + IN request_userNameAttribute VARCHAR(45), + IN request_adminUserName VARCHAR(150), + IN request_adminSecret VARCHAR(300), + IN request_id VARCHAR(11)) + BEGIN + + INSERT INTO ldap_settings (ldapAdServer,ldapSearchBaseUsers,security_auntification,userSearchFilter,domain,mailAttribute,firstNameAttribute,lastNameAttribute,userNameAttribute,id,adminUserName,adminSecret) + VALUES ( + request_ldapAdServer, + request_ldapSearchBaseUsers, + request_security_auntification, + request_userSearchFilter, + request_domain, + request_mailAttribute, + request_firstNameAttribute, + request_lastNameAttribute, + request_userNameAttribute, + request_id, + request_adminUserName, + request_adminSecret + ) + ON DUPLICATE KEY UPDATE + ldapAdServer= IF(request_ldapAdServer = '', ldapAdServer, request_ldapAdServer), + ldapSearchBaseUsers = IF(request_ldapSearchBaseUsers = '', ldapSearchBaseUsers, request_ldapSearchBaseUsers), + security_auntification = IF(request_security_auntification = '', security_auntification, request_security_auntification), + userSearchFilter = IF(request_userSearchFilter = '', userSearchFilter, request_userSearchFilter), + domain = IF(request_domain = '', domain, request_domain), + mailAttribute = IF(request_mailAttribute = '', mailAttribute, request_mailAttribute), + firstNameAttribute = IF(request_firstNameAttribute='', firstNameAttribute, request_firstNameAttribute), + lastNameAttribute = IF(request_lastNameAttribute='', lastNameAttribute, request_lastNameAttribute), + userNameAttribute = IF(request_userNameAttribute='', userNameAttribute, request_userNameAttribute), + adminUserName = IF(request_adminUserName='', adminUserName, request_adminUserName), + adminSecret = IF(request_adminSecret='', adminSecret, request_adminSecret) + ; + + SET @result_id = IF(request_id = '', LAST_INSERT_ID(), request_id); + SELECT * from ldap_settings where id = @result_id; + + END + + + DROP procedure IF EXISTS `INSERT_LDAP_SETTING`; + # + CREATE PROCEDURE `INSERT_LDAP_SETTING`( + In request_ldapAdServer varchar(300), + IN request_ldapSearchBaseUsers VARCHAR(300), + IN request_security_auntification VARCHAR(45), + IN request_userSearchFilter VARCHAR(300), + IN request_domain VARCHAR(300), + IN request_mailAttribute VARCHAR(45), + IN request_firstNameAttribute VARCHAR(45), + IN request_lastNameAttribute VARCHAR(45), + IN request_userNameAttribute VARCHAR(45), + IN request_adminUserName VARCHAR(150), + IN request_adminSecret VARCHAR(300), + IN request_id VARCHAR(11)) + BEGIN + + INSERT INTO ldap_settings (ldapAdServer,ldapSearchBaseUsers,security_auntification,userSearchFilter,domain,mailAttribute,firstNameAttribute,lastNameAttribute,userNameAttribute,id,adminUserName,adminSecret) + VALUES ( + request_ldapAdServer, + request_ldapSearchBaseUsers, + request_security_auntification, + request_userSearchFilter, + request_domain, + request_mailAttribute, + request_firstNameAttribute, + request_lastNameAttribute, + request_userNameAttribute, + request_id, + request_adminUserName, + request_adminSecret + ) + ON DUPLICATE KEY UPDATE + ldapAdServer= IF(request_ldapAdServer = '', ldapAdServer, request_ldapAdServer), + ldapSearchBaseUsers = IF(request_ldapSearchBaseUsers = '', ldapSearchBaseUsers, request_ldapSearchBaseUsers), + security_auntification = IF(request_security_auntification = '', security_auntification, request_security_auntification), + userSearchFilter = IF(request_userSearchFilter = '', userSearchFilter, request_userSearchFilter), + domain = IF(request_domain = '', domain, request_domain), + mailAttribute = IF(request_mailAttribute = '', mailAttribute, request_mailAttribute), + firstNameAttribute = IF(request_firstNameAttribute='', firstNameAttribute, request_firstNameAttribute), + lastNameAttribute = IF(request_lastNameAttribute='', lastNameAttribute, request_lastNameAttribute), + userNameAttribute = IF(request_userNameAttribute='', userNameAttribute, request_userNameAttribute), + adminUserName = IF(request_adminUserName='', adminUserName, request_adminUserName), + adminSecret = IF(request_adminSecret='', adminSecret, request_adminSecret) + ; + END + + + + From 2fe785270a2ed0571a9e366cda2fb2dddb7d3a53 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Thu, 5 Mar 2020 10:51:44 +0300 Subject: [PATCH 04/17] Fix select procedures without id add override id option --- .../java/main/annotations/OverrideIDName.java | 12 +++ src/main/java/main/model/db/dao/DAO.java | 26 ++++++- .../main/model/db/dao/audit/AuditorsDao.java | 2 +- src/main/java/main/model/dto/AuditorDto.java | 2 + src/main/java/main/model/dto/BaseDto.java | 75 +++++++++++++++++-- .../db_changelog/db.changelog-0.3.8.xml | 24 ++++++ 6 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/main/java/main/annotations/OverrideIDName.java diff --git a/src/main/java/main/annotations/OverrideIDName.java b/src/main/java/main/annotations/OverrideIDName.java new file mode 100644 index 0000000..297d3ba --- /dev/null +++ b/src/main/java/main/annotations/OverrideIDName.java @@ -0,0 +1,12 @@ +package main.annotations; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value= ElementType.FIELD) +@Retention(value= RetentionPolicy.RUNTIME) +public @interface OverrideIDName { +} \ No newline at end of file diff --git a/src/main/java/main/model/db/dao/DAO.java b/src/main/java/main/model/db/dao/DAO.java index 68a35c2..49e6514 100644 --- a/src/main/java/main/model/db/dao/DAO.java +++ b/src/main/java/main/model/db/dao/DAO.java @@ -104,6 +104,22 @@ public T getEntityById(Integer id) throws AqualityException { } } + /** + * Get single entity by id and project_id + * @param entity entity with id and project_id + * @return entity + */ + public T getEntityById(T entity) throws AqualityException { + List> parameters = entity.getIdAndProjectIdSearchParameters(); + List all = dtoMapper.mapObjects(CallStoredProcedure(select, parameters).toString()); + if(!all.isEmpty()) { + return all.get(0); + } + else{ + throw new AqualityException("No Entities was found by id"); + } + } + /** * Update entity * @param entity with fields that should be updated (id is required) @@ -111,9 +127,13 @@ public T getEntityById(Integer id) throws AqualityException { */ public T update(T entity) throws AqualityException { try { - getEntityById(entity.getId()); + if(entity.hasProjectId()){ + getEntityById(entity); + } else { + getEntityById(entity.getIdOrOverrideId()); + } } catch (AqualityException e) { - throw new AqualityParametersException("Entity with specified '%s' id does not exist!", entity.getId()); + throw new AqualityParametersException("Entity with specified '%s' id does not exist!", entity.getIdOrOverrideId()); } List> parameters = entity.getParameters(); @@ -145,7 +165,7 @@ public boolean delete(T entity) throws AqualityException { public T create(T entity) throws AqualityException { Integer id = null; try { - id = entity.getId(); + id = entity.getIdOrOverrideId(); } catch (AqualityException e) { // entity has no id } diff --git a/src/main/java/main/model/db/dao/audit/AuditorsDao.java b/src/main/java/main/model/db/dao/audit/AuditorsDao.java index ff2031e..39d60c7 100644 --- a/src/main/java/main/model/db/dao/audit/AuditorsDao.java +++ b/src/main/java/main/model/db/dao/audit/AuditorsDao.java @@ -11,7 +11,7 @@ public class AuditorsDao extends DAO { public AuditorsDao() { super(AuditorDto.class); - select = "{call SELECT_AUDITOR(?,?)}"; + select = "{call SELECT_AUDITOR(?,?,?)}"; insert = "{call INSERT_AUDITOR(?,?)}"; remove = "{call REMOVE_AUDITOR(?)}"; } diff --git a/src/main/java/main/model/dto/AuditorDto.java b/src/main/java/main/model/dto/AuditorDto.java index cd80d60..56ead0e 100644 --- a/src/main/java/main/model/dto/AuditorDto.java +++ b/src/main/java/main/model/dto/AuditorDto.java @@ -15,6 +15,8 @@ public class AuditorDto extends UserDto { @DataBaseInsert @DataBaseSearchable private Integer id; + @DataBaseSearchable + @OverrideIDName @DataBaseName(name="request_auditor_id") @DataBaseID private Integer auditor_id; diff --git a/src/main/java/main/model/dto/BaseDto.java b/src/main/java/main/model/dto/BaseDto.java index 98f2d0c..cb93dac 100644 --- a/src/main/java/main/model/dto/BaseDto.java +++ b/src/main/java/main/model/dto/BaseDto.java @@ -80,16 +80,50 @@ public List> getDataBaseIDParameters() throws AqualityExcep return list; } + public List> getIdAndProjectIdSearchParameters() throws AqualityException { + List> list = new ArrayList<>(); + List classFields = this.getClassFields(); + for (Field field : classFields) { + DataBaseName nameAnnotation = field.getAnnotation(DataBaseName.class); + DataBaseSearchable searchAnnotation = field.getAnnotation(DataBaseSearchable.class); + if (nameAnnotation != null && searchAnnotation != null) { + try { + field.setAccessible(true); + String value = ""; + if (Objects.equals(field.getName(), "id") || Objects.equals(field.getName(), "project_id")) { + value = getStringValue(field.get(this)); + } + if (nameAnnotation.name().equals("request_limit") && (value.equals("0") || value.equals(""))) { + value = "100000"; + } + Pair pair = new Pair<>(nameAnnotation.name(), value); + list.add(pair); + + } catch (IllegalAccessException e) { + throw new AqualityException(String.format("Cannot read Field: %s", field.getName())); + } + } + } + + if (list.isEmpty()) { + throw new AqualityException("Entity has no id parameter"); + } + + return list; + } + public List> getIdSearchParameters(Integer id) throws AqualityException { List> list = new ArrayList<>(); List classFields = this.getClassFields(); + boolean hasOverrideIdAnnotation = hasOverrideIdAnnotation(OverrideIDName.class); for (Field field: classFields) { DataBaseName nameAnnotation = field.getAnnotation(DataBaseName.class); DataBaseSearchable searchAnnotation = field.getAnnotation(DataBaseSearchable.class); + OverrideIDName override = field.getAnnotation(OverrideIDName.class); if(nameAnnotation != null && searchAnnotation != null){ field.setAccessible(true); String value = ""; - if(Objects.equals(field.getName(), "id")) { + if((Objects.equals(field.getName(), "id") && !hasOverrideIdAnnotation) || override != null) { value = id.toString(); } if(nameAnnotation.name().equals("request_limit") && (value.equals("0") || value.equals(""))){ @@ -107,24 +141,43 @@ public List> getIdSearchParameters(Integer id) throws Aqual return list; } - public Integer getId() throws AqualityException { + public Integer getIdOrOverrideId() throws AqualityException { List classFields = this.getClassFields(); + boolean hasOverrideIdAnnotation = hasOverrideIdAnnotation(OverrideIDName.class); for (Field field: classFields) { field.setAccessible(true); - if(Objects.equals(field.getName(), "id")) { - Object value; + OverrideIDName override = field.getAnnotation(OverrideIDName.class); + if((Objects.equals(field.getName(), "id") && !hasOverrideIdAnnotation) || override != null) { + String value; try { - value = field.get(this); + value = getStringValue(field.get(this)); } catch (IllegalAccessException e) { throw new AqualityException(String.format("Cannot read Field: %s", field.getName())); } - return Integer.valueOf(getStringValue(value)); + return value.isEmpty() ? null : Integer.valueOf(value); } } throw new AqualityException("Entity has no id parameter"); } + public boolean hasProjectId() throws AqualityException { + List classFields = this.getClassFields(); + for (Field field: classFields) { + field.setAccessible(true); + if(Objects.equals(field.getName(), "project_id")) { + Object value; + try { + value = field.get(this); + } catch (IllegalAccessException e) { + throw new AqualityException(String.format("Cannot read Field: %s", field.getName())); + } + return !getStringValue(value).isEmpty(); + } + } + return false; + } + public void getSearchTemplateFromRequestParameters(@NotNull HttpServletRequest req) throws AqualityException { getTemplate(req, DataBaseSearchable.class); } @@ -160,6 +213,16 @@ private boolean hasIdAnnotation(Class dataBaseIDClass){ return false; } + private boolean hasOverrideIdAnnotation(Class dataBaseIDClass){ + List classFields = this.getClassFields(); + for (Field field: classFields) { + if(field.getAnnotation(dataBaseIDClass) != null){ + return true; + } + } + return false; + } + private List getClassFields(){ List declaredFields = new ArrayList<>(); Class superclass = this.getClass(); diff --git a/src/main/resources/db_changelog/db.changelog-0.3.8.xml b/src/main/resources/db_changelog/db.changelog-0.3.8.xml index bb53cfd..126d8c4 100644 --- a/src/main/resources/db_changelog/db.changelog-0.3.8.xml +++ b/src/main/resources/db_changelog/db.changelog-0.3.8.xml @@ -160,4 +160,28 @@ + + + + DROP procedure IF EXISTS `SELECT_AUDITOR`; + + # + CREATE PROCEDURE `SELECT_AUDITOR`( + In request_audit_id varchar(11), + In request_user_id varchar(11), + In request_auditor_id varchar(11) + ) + BEGIN + SELECT * FROM auditor_assignments + LEFT JOIN users ON auditor_assignments.user_id=users.id + WHERE empty_or_equal(request_audit_id, auditor_assignments.audit_id) + AND empty_or_equal(request_user_id, auditor_assignments.user_id) + AND empty_or_equal(request_auditor_id, auditor_assignments.auditor_id) + ; + END + + + + + From 50fc5f2324993ff78abb39cc16739f02ee353d8f Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Thu, 5 Mar 2020 15:58:18 +0300 Subject: [PATCH 05/17] Fix pr comments --- src/main/java/main/model/db/dao/DAO.java | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/main/model/db/dao/DAO.java b/src/main/java/main/model/db/dao/DAO.java index 49e6514..a2dcb88 100644 --- a/src/main/java/main/model/db/dao/DAO.java +++ b/src/main/java/main/model/db/dao/DAO.java @@ -96,12 +96,8 @@ public T getEntityById(Integer id) throws AqualityException { List> parameters = entity.getIdSearchParameters(id); List all = dtoMapper.mapObjects(CallStoredProcedure(select, parameters).toString()); - if(!all.isEmpty()) { - return all.get(0); - } - else{ - throw new AqualityException("No Entities was found by id"); - } + + return getSingleResult(all, id); } /** @@ -112,12 +108,8 @@ public T getEntityById(Integer id) throws AqualityException { public T getEntityById(T entity) throws AqualityException { List> parameters = entity.getIdAndProjectIdSearchParameters(); List all = dtoMapper.mapObjects(CallStoredProcedure(select, parameters).toString()); - if(!all.isEmpty()) { - return all.get(0); - } - else{ - throw new AqualityException("No Entities was found by id"); - } + + return getSingleResult(all, entity.getIdOrOverrideId()); } /** @@ -225,6 +217,15 @@ protected JSONArray CallStoredProcedure(String sql, List> p return json; } + private T getSingleResult(List allResults, Integer id) throws AqualityException { + if(!allResults.isEmpty()) { + return allResults.get(0); + } + else{ + throw new AqualityException("No Entities was found by '%s' id", id); + } + } + private void getConnection() throws AqualityException { InitialContext initialContext; try { From 2cf4f99ada54ba10f07655bc89d05256f2c0ec29 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Fri, 6 Mar 2020 15:17:30 +0300 Subject: [PATCH 06/17] Update swagger with statistic endpoints --- .../Project/TestRunController.java | 11 +- .../TestResultStatisticServlet.java | 2 +- .../TestRunStatisticServlet.java | 2 +- .../TestSuiteStatisticServlet.java} | 6 +- src/main/webapp/doc/api-doc.yaml | 779 +++++++++++------- 5 files changed, 481 insertions(+), 319 deletions(-) rename src/main/java/main/view/Project/{ => statistic}/TestResultStatisticServlet.java (97%) rename src/main/java/main/view/Project/{ => statistic}/TestRunStatisticServlet.java (97%) rename src/main/java/main/view/Project/{TestSuiteStatServlet.java => statistic/TestSuiteStatisticServlet.java} (90%) diff --git a/src/main/java/main/controllers/Project/TestRunController.java b/src/main/java/main/controllers/Project/TestRunController.java index a80645f..ebbcb1b 100644 --- a/src/main/java/main/controllers/Project/TestRunController.java +++ b/src/main/java/main/controllers/Project/TestRunController.java @@ -62,7 +62,16 @@ public List get(TestRunLabelDto template) throws AqualityExcept } public List get(TestRunStatisticDto template) throws AqualityException { - return testRunStatisticDao.searchAll(template); + TestRunDto testRunDto = new TestRunDto(); + testRunDto.setId(template.getId()); + Integer projectId = template.getId() != null + ? testRunDto.getProjectIdById() + : template.getProject_id(); + if (baseUser.isFromGlobalManagement() || baseUser.getProjectUser(projectId).isViewer()) { + return testRunStatisticDao.searchAll(template); + } else { + throw new AqualityPermissionsException("Account is not allowed to view Test Run Statistic", baseUser); + } } public TestRunDto getLastSuiteTestRun(Integer suiteId, Integer projectId) throws AqualityException { diff --git a/src/main/java/main/view/Project/TestResultStatisticServlet.java b/src/main/java/main/view/Project/statistic/TestResultStatisticServlet.java similarity index 97% rename from src/main/java/main/view/Project/TestResultStatisticServlet.java rename to src/main/java/main/view/Project/statistic/TestResultStatisticServlet.java index fe32de1..99a532b 100644 --- a/src/main/java/main/view/Project/TestResultStatisticServlet.java +++ b/src/main/java/main/view/Project/statistic/TestResultStatisticServlet.java @@ -1,4 +1,4 @@ -package main.view.Project; +package main.view.Project.statistic; import main.Session; import main.model.dto.TestResultDto; diff --git a/src/main/java/main/view/Project/TestRunStatisticServlet.java b/src/main/java/main/view/Project/statistic/TestRunStatisticServlet.java similarity index 97% rename from src/main/java/main/view/Project/TestRunStatisticServlet.java rename to src/main/java/main/view/Project/statistic/TestRunStatisticServlet.java index a2a3cce..43c8dd9 100644 --- a/src/main/java/main/view/Project/TestRunStatisticServlet.java +++ b/src/main/java/main/view/Project/statistic/TestRunStatisticServlet.java @@ -1,4 +1,4 @@ -package main.view.Project; +package main.view.Project.statistic; import main.Session; import main.model.dto.TestRunDto; diff --git a/src/main/java/main/view/Project/TestSuiteStatServlet.java b/src/main/java/main/view/Project/statistic/TestSuiteStatisticServlet.java similarity index 90% rename from src/main/java/main/view/Project/TestSuiteStatServlet.java rename to src/main/java/main/view/Project/statistic/TestSuiteStatisticServlet.java index d2c951f..fc55369 100644 --- a/src/main/java/main/view/Project/TestSuiteStatServlet.java +++ b/src/main/java/main/view/Project/statistic/TestSuiteStatisticServlet.java @@ -1,4 +1,4 @@ -package main.view.Project; +package main.view.Project.statistic; import main.Session; import main.model.dto.SuiteStatisticDto; @@ -12,8 +12,8 @@ import java.nio.charset.StandardCharsets; import java.util.List; -@WebServlet("/suite/stat") -public class TestSuiteStatServlet extends BaseServlet implements IGet { +@WebServlet("/stats/suite") +public class TestSuiteStatisticServlet extends BaseServlet implements IGet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp){ diff --git a/src/main/webapp/doc/api-doc.yaml b/src/main/webapp/doc/api-doc.yaml index 3c5e7c4..0ddb523 100644 --- a/src/main/webapp/doc/api-doc.yaml +++ b/src/main/webapp/doc/api-doc.yaml @@ -4,7 +4,10 @@ openapi: 3.0.0 info: description: | Documentation for Aquality Tracker API. - version: '0.3.6' + To Authorize you can use API token that you can create in Aquality Tracking Administration + - As user name you should use `project:{your project id}` + - As password you should use API token + version: '0.3.8' title: 'Aquality Tracker - API documentation' servers: @@ -23,6 +26,8 @@ security: tags: - name: 'public' description: 'Public API to simplify results import' + - name: 'stats' + description: 'Overal statistic info' - name: 'import' description: 'Import operations' - name: 'suite' @@ -41,8 +46,6 @@ tags: description: 'Operations with Tests' - name: 'project' description: 'Operations with Projects' - - name: 'stats' - description: 'Operations with Statistics' - name: 'users' description: 'Operations with Users' - name: 'settings' @@ -82,20 +85,28 @@ paths: responses: 200: description: 'Test Suite was created/updated (ID of created/updated Test Suite is in the `id` header).' - schema: - $ref: '#/definitions/TestSuite' + content: + application/json: + schema: + $ref: '#/definitions/TestSuite' 400: description: 'You have missed one of required parameters you should specify `project_id` AND (`name` AND/OR `id`)' - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 401: description: "You've missed your authorization header!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 403: description: "You have no permissions for selected project!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' /public/test/create-or-update: post: security: @@ -134,20 +145,28 @@ paths: responses: 200: description: 'Test Suite was created/updated. The Test JSON will be returned in body' - schema: - $ref: '#/definitions/Test' + content: + application/json: + schema: + $ref: '#/definitions/Test' 400: description: 'You have missed one of required parameters you should specify `project_id` AND (`name` AND/OR `id`) AND `suites`' - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 401: description: "You've missed your authorization header!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 403: description: "You have no permissions for selected project!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' /public/testrun/start: post: security: @@ -196,20 +215,28 @@ paths: responses: 200: description: 'Test Run was created and Started. The Test JSON will be returned in body' - schema: - $ref: '#/definitions/Test' + content: + application/json: + schema: + $ref: '#/definitions/Test' 400: description: 'You have missed one of required parameters you should specify `project_id` AND `build_name` AND `test_suite_id`' - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 401: description: "You've missed your authorization header!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 403: description: "You have no permissions for selected project!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' /public/testrun/finish: get: security: @@ -235,20 +262,28 @@ paths: responses: 200: description: 'Test Suite was finished. The Test JSON will be returned in body' - schema: - $ref: '#/definitions/Test' + content: + application/json: + schema: + $ref: '#/definitions/Test' 400: description: 'You have missed one of required parameters you should specify `project_id` AND `id`' - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 401: description: "You've missed your authorization header!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 403: description: "You have no permissions for selected project!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' /public/test/result/start: get: security: @@ -279,20 +314,28 @@ paths: responses: 200: description: 'Test Result was started. The Test Result JSON will be returned in body' - schema: - $ref: '#/definitions/TestResult' + content: + application/json: + schema: + $ref: '#/definitions/TestResult' 400: description: 'You have missed one of required parameters you should specify `project_id` AND `test_id` AND `test_run_id`' - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 401: description: "You've missed your authorization header!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' 403: description: "You have no permissions for selected project!" - schema: - $ref: '#/definitions/Error' + content: + application/json: + schema: + $ref: '#/definitions/Error' /public/test/result/finish: post: security: @@ -334,20 +377,185 @@ paths: responses: 200: description: 'Test result was finished. The Test JSON will be returned in body' - schema: - $ref: '#/definitions/TestResult' + content: + application/json: + schema: + $ref: '#/definitions/TestResult' 400: description: 'You have missed one of required parameters you should specify `project_id` AND `id` AND `final_result_id`' + content: + application/json: + schema: + $ref: '#/definitions/Error' + 401: + description: "You've missed your authorization header!" + content: + application/json: + schema: + $ref: '#/definitions/Error' + 403: + description: "You have no permissions for selected project!" + content: + application/json: + schema: + $ref: '#/definitions/Error' + + /stats/testrun: + get: + tags: + - 'stats' + summary: 'Get Test Runs statistic' + description: 'Test Runs statistic information' + produces: + - 'application/json' + parameters: + - in: query + name: id schema: - $ref: '#/definitions/Error' + type: integer + description: 'Test Run ID - will return stats for one specific test run' + - in: query + name: test_suite_id + schema: + type: integer + description: 'Suite ID - will return stats for one specific suite' + - in: query + name: project_id + required: true + schema: + type: integer + description: 'Project ID' + - in: query + name: debug + schema: + type: integer + description: '1 - Only debug test runs, 0 - Only non debug test runs' + responses: + 200: + description: 'Test Runs statistic' + content: + application/json: + schema: + type: array + items: + $ref: '#/definitions/TestRunStatistic' + 400: + description: 'You have missed one of required parameters you should specify `project_id`' + content: + application/json: + schema: + $ref: '#/definitions/Error' 401: description: "You've missed your authorization header!" + content: + application/json: + schema: + $ref: '#/definitions/Error' + 403: + description: "You have no permissions for selected project!" + content: + application/json: + schema: + $ref: '#/definitions/Error' + /stats/testresult: + get: + tags: + - 'stats' + summary: 'Get Test Results statistic' + description: 'Test Results statistic information' + produces: + - 'application/json' + parameters: + - in: query + name: project_id + required: true schema: - $ref: '#/definitions/Error' + type: integer + description: 'Project ID' + - in: query + name: testRunStartedFrom + schema: + type: string + description: 'Date string. e.g. 2020-03-06T21:00:00.000Z' + - in: query + name: testRunStartedTo + schema: + type: string + description: 'Date string. e.g. 2020-03-06T21:00:00.000Z' + responses: + 200: + description: 'Test Results statistic' + content: + application/json: + schema: + type: array + items: + $ref: '#/definitions/TestResultStatistic' + 400: + description: 'You have missed one of required parameters you should specify `project_id`' + content: + application/json: + schema: + $ref: '#/definitions/Error' + 401: + description: "You've missed your authorization header!" + content: + application/json: + schema: + $ref: '#/definitions/Error' 403: description: "You have no permissions for selected project!" + content: + application/json: + schema: + $ref: '#/definitions/Error' + /stats/suite: + get: + tags: + - 'stats' + summary: 'Get Test Suite statistic' + description: 'Test Suites statistic information' + produces: + - 'application/json' + parameters: + - in: query + name: project_id + required: true + schema: + type: integer + description: 'Project ID' + - in: query + name: suiteId schema: - $ref: '#/definitions/Error' + type: integer + description: 'Suite ID' + responses: + 200: + description: 'Test Suites statistic' + content: + application/json: + schema: + type: array + items: + $ref: '#/definitions/TestSuiteStatistic' + 400: + description: 'You have missed one of required parameters you should specify `project_id`' + content: + application/json: + schema: + $ref: '#/definitions/Error' + 401: + description: "You've missed your authorization header!" + content: + application/json: + schema: + $ref: '#/definitions/Error' + 403: + description: "You have no permissions for selected project!" + content: + application/json: + schema: + $ref: '#/definitions/Error' /import: post: @@ -775,107 +983,6 @@ paths: responses: 200: description: 'Result Resolution was removed' - /stats/testrun: - get: - tags: - - 'stats' - summary: 'Get statistics for Test Runs' - description: 'Test Runs stats' - produces: - - 'application/json' - parameters: - - in: query - name: id - schema: - type: integer - description: 'Test Run ID' - - in: query - name: test_suite_id - schema: - type: integer - description: 'Suite ID' - - in: query - name: project_id - schema: - type: integer - description: 'Project ID' - responses: - 200: - description: 'Test Suite stats' - schema: - schema: - type: object - properties: - id: - schema: - type: integer - description: 'Test Run ID' - build_name: - schema: - type: string - milestone_id: - schema: - type: integer - test_suite_id: - schema: - type: integer - project_id: - schema: - type: integer - execution_environment: - schema: - type: string - debug: - schema: - type: integer - start_time: - schema: - type: string - description: 'Test Run start time' - finish_time: - schema: - type: string - description: 'Test Run finish time' - passed: - schema: - type: integer - description: 'Number of passed tests (`final_results` table)' - failed: - schema: - type: integer - description: 'Number of failed tests (`final_results` table)' - not_executed: - schema: - type: integer - description: 'Number of not executed tests (`final_results` table)' - in_progress: - schema: - type: integer - description: 'Number of tests in progress (`final_results` table)' - pending: - schema: - type: integer - description: 'Number of pending tests (`final_results` table)' - total: - schema: - type: integer - description: 'Total number of tests in Test Run' - app_issue: - schema: - type: integer - description: 'Number of tests having "Application Issue" resolution (`result_resolution` table)' - warning: - schema: - type: integer - description: 'Number of tests having "Environment Issue", "Test Issue" or "Test Design Issue" resolution (`result_resolution` table)' - not_assigned: - schema: - type: integer - description: 'Number of failed tests not assigned to anyone' - other: - schema: - type: integer - description: 'Number of results with not warning or error of not assigned Resolutions' /suite: get: tags: @@ -1746,302 +1853,348 @@ paths: definitions: Error: - schema: - type: object + type: object properties: message: type: string FinalResult: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer name: - schema: - type: string + type: string color: - schema: - type: integer + type: integer Milestone: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer name: - schema: - type: string + type: string project_id: - schema: - type: integer + type: integer Project: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer name: - schema: - type: string + type: string TestSuite: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer name: - schema: - type: string + type: string project_id: - schema: - type: integer + type: integer tests: - schema: - type: array + type: array description: 'List of Tests in Suite. Optional.' items: $ref: '#definitions/Test' TestRun: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer build_name: - schema: - type: string + type: string milestone_id: - schema: - type: integer + type: integer test_suite_id: - schema: - type: integer + type: integer project_id: - schema: - type: integer + type: integer execution_environment: - schema: - type: string + type: string start_time: - schema: - type: string + type: string finish_time: - schema: - type: string + type: string author: - schema: - type: string + type: string debug: - schema: - type: integer + type: integer ci_build: - schema: - type: string + type: string testResults: - schema: - type: array + type: array description: 'List of Test Results in Suite. Optional.' items: $ref: '#definitions/TestResult' User: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer first_name: - schema: - type: string + type: string second_name: - schema: - type: string + type: string user_name: - schema: - type: string + type: string pass: - schema: - type: string + type: string description: 'MD5 hash of user password' updated: - schema: - type: integer + type: integer description: 'Last update date' session_code: - schema: - type: string + type: string description: 'Code of the user session' session_created: - schema: - type: string + type: string description: 'Date of the user session start' admin: - schema: - type: string + type: string description: 'Indication that user has Admin role' manager: - schema: - type: string + type: string description: 'Indication that user has Manager role' ProjectUser: - schema: - type: object + type: object properties: user: - schema: - type: object + type: object $ref: '#definitions/User' project_id: - schema: - type: integer + type: integer admin: - schema: - type: integer + type: integer manager: - schema: - type: integer + type: integer engineer: - schema: - type: integer + type: integer viewer: - schema: - type: integer + type: integer ResultResolution: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer name: - schema: - type: string + type: string color: - schema: - type: integer + type: integer project_id: - schema: - type: integer + type: integer Test: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer name: - schema: - type: string + type: string body: - schema: - type: string + type: string test_suite_id: - schema: - type: integer + type: integer project_id: - schema: - type: integer + type: integer manual_duration: - schema: - type: string + type: string developer: - schema: - type: integer + type: integer results: - schema: - type: array + type: array description: 'List of Test Results for Test. Optional.' items: $ref: '#definitions/TestResult' ImportDto: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer project_id: - schema: - type: integer + type: integer description: 'ID of related Project' testrun_id: - schema: - type: integer + type: integer description: 'ID of related Test Run' is_finished: - schema: - type: integer + type: integer description: '1 if finished and 0 if not' started: - schema: - type: string + type: string description: 'Started (format: yyyy-MM-dd HH:mm:ss)' finished: - schema: - type: string + type: string description: 'Finished (format: yyyy-MM-dd HH:mm:ss)' log: - schema: - type: string + type: string description: 'Logs' TestResult: - schema: - type: object + type: object properties: id: - schema: - type: integer + type: integer project_id: - schema: - type: integer + type: integer description: 'ID of related Project' test: $ref: '#definitions/Test' final_result: $ref: '#definitions/FinalResult' comment: - schema: - type: string + type: string description: 'Comment regarding Test Result' test_run_id: - schema: - type: integer + type: integer description: 'ID of related Test Run' test_resolution: $ref: '#definitions/ResultResolution' debug: - schema: - type: integer + type: integer description: 'Debug flag' updated: - schema: - type: string + type: string description: 'Test Result last update date (format: yyyy-MM-dd HH:mm:ss)' log: - schema: - type: string + type: string description: 'Log of the Test' start_date: - schema: - type: string + type: string description: 'Test start date (format: yyyy-MM-dd HH:mm:ss)' finish_date: - schema: - type: string + type: string description: 'Test finish date (format: yyyy-MM-dd HH:mm:ss)' final_result_updated: - schema: - type: string + type: string description: 'Test Final Result last update date (format: yyyy-MM-dd HH:mm:ss)' fail_reason: - schema: - type: string + type: string description: 'Description of the fail reason' assigned_user: $ref: '#definitions/ProjectUser' + TestRunStatistic: + type: object + properties: + id: + type: integer + example: 1 + description: 'Test Run ID' + build_name: + type: string + example: 'build_1' + milestone_id: + type: integer + example: 1 + test_suite_id: + type: integer + example: 1 + project_id: + type: integer + example: 1 + execution_environment: + type: string + example: 'Chrome win 10' + debug: + type: integer + example: 1 + start_time: + type: integer + description: 'Test Run start time' + example: 1583491768000 + finish_time: + type: integer + description: 'Test Run finish time' + example: 1583491768000 + passed: + type: integer + description: 'Number of passed tests (`final_results` table)' + example: 1 + failed: + type: integer + description: 'Number of failed tests (`final_results` table)' + example: 1 + not_executed: + type: integer + description: 'Number of not executed tests (`final_results` table)' + example: 1 + in_progress: + type: integer + description: 'Number of tests in progress (`final_results` table)' + example: 1 + pending: + type: integer + description: 'Number of pending tests (`final_results` table)' + example: 1 + total: + type: integer + description: 'Total number of tests in Test Run' + example: 1 + app_issue: + type: integer + description: 'Number of tests having "Red" resolution color' + example: 1 + warning: + type: integer + description: 'Number of tests having "Orange" resolution color' + example: 1 + not_assigned: + type: integer + description: 'Number of failed tests "Blue" resolution color' + example: 1 + other: + type: integer + description: 'Number of results with not "Red", "Orange", "Blue" colors' + example: 1 + TestResultStatistic: + type: object + properties: + test_run_id: + type: integer + example: 1 + description: 'Test Run ID' + test_run_started: + type: integer + description: 'Test Run start time' + example: 1583491768000 + name: + type: string + example: 'Test Feature with all results: All passed' + status: + type: string + example: 'Passed' + resolution: + type: string + example: 'Not Assigned' + TestSuiteStatistic: + type: object + properties: + id: + type: integer + example: 1 + description: 'Test ID' + name: + type: string + description: 'Test name' + example: 'Test Feature with all results: All passed' + total_runs: + type: integer + description: 'Total executions number' + example: 10 + passed: + type: integer + example: 3 + description: 'Total passed number' + failed: + type: integer + example: 7 + description: 'Total failed number' + app_issue: + type: integer + example: 3 + description: 'Total app issues number' + autotest_issue: + type: integer + example: 3 + description: 'Total autotest issues number' + resolution_na: + type: integer + example: 1 + description: 'Total results number with not assigned resolutions' \ No newline at end of file From 11095510c8f543379f347bf844545e73f69056ea Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Fri, 6 Mar 2020 15:21:56 +0300 Subject: [PATCH 07/17] add changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fb81e8..3b0f384 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 0.3.8 (Unreleased) + +Features: + - [Doc] Update Swagger -> View Issue + ## 0.3.7 (2020-03-02) Features: From 339d7d3679e450ee75d3e6c89fcf4ffb802c5a9a Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Fri, 6 Mar 2020 15:23:32 +0300 Subject: [PATCH 08/17] Update change log --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b0f384..e82aee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## 0.3.8 (Unreleased) Features: - - [Doc] Update Swagger -> View Issue + - [Doc] Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76) ## 0.3.7 (2020-03-02) From 06a8a9afde37b6e9eb5fcdce18e643752db98a5e Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Fri, 6 Mar 2020 16:51:46 +0300 Subject: [PATCH 09/17] fix deadlock --- CHANGELOG.md | 2 ++ src/main/java/main/model/db/dao/DAO.java | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e82aee0..cd331fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Features: - [Doc] Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76) +Features: + - [BUG] Import was finished with Error! You are trying to edit entity which is locked -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/44) ## 0.3.7 (2020-03-02) Features: diff --git a/src/main/java/main/model/db/dao/DAO.java b/src/main/java/main/model/db/dao/DAO.java index a2dcb88..869a2fa 100644 --- a/src/main/java/main/model/db/dao/DAO.java +++ b/src/main/java/main/model/db/dao/DAO.java @@ -270,13 +270,22 @@ private CallableStatement executeCallableStatement(String sql, List Date: Mon, 9 Mar 2020 19:41:23 +0300 Subject: [PATCH 10/17] Save Work --- CHANGELOG.md | 3 +- .../main/model/db/imports/BaseImporter.java | 16 +-- .../java/main/model/db/imports/Handler.java | 4 + .../main/model/db/imports/HandlerFactory.java | 5 +- .../db/imports/ImportHandlers/Cucumber.java | 16 +-- .../db/imports/ImportHandlers/JavaTestNG.java | 4 + .../db/imports/ImportHandlers/NUnitV2.java | 4 + .../db/imports/ImportHandlers/NUnitV3.java | 4 + .../ImportHandlers/PHPCodeception.java | 4 + .../db/imports/ImportHandlers/Robot.java | 4 + .../model/db/imports/ImportHandlers/TRX.java | 4 + .../java/main/model/db/imports/Importer.java | 70 +++++++--- .../SAXHandlers/JavaTestNGHandler.java | 9 +- .../imports/SAXHandlers/NUnitV2Handler.java | 3 - .../imports/SAXHandlers/NUnitV3Handler.java | 1 - .../SAXHandlers/PHPCodeceptionHandler.java | 2 - .../db/imports/SAXHandlers/RobotHandler.java | 9 +- .../db/imports/SAXHandlers/TRXHandler.java | 8 +- src/main/java/main/utils/DateUtils.java | 9 +- src/main/java/main/utils/FileUtils.java | 4 + .../workers/imports/CucumberHandlerTest.java | 59 +++++++++ .../tests/workers/imports/ImporterTest.java | 4 + .../resources/reports/cucumber/cucumber.json | 121 ++++++++++++++++++ .../resources/reports/cucumber/suite.json | 1 + .../reports/cucumber/testResults.json | 1 + .../resources/reports/cucumber/testRun.json | 1 + .../resources/reports/cucumber/tests.json | 1 + 27 files changed, 315 insertions(+), 56 deletions(-) create mode 100644 src/test/java/tests/workers/imports/CucumberHandlerTest.java create mode 100644 src/test/java/tests/workers/imports/ImporterTest.java create mode 100644 src/test/resources/reports/cucumber/cucumber.json create mode 100644 src/test/resources/reports/cucumber/suite.json create mode 100644 src/test/resources/reports/cucumber/testResults.json create mode 100644 src/test/resources/reports/cucumber/testRun.json create mode 100644 src/test/resources/reports/cucumber/tests.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cd331fa..e59c6f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,9 @@ Features: - [Doc] Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76) -Features: +Bugfixes: - [BUG] Import was finished with Error! You are trying to edit entity which is locked -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/44) + ## 0.3.7 (2020-03-02) Features: diff --git a/src/main/java/main/model/db/imports/BaseImporter.java b/src/main/java/main/model/db/imports/BaseImporter.java index f0f9cf1..9d12f7f 100644 --- a/src/main/java/main/model/db/imports/BaseImporter.java +++ b/src/main/java/main/model/db/imports/BaseImporter.java @@ -88,6 +88,7 @@ private void updateImportTestRun() throws AqualityException { } void logToImport(String log) throws AqualityException { + importDto.setProject_id(this.projectId); importDto.addToLog(log); importDto = importDao.create(importDto); } @@ -105,22 +106,15 @@ private void createTestRun() throws AqualityException { } } else{ - createTestRun((testRun.getBuild_name() != null && !testRun.getBuild_name().equals("")) - ? testRun.getBuild_name() - : file.getName().substring(0, file.getName().lastIndexOf("."))); + setTestRunStartDate(); + setTestRunFinishDate(); + testRun.setTest_suite_id(testSuite.getId()); + testRun.setId(controllerFactory.getHandler(testRun).create(testRun).getId()); } updateImportTestRun(); logToImport("Test Run is updated."); } - private void createTestRun(String buildName) throws AqualityException { - testRun.setBuild_name(buildName); - setTestRunStartDate(); - setTestRunFinishDate(); - testRun.setTest_suite_id(testSuite.getId()); - testRun.setId(controllerFactory.getHandler(testRun).create(testRun).getId()); - } - private void setTestRunStartDate(){ Comparator startDate = Comparator.comparing(TestResultDto::getStart_date); if(testRun.getStart_time() == null){ diff --git a/src/main/java/main/model/db/imports/Handler.java b/src/main/java/main/model/db/imports/Handler.java index 6d9e2e9..58fd42a 100644 --- a/src/main/java/main/model/db/imports/Handler.java +++ b/src/main/java/main/model/db/imports/Handler.java @@ -16,6 +16,7 @@ public abstract class Handler extends DefaultHandler { protected SAXParser parser; + protected TestRunDto testRun = new TestRunDto(); public Handler() throws AqualityException { try { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); @@ -33,4 +34,7 @@ public Handler() throws AqualityException { public abstract TestRunDto getTestRun(); public abstract List getTests(); public abstract List getTestResults(); + public void setTestRun(TestRunDto testRun){ + this.testRun = testRun; + } } diff --git a/src/main/java/main/model/db/imports/HandlerFactory.java b/src/main/java/main/model/db/imports/HandlerFactory.java index dbbda06..913516f 100644 --- a/src/main/java/main/model/db/imports/HandlerFactory.java +++ b/src/main/java/main/model/db/imports/HandlerFactory.java @@ -4,9 +4,10 @@ import main.model.db.imports.ImportHandlers.*; import java.io.File; +import java.util.Date; class HandlerFactory { - Handler getHandler(File file, String type, TestNameNodeType testNameNodeType) throws AqualityException { + Handler getHandler(File file, String type, TestNameNodeType testNameNodeType, Date finishTime) throws AqualityException { switch (ImportTypes.valueOf(type)){ case MSTest: if(testNameNodeType == null){ @@ -23,7 +24,7 @@ Handler getHandler(File file, String type, TestNameNodeType testNameNodeType) th return new JavaTestNG(file, testNameNodeType); case Cucumber: case TestNGCucumber: - return new Cucumber(file); + return new Cucumber(file, finishTime); case PHPCodeception: return new PHPCodeception(file); case NUnit_v2: diff --git a/src/main/java/main/model/db/imports/ImportHandlers/Cucumber.java b/src/main/java/main/model/db/imports/ImportHandlers/Cucumber.java index ae950be..3d8674a 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/Cucumber.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/Cucumber.java @@ -16,23 +16,23 @@ public class Cucumber extends Handler{ private List features; - private TestRunDto testRun; private List tests = new ArrayList<>(); private List results = new ArrayList<>(); private DateUtils dateUtils = new DateUtils(); private FeatureDto currentFeature; private TestResultDto currentResult; private Integer testTime = 0; - private Date dateCounter = new Date(); + private Date dateCounter; private boolean previousWasBackground = false; private TestDto currentTest; - public Cucumber(@NotNull File file) throws AqualityException { + public Cucumber(@NotNull File file, Date finishTime) throws AqualityException { super(); FileUtils fileUtils = new FileUtils(); String json = fileUtils.readFile(file.getPath()); CucumberUtils cucumberUtils = new CucumberUtils(json); this.features = cucumberUtils.getFeatures(); + dateCounter = finishTime; parse(); } @@ -42,9 +42,9 @@ private void parse() { private void handleTestRun() { testRun = new TestRunDto(); - testRun.setStart_time(dateCounter); - features.forEach(this::handleFeature); testRun.setFinish_time(dateCounter); + features.forEach(this::handleFeature); + testRun.setStart_time(dateCounter); } private void handleFeature(@NotNull FeatureDto feature) { @@ -72,14 +72,14 @@ private void handleScenario(@NotNull ScenarioDto scenario) { String[] strings = scenario.getId().split(";;"); currentTest.setName(String.format("%s: %s%s", currentFeature.getName(), scenario.getName(), strings.length > 1 ? String.format(": %s", strings[1]) : "")); - currentResult.setStart_date(dateCounter); + currentResult.setFinish_date(dateCounter); if(currentResult.getFail_reason() == null) currentResult.setFail_reason(""); if(scenario.getBefore() != null) scenario.getBefore().forEach(this::handleStep); scenario.getSteps().forEach(this::handleStep); if(scenario.getAfter() != null) scenario.getAfter().forEach(this::handleStep); - dateCounter = dateUtils.addMS(dateCounter, testTime); + dateCounter = dateUtils.removeMS(dateCounter, testTime); + currentResult.setStart_date(dateCounter); testTime = 0; - currentResult.setFinish_date(dateCounter); tests.add(currentTest); results.add(currentResult); } else { diff --git a/src/main/java/main/model/db/imports/ImportHandlers/JavaTestNG.java b/src/main/java/main/model/db/imports/ImportHandlers/JavaTestNG.java index 6ecffcb..c9fdec9 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/JavaTestNG.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/JavaTestNG.java @@ -45,4 +45,8 @@ public List getTests() { public List getTestResults() { return handler.getTestResults(); } + + public void setTestRun(TestRunDto testRun){ + handler.setTestRun(testRun); + } } diff --git a/src/main/java/main/model/db/imports/ImportHandlers/NUnitV2.java b/src/main/java/main/model/db/imports/ImportHandlers/NUnitV2.java index 1364a5e..d272ea7 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/NUnitV2.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/NUnitV2.java @@ -45,4 +45,8 @@ public List getTests() { public List getTestResults() { return handler.getTestResults(); } + + public void setTestRun(TestRunDto testRun){ + handler.setTestRun(testRun); + } } diff --git a/src/main/java/main/model/db/imports/ImportHandlers/NUnitV3.java b/src/main/java/main/model/db/imports/ImportHandlers/NUnitV3.java index 18727dc..17669a7 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/NUnitV3.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/NUnitV3.java @@ -46,4 +46,8 @@ public List getTests() { public List getTestResults() { return handler.getTestResults(); } + + public void setTestRun(TestRunDto testRun){ + handler.setTestRun(testRun); + } } diff --git a/src/main/java/main/model/db/imports/ImportHandlers/PHPCodeception.java b/src/main/java/main/model/db/imports/ImportHandlers/PHPCodeception.java index 10f729e..7ac07ea 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/PHPCodeception.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/PHPCodeception.java @@ -45,4 +45,8 @@ public List getTests() { public List getTestResults() { return handler.getTestResults(); } + + public void setTestRun(TestRunDto testRun){ + handler.setTestRun(testRun); + } } diff --git a/src/main/java/main/model/db/imports/ImportHandlers/Robot.java b/src/main/java/main/model/db/imports/ImportHandlers/Robot.java index 81c30cc..b19b0a8 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/Robot.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/Robot.java @@ -45,4 +45,8 @@ public List getTests() { public List getTestResults() { return handler.getTestResults(); } + + public void setTestRun(TestRunDto testRun){ + handler.setTestRun(testRun); + } } diff --git a/src/main/java/main/model/db/imports/ImportHandlers/TRX.java b/src/main/java/main/model/db/imports/ImportHandlers/TRX.java index 48e7b6c..2a788e5 100644 --- a/src/main/java/main/model/db/imports/ImportHandlers/TRX.java +++ b/src/main/java/main/model/db/imports/ImportHandlers/TRX.java @@ -45,4 +45,8 @@ public List getTests() { public List getTestResults() { return handler.getTestResults(); } + + public void setTestRun(TestRunDto testRun){ + handler.setTestRun(testRun); + } } diff --git a/src/main/java/main/model/db/imports/Importer.java b/src/main/java/main/model/db/imports/Importer.java index 48904cd..267d204 100644 --- a/src/main/java/main/model/db/imports/Importer.java +++ b/src/main/java/main/model/db/imports/Importer.java @@ -18,6 +18,7 @@ public class Importer extends BaseImporter { private String suiteName; private TestRunDto testRunTemplate; private boolean singleTestRun; + private Date nextFinishTime = new Date(); private HandlerFactory handlerFactory = new HandlerFactory(); @@ -33,20 +34,16 @@ public Importer(List files, TestRunDto testRunTemplate, String pattern, public List executeImport() throws AqualityException { if(testRunTemplate.getId() == null && !singleTestRun){ - return parseIntoMultiple(); + return executeMultiTestRunImport(); } - return Collections.singletonList(parseIntoOne()); + return Collections.singletonList(executeSingleTestRunImport()); } - private ImportDto parseIntoOne() throws AqualityException { + private ImportDto executeSingleTestRunImport() throws AqualityException { try { createImport("Import into One Test Run was started!"); - for (String pathToFile : this.files) { - this.file = new File(pathToFile); - Handler handler = handlerFactory.getHandler(this.file, type, testNameNodeType); - storeResults(handler); - } + readData(this.files); executeResultsCreation(); return finishImport(); } catch (Exception e) { @@ -55,14 +52,13 @@ private ImportDto parseIntoOne() throws AqualityException { } } - private List parseIntoMultiple() throws AqualityException { + private List executeMultiTestRunImport() throws AqualityException { List imports = new ArrayList<>(); for (String pathToFile : this.files) { try{ - this.file = new File(pathToFile); - createImport("Import was started for file: " + this.file.getName()); - Handler handler = handlerFactory.getHandler(this.file, type, testNameNodeType); - storeResults(handler); + File file = new File(pathToFile); + readData(file); + createImport("Import was started for file: " + file.getName()); executeResultsCreation(); imports.add(finishImport()); } catch (Exception e){ @@ -75,14 +71,29 @@ private List parseIntoMultiple() throws AqualityException { } private void executeResultsCreation() throws AqualityException { - fillTestRunWithInputData(); - fillTestSuiteWithInputData(); this.processImport(testRunTemplate.getId() != null); this.testRun = new TestRunDto(); this.testResults = new ArrayList<>(); this.tests = new ArrayList<>(); } + private void readData(List filePaths) throws AqualityException { + for (String pathToFile : filePaths) { + Handler handler = handlerFactory.getHandler(new File(pathToFile), type, testNameNodeType, nextFinishTime); + updateTestRun(handler); + storeResults(handler); + } + fillTestRunWithInputData(); + fillTestSuiteWithInputData(); + } + + private void readData(File file) throws AqualityException { + Handler handler = handlerFactory.getHandler(file, type, testNameNodeType, new Date()); + storeResults(handler); + fillTestRunWithInputData(file.getName()); + fillTestSuiteWithInputData(); + } + private void storeResults(Handler handler) throws AqualityException { this.testRun = handler.getTestRun(); this.testResults.addAll(handler.getTestResults()); @@ -91,6 +102,23 @@ private void storeResults(Handler handler) throws AqualityException { logToImport("File was parsed correctly!"); } + private void updateTestRun(Handler handler) { + TestRunDto handlerTestRun = handler.getTestRun(); + if(this.testRun != null){ + + if(this.testRun.getStart_time().before(handlerTestRun.getStart_time())){ + handlerTestRun.setStart_time(this.testRun.getStart_time()); + } + + if(this.testRun.getFinish_time().after(handlerTestRun.getFinish_time())){ + handlerTestRun.setFinish_time(this.testRun.getFinish_time()); + } + } + + handler.setTestRun(handlerTestRun); + nextFinishTime = handlerTestRun.getStart_time(); + } + private void fillTestSuiteWithInputData(){ testSuite.setName(suiteName); } @@ -105,6 +133,17 @@ private void fillTestRunWithInputData(){ this.testRun.setDebug(testRunTemplate.getDebug()); } + private void fillTestRunWithInputData(String fileName){ + testRunTemplate.setBuild_name(getBuildName(testRunTemplate, fileName)); + fillTestRunWithInputData(); + } + + private String getBuildName(TestRunDto testRun, String fileName) { + return (testRun.getBuild_name() != null && !testRun.getBuild_name().equals("")) + ? testRun.getBuild_name() + : fileName.substring(0, fileName.lastIndexOf(".")); + } + private ImportDto finishImport() throws AqualityException { importDto.setFinished(new Date()); importDto.setIs_finished(1); @@ -117,6 +156,7 @@ private void finishImportWithError(String log) throws AqualityException { log = "Without any error message :("; } + importDto.setProject_id(this.projectId); importDto.setFinished(new Date()); importDto.setIs_finished(1); importDto.addToLog("Import was finished with Error! " + log); diff --git a/src/main/java/main/model/db/imports/SAXHandlers/JavaTestNGHandler.java b/src/main/java/main/model/db/imports/SAXHandlers/JavaTestNGHandler.java index fdac063..b01bae6 100644 --- a/src/main/java/main/model/db/imports/SAXHandlers/JavaTestNGHandler.java +++ b/src/main/java/main/model/db/imports/SAXHandlers/JavaTestNGHandler.java @@ -1,5 +1,7 @@ package main.model.db.imports.SAXHandlers; +import main.exceptions.AqualityException; +import main.model.db.imports.Handler; import main.model.db.imports.TestNameNodeType; import main.model.dto.*; import org.xml.sax.Attributes; @@ -12,10 +14,8 @@ import static main.model.db.imports.ResultStatus.*; -public class JavaTestNGHandler extends DefaultHandler { - +public class JavaTestNGHandler extends Handler { private TestSuiteDto testSuite = new TestSuiteDto(); - private TestRunDto testRun = new TestRunDto(); private List results = new ArrayList<>(); private TestResultDto result = new TestResultDto(); private List tests = new ArrayList<>(); @@ -25,7 +25,8 @@ public class JavaTestNGHandler extends DefaultHandler { private Date currentTimeSlot; private TestNameNodeType testNameNodeType; - public JavaTestNGHandler(TestNameNodeType testNameNodeType){ + public JavaTestNGHandler(TestNameNodeType testNameNodeType) throws AqualityException { + super(); this.testNameNodeType = testNameNodeType; result.setFail_reason("$blank"); testRun.setFinish_time(new Date()); diff --git a/src/main/java/main/model/db/imports/SAXHandlers/NUnitV2Handler.java b/src/main/java/main/model/db/imports/SAXHandlers/NUnitV2Handler.java index f6da948..3224171 100644 --- a/src/main/java/main/model/db/imports/SAXHandlers/NUnitV2Handler.java +++ b/src/main/java/main/model/db/imports/SAXHandlers/NUnitV2Handler.java @@ -15,10 +15,7 @@ import static main.model.db.imports.ResultStatus.*; public class NUnitV2Handler extends Handler { - - private TestSuiteDto testSuite = new TestSuiteDto(); - private TestRunDto testRun = new TestRunDto(); private List results = new ArrayList(); private TestResultDto result = new TestResultDto(); private List tests = new ArrayList(); diff --git a/src/main/java/main/model/db/imports/SAXHandlers/NUnitV3Handler.java b/src/main/java/main/model/db/imports/SAXHandlers/NUnitV3Handler.java index 3c1a0a2..cdd0b4d 100644 --- a/src/main/java/main/model/db/imports/SAXHandlers/NUnitV3Handler.java +++ b/src/main/java/main/model/db/imports/SAXHandlers/NUnitV3Handler.java @@ -18,7 +18,6 @@ public class NUnitV3Handler extends Handler { private TestSuiteDto testSuite = new TestSuiteDto(); - private TestRunDto testRun = new TestRunDto(); private List results = new ArrayList<>(); private TestResultDto result = new TestResultDto(); private List tests = new ArrayList<>(); diff --git a/src/main/java/main/model/db/imports/SAXHandlers/PHPCodeceptionHandler.java b/src/main/java/main/model/db/imports/SAXHandlers/PHPCodeceptionHandler.java index ebc6204..53f8d5c 100644 --- a/src/main/java/main/model/db/imports/SAXHandlers/PHPCodeceptionHandler.java +++ b/src/main/java/main/model/db/imports/SAXHandlers/PHPCodeceptionHandler.java @@ -13,8 +13,6 @@ import static main.model.db.imports.ResultStatus.*; public class PHPCodeceptionHandler extends Handler { - - private TestRunDto testRun = new TestRunDto(); private TestSuiteDto testSuite = new TestSuiteDto(); private List results = new ArrayList<>(); private TestResultDto result = new TestResultDto(); diff --git a/src/main/java/main/model/db/imports/SAXHandlers/RobotHandler.java b/src/main/java/main/model/db/imports/SAXHandlers/RobotHandler.java index 1006637..0fed743 100644 --- a/src/main/java/main/model/db/imports/SAXHandlers/RobotHandler.java +++ b/src/main/java/main/model/db/imports/SAXHandlers/RobotHandler.java @@ -1,6 +1,8 @@ package main.model.db.imports.SAXHandlers; +import main.exceptions.AqualityException; +import main.model.db.imports.Handler; import main.model.db.imports.ResultStatus; import main.model.dto.*; import org.xml.sax.Attributes; @@ -16,9 +18,7 @@ import static main.model.db.imports.ResultStatus.*; -public class RobotHandler extends DefaultHandler { - - private TestRunDto testRun = new TestRunDto(); +public class RobotHandler extends Handler { private TestSuiteDto testSuite = new TestSuiteDto(); private List results = new ArrayList<>(); private TestResultDto result = new TestResultDto(); @@ -31,7 +31,8 @@ public class RobotHandler extends DefaultHandler { private String currentElement = ""; private boolean errorMessage = false; - public RobotHandler(){ + public RobotHandler() throws AqualityException { + super(); result.setFail_reason("$blank"); } diff --git a/src/main/java/main/model/db/imports/SAXHandlers/TRXHandler.java b/src/main/java/main/model/db/imports/SAXHandlers/TRXHandler.java index dcbc751..f9d4f09 100644 --- a/src/main/java/main/model/db/imports/SAXHandlers/TRXHandler.java +++ b/src/main/java/main/model/db/imports/SAXHandlers/TRXHandler.java @@ -1,5 +1,7 @@ package main.model.db.imports.SAXHandlers; +import main.exceptions.AqualityException; +import main.model.db.imports.Handler; import main.model.db.imports.ResultStatus; import org.xml.sax.helpers.DefaultHandler; import main.model.db.imports.TestNameNodeType; @@ -13,8 +15,7 @@ import static main.model.db.imports.ResultStatus.*; -public class TRXHandler extends DefaultHandler { - private TestRunDto testRun = new TestRunDto(); +public class TRXHandler extends Handler { private List results = new ArrayList<>(); private TestResultDto result = new TestResultDto(); private List tests = new ArrayList<>(); @@ -24,7 +25,8 @@ public class TRXHandler extends DefaultHandler { private boolean ddtResultWasOpened = false; private TestNameNodeType testNameNodeType; - public TRXHandler(TestNameNodeType testNameNodeType){ + public TRXHandler(TestNameNodeType testNameNodeType) throws AqualityException { + super(); this.testNameNodeType = testNameNodeType; result.setFail_reason("$blank"); } diff --git a/src/main/java/main/utils/DateUtils.java b/src/main/java/main/utils/DateUtils.java index ac816cd..ca70bb7 100644 --- a/src/main/java/main/utils/DateUtils.java +++ b/src/main/java/main/utils/DateUtils.java @@ -13,6 +13,11 @@ public Date addMS(Date date, Integer ms) return add(Calendar.MILLISECOND, date, ms); } + public Date removeMS(Date date, Integer ms) + { + return add(Calendar.MILLISECOND, date, -ms); + } + public Date addDays(Date date, int days) { return add(Calendar.DATE, date, days); @@ -23,10 +28,10 @@ public Date addMonth(Date date, int month) return add(Calendar.MONTH, date, month); } - public Date add(int field, Date date, int month) { + public Date add(int field, Date date, int diff) { Calendar cal = Calendar.getInstance(); cal.setTime(date); - cal.add(field, month); + cal.add(field, diff); return cal.getTime(); } diff --git a/src/main/java/main/utils/FileUtils.java b/src/main/java/main/utils/FileUtils.java index 84975ae..12d90aa 100644 --- a/src/main/java/main/utils/FileUtils.java +++ b/src/main/java/main/utils/FileUtils.java @@ -8,8 +8,12 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.List; public class FileUtils { diff --git a/src/test/java/tests/workers/imports/CucumberHandlerTest.java b/src/test/java/tests/workers/imports/CucumberHandlerTest.java new file mode 100644 index 0000000..0964ef1 --- /dev/null +++ b/src/test/java/tests/workers/imports/CucumberHandlerTest.java @@ -0,0 +1,59 @@ +package tests.workers.imports; + +import com.fasterxml.jackson.core.JsonProcessingException; +import main.model.db.imports.ImportHandlers.Cucumber; +import main.model.db.imports.ImportHandlers.NUnitV3; +import main.model.db.imports.TestNameNodeType; +import main.model.dto.*; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import utils.FileUtils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +public class CucumberHandlerTest { + private Cucumber cucumber; + private DtoMapperGeneral mapper = new DtoMapperGeneral(); + + @BeforeMethod + public void tryParse(){ + try { + String string = "January 2, 2010"; + DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH); + cucumber = new Cucumber(FileUtils.getResourceFile("reports/cucumber/cucumber.json"), format.parse(string)); + } catch (Exception e){ + assertNull(e, String.format("Failed on Handler Creating: %s", e.getMessage())); + } + } + + @Test + public void validateTests() throws JsonProcessingException { + List actualTests = cucumber.getTests(); + assertEquals(mapper.serialize(actualTests), FileUtils.getResourceFileAsString("reports/cucumber/tests.json")); + } + + @Test + public void validateTestSuite() throws JsonProcessingException { + TestSuiteDto actualTestSuite = cucumber.getTestSuite(); + assertEquals(mapper.serialize(actualTestSuite), FileUtils.getResourceFileAsString("reports/cucumber/suite.json")); + } + + @Test + public void validateTestRun() throws JsonProcessingException { + TestRunDto actualTestRun = cucumber.getTestRun(); + assertEquals(mapper.serialize(actualTestRun), FileUtils.getResourceFileAsString("reports/cucumber/testRun.json")); + } + + @Test + public void validateTestResults() throws JsonProcessingException { + List actualTestResults = cucumber.getTestResults(); + assertEquals(mapper.serialize(actualTestResults), FileUtils.getResourceFileAsString("reports/cucumber/testResults.json")); + } +} diff --git a/src/test/java/tests/workers/imports/ImporterTest.java b/src/test/java/tests/workers/imports/ImporterTest.java new file mode 100644 index 0000000..8f0b5c7 --- /dev/null +++ b/src/test/java/tests/workers/imports/ImporterTest.java @@ -0,0 +1,4 @@ +package tests.workers.imports; + +public class ImporterTest { +} diff --git a/src/test/resources/reports/cucumber/cucumber.json b/src/test/resources/reports/cucumber/cucumber.json new file mode 100644 index 0000000..213d334 --- /dev/null +++ b/src/test/resources/reports/cucumber/cucumber.json @@ -0,0 +1,121 @@ +[ + { + "description": "Test Report", + "keyword": "Feature", + "name": "Test Feature with all results", + "line": 2, + "id": "Test-Report", + "tags": [], + "uri": "features/testdeature.feature", + "elements": [ + { + "id": "passed", + "keyword": "Scenario", + "line": 7, + "name": "All passed", + "tags": [], + "type": "scenario", + "steps": [ + { + "arguments": [], + "keyword": "Given ", + "line": 8, + "name": "passed step", + "match": { + "location": "Projects/nodejs-cucumber-sample-master/node_modules/cucumber/lib/support_code_library_builder/define_helpers.js:135" + }, + "result": { + "status": "passed", + "duration": 1684328900 + } + }, + { + "arguments": [], + "keyword": "Then ", + "line": 9, + "name": "passed step", + "match": { + "location": "Projects/nodejs-cucumber-sample-master/node_modules/cucumber/lib/support_code_library_builder/define_helpers.js:135" + }, + "result": { + "status": "passed", + "duration": 1684328900 + } + } + ] + }, { + "id": "failed", + "keyword": "Scenario", + "line": 7, + "name": "step failed", + "tags": [], + "type": "scenario", + "steps": [ + { + "arguments": [], + "keyword": "Given ", + "line": 8, + "name": "passed step", + "match": { + "location": "Projects/nodejs-cucumber-sample-master/node_modules/cucumber/lib/support_code_library_builder/define_helpers.js:135" + }, + "result": { + "status": "passed", + "duration": 2667613100 + } + }, + { + "arguments": [], + "keyword": "Then ", + "line": 9, + "name": "failed step", + "match": { + "location": "Projects/nodejs-cucumber-sample-master/node_modules/cucumber/lib/support_code_library_builder/define_helpers.js:135" + }, + "result": { + "status": "failed", + "duration": 2667613100, + "error_message": "step was failed" + } + } + ] + }, { + "id": "failed", + "keyword": "Scenario", + "line": 7, + "name": "Step skipped", + "tags": [], + "type": "scenario", + "steps": [ + { + "arguments": [], + "keyword": "Given ", + "line": 8, + "name": "passed step", + "match": { + "location": "Projects/nodejs-cucumber-sample-master/node_modules/cucumber/lib/support_code_library_builder/define_helpers.js:135" + }, + "result": { + "status": "passed", + "duration": 2667613100 + } + }, + { + "arguments": [], + "keyword": "Then ", + "line": 9, + "name": "skipped step", + "match": { + "location": "Projects/nodejs-cucumber-sample-master/node_modules/cucumber/lib/support_code_library_builder/define_helpers.js:135" + }, + "result": { + "status": "skipped", + "duration": 1684328900, + "error_message": "step was skipped" + } + } + ] + } + ] + } +] diff --git a/src/test/resources/reports/cucumber/suite.json b/src/test/resources/reports/cucumber/suite.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/test/resources/reports/cucumber/suite.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/test/resources/reports/cucumber/testResults.json b/src/test/resources/reports/cucumber/testResults.json new file mode 100644 index 0000000..bb87b8b --- /dev/null +++ b/src/test/resources/reports/cucumber/testResults.json @@ -0,0 +1 @@ +[{"final_result_id":2,"start_date":1262383196632,"finish_date":1262383200000,"fail_reason":""},{"final_result_id":1,"start_date":1262383191298,"finish_date":1262383196632,"fail_reason":"step was failed"},{"final_result_id":5,"start_date":1262383186947,"finish_date":1262383191298,"fail_reason":"step was skippedstep was skipped"}] \ No newline at end of file diff --git a/src/test/resources/reports/cucumber/testRun.json b/src/test/resources/reports/cucumber/testRun.json new file mode 100644 index 0000000..ef34cf6 --- /dev/null +++ b/src/test/resources/reports/cucumber/testRun.json @@ -0,0 +1 @@ +{"start_time":1262383186947,"finish_time":1262383200000} \ No newline at end of file diff --git a/src/test/resources/reports/cucumber/tests.json b/src/test/resources/reports/cucumber/tests.json new file mode 100644 index 0000000..e7ae1e2 --- /dev/null +++ b/src/test/resources/reports/cucumber/tests.json @@ -0,0 +1 @@ +[{"name":"Test Feature with all results: All passed","body":"Given passed step\r\nThen passed step"},{"name":"Test Feature with all results: step failed","body":"Given passed step\r\nThen failed step"},{"name":"Test Feature with all results: Step skipped","body":"Given passed step\r\nThen skipped step"}] \ No newline at end of file From ad1bb9f8d13103d08cc471e5d1a4fb7066380b77 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Tue, 10 Mar 2020 11:12:30 +0300 Subject: [PATCH 11/17] Add finish status --- .../java/main/model/db/imports/Importer.java | 8 +- src/main/java/main/model/dto/ImportDto.java | 4 +- .../db_changelog/db.changelog-0.3.8.xml | 314 ++++++++++++++++++ 3 files changed, 320 insertions(+), 6 deletions(-) diff --git a/src/main/java/main/model/db/imports/Importer.java b/src/main/java/main/model/db/imports/Importer.java index 267d204..bf58eb0 100644 --- a/src/main/java/main/model/db/imports/Importer.java +++ b/src/main/java/main/model/db/imports/Importer.java @@ -57,8 +57,8 @@ private List executeMultiTestRunImport() throws AqualityException { for (String pathToFile : this.files) { try{ File file = new File(pathToFile); - readData(file); createImport("Import was started for file: " + file.getName()); + readData(file); executeResultsCreation(); imports.add(finishImport()); } catch (Exception e){ @@ -146,7 +146,7 @@ private String getBuildName(TestRunDto testRun, String fileName) { private ImportDto finishImport() throws AqualityException { importDto.setFinished(new Date()); - importDto.setIs_finished(1); + importDto.setFinish_status(1); importDto.addToLog("Import was finished!"); return importDao.create(importDto); } @@ -158,7 +158,7 @@ private void finishImportWithError(String log) throws AqualityException { importDto.setProject_id(this.projectId); importDto.setFinished(new Date()); - importDto.setIs_finished(1); + importDto.setFinish_status(2); importDto.addToLog("Import was finished with Error! " + log); importDao.create(importDto); } @@ -167,7 +167,7 @@ private void createImport(String log) throws AqualityException { importDto = new ImportDto(); importDto.setStarted(new Date()); importDto.setProject_id(projectId); - importDto.setIs_finished(0); + importDto.setFinish_status(0); importDto.setLog(log); importDto = importDao.create(importDto); } diff --git a/src/main/java/main/model/dto/ImportDto.java b/src/main/java/main/model/dto/ImportDto.java index 72033e8..8714f4e 100644 --- a/src/main/java/main/model/dto/ImportDto.java +++ b/src/main/java/main/model/dto/ImportDto.java @@ -23,9 +23,9 @@ public class ImportDto extends BaseDto { @DataBaseSearchable @DataBaseInsert private Integer project_id; - @DataBaseName(name="request_is_finished") + @DataBaseName(name="request_finish_status") @DataBaseInsert - private Integer is_finished; + private Integer finish_status; @DataBaseName(name="request_started") @DataBaseInsert @JsonDeserialize(using=CustomerDateAndTimeDeserialize.class) diff --git a/src/main/resources/db_changelog/db.changelog-0.3.8.xml b/src/main/resources/db_changelog/db.changelog-0.3.8.xml index 126d8c4..98b1097 100644 --- a/src/main/resources/db_changelog/db.changelog-0.3.8.xml +++ b/src/main/resources/db_changelog/db.changelog-0.3.8.xml @@ -184,4 +184,318 @@ + + + ALTER TABLE `imports` + CHANGE COLUMN `is_finished` `finish_status` INT(1) NOT NULL DEFAULT '0' COMMENT '0 - in progress\n1 - ok\n2 - error' ; + + + + + + + + + DROP procedure IF EXISTS `INSERT_IMPORT`; + + # + CREATE PROCEDURE `INSERT_IMPORT`( + IN request_id VARCHAR(11), + IN request_testrun_id VARCHAR(11), + IN request_project_id VARCHAR(11), + IN request_finish_status VARCHAR(1), + IN request_started VARCHAR(500), + IN request_finished VARCHAR(500), + IN request_log LONGTEXT + ) + BEGIN + + SET time_zone = '+00:00'; + INSERT INTO imports (id, testrun_id, project_id, finish_status, started, finished, log) + VALUES ( + IF(request_id = '', null,request_id), + IF(request_testrun_id = '', null,request_testrun_id), + IF(request_project_id = '', null,request_project_id), + IF(request_finish_status = '', null,request_finish_status), + IF(request_started = '', null,FROM_UNIXTIME(request_started)), + IF(request_finished = '', null,FROM_UNIXTIME(request_finished)), + IF(request_log = '', null,request_log) + ) ON DUPLICATE KEY UPDATE + testrun_id = IF(request_testrun_id = '', testrun_id, request_testrun_id), + project_id = IF(request_project_id = '', project_id, request_project_id), + finish_status = IF(request_finish_status = '', finish_status, request_finish_status), + started = IF(request_started = '', started, FROM_UNIXTIME(request_started)), + finished= IF(request_finished = '', finished, FROM_UNIXTIME(request_finished)), + log = IF(request_log = '', log, request_log); + + SET @result_id = IF(request_id = '', LAST_INSERT_ID(), request_id); + SELECT * from imports where id = @result_id; + END + + + + + + + + + DROP TRIGGER IF EXISTS `imports_AFTER_INSERT`; + + # + CREATE TRIGGER imports_AFTER_INSERT AFTER INSERT ON imports FOR EACH ROW + BEGIN + IF (NEW.finish_status = 1 AND new.testrun_id IS NOT NULL) + THEN + + DELETE FROM testrun_statistic WHERE testrun_id = NEW.testrun_id; + + INSERT INTO testrun_statistic (testrun_id, failed, passed, not_executed, in_progress, pending, total, app_issue, warning, not_assigned, other) + + SELECT + trn.id, + sum(frs.color = 1) as failed, + sum(frs.color = 5) as passed, + sum(frs.color = 3) as not_executed, + sum(frs.color = 2) as in_progress, + sum(frs.color = 4) as pending, + sum(frs.color != 0) as total, + sum(rr.color = 1 AND frs.color != 5) as app_issue, + sum(rr.color = 2 AND frs.color != 5) as warning, + sum(rr.color = 3 AND frs.color != 5) as not_assigned, + sum((rr.color = 4 OR rr.color = 5) AND frs.color != 5) as other + + from test_runs as trn + right join union_reporting.test_results as trs on trn.id=test_run_id + left join union_reporting.final_results as frs on trs.final_result_id = frs.id + left join union_reporting.result_resolution as rr on trs.test_resolution_id = rr.id + + Where trn.id = NEW.testrun_id; + END IF; + END + + + + + + + + + DROP TRIGGER IF EXISTS `imports_AFTER_UPDATE`; + + # + CREATE TRIGGER imports_AFTER_UPDATE AFTER UPDATE ON imports FOR EACH ROW + BEGIN + IF (NEW.finish_status = 1 AND new.testrun_id IS NOT NULL) + THEN + + DELETE FROM testrun_statistic WHERE testrun_id = NEW.testrun_id; + + INSERT INTO testrun_statistic (testrun_id, failed, passed, not_executed, in_progress, pending, total, app_issue, warning, not_assigned, other) + + SELECT + trn.id, + sum(frs.color = 1) as failed, + sum(frs.color = 5) as passed, + sum(frs.color = 3) as not_executed, + sum(frs.color = 2) as in_progress, + sum(frs.color = 4) as pending, + sum(frs.color != 0) as total, + sum(rr.color = 1 AND frs.color != 5) as app_issue, + sum(rr.color = 2 AND frs.color != 5) as warning, + sum(rr.color = 3 AND frs.color != 5) as not_assigned, + sum((rr.color = 4 OR rr.color = 5) AND frs.color != 5) as other + + from test_runs as trn + right join union_reporting.test_results as trs on trn.id=test_run_id + left join union_reporting.final_results as frs on trs.final_result_id = frs.id + left join union_reporting.result_resolution as rr on trs.test_resolution_id = rr.id + + Where trn.id = NEW.testrun_id; + END IF; + END + + + + + + + + + DROP TRIGGER IF EXISTS `test_results_AFTER_INSERT`; + + # + CREATE TRIGGER test_results_AFTER_INSERT AFTER INSERT ON test_results FOR EACH ROW + BEGIN + + IF NOT EXISTS (SELECT * FROM imports WHERE testrun_id= NEW.test_run_id AND finish_status = 0) + THEN + + DELETE FROM testrun_statistic WHERE testrun_id = NEW.test_run_id; + + INSERT INTO testrun_statistic (testrun_id, failed, passed, not_executed, in_progress, pending, total, app_issue, warning, not_assigned, other) + + SELECT + trn.id, + sum(frs.color = 1) as failed, + sum(frs.color = 5) as passed, + sum(frs.color = 3) as not_executed, + sum(frs.color = 2) as in_progress, + sum(frs.color = 4) as pending, + sum(frs.color != 0) as total, + sum(rr.color = 1 AND frs.color != 5) as app_issue, + sum(rr.color = 2 AND frs.color != 5) as warning, + sum(rr.color = 3 AND frs.color != 5) as not_assigned, + sum((rr.color = 4 OR rr.color = 5) AND frs.color != 5) as other + + from test_runs as trn + right join union_reporting.test_results as trs on trn.id=test_run_id + left join union_reporting.final_results as frs on trs.final_result_id = frs.id + left join union_reporting.result_resolution as rr on trs.test_resolution_id = rr.id + + Where trn.id = NEW.test_run_id; + END IF; + + CALL UPDATE_LAST_RESULT_COLORS_FOR_TEST ( + NEW.test_id, + (SELECT stability_count from projects where id = NEW.project_id) + ); + END + + + + + + + + + DROP TRIGGER IF EXISTS `test_results_AFTER_UPDATE`; + + # + CREATE TRIGGER test_results_AFTER_UPDATE AFTER UPDATE ON test_results FOR EACH ROW + BEGIN + IF NOT EXISTS (SELECT * FROM imports WHERE testrun_id= NEW.test_run_id AND finish_status = 0) + THEN + + DELETE FROM testrun_statistic WHERE testrun_id = NEW.test_run_id; + + INSERT INTO testrun_statistic (testrun_id, failed, passed, not_executed, in_progress, pending, total, app_issue, warning, not_assigned, other) + + SELECT + trn.id, + sum(frs.color = 1) as failed, + sum(frs.color = 5) as passed, + sum(frs.color = 3) as not_executed, + sum(frs.color = 2) as in_progress, + sum(frs.color = 4) as pending, + sum(frs.color != 0) as total, + sum(rr.color = 1 AND frs.color != 5) as app_issue, + sum(rr.color = 2 AND frs.color != 5) as warning, + sum(rr.color = 3 AND frs.color != 5) as not_assigned, + sum((rr.color = 4 OR rr.color = 5) AND frs.color != 5) as other + + from test_runs as trn + right join union_reporting.test_results as trs on trn.id=test_run_id + left join union_reporting.final_results as frs on trs.final_result_id = frs.id + left join union_reporting.result_resolution as rr on trs.test_resolution_id = rr.id + + Where trn.id = NEW.test_run_id; + END IF; + + CALL UPDATE_LAST_RESULT_COLORS_FOR_TEST ( + NEW.test_id, + (SELECT stability_count from projects where id = NEW.project_id) + ); + END + + + + + + + + + DROP TRIGGER IF EXISTS `test_results_BEFORE_DELETE`; + + # + CREATE TRIGGER `test_results_BEFORE_DELETE` BEFORE DELETE ON `test_results` FOR EACH ROW + BEGIN + IF NOT EXISTS (SELECT * FROM imports WHERE testrun_id= OLD.test_run_id AND finish_status = 0) + THEN + + DELETE FROM testrun_statistic WHERE testrun_id = OLD.test_run_id; + + INSERT INTO testrun_statistic (testrun_id, failed, passed, not_executed, in_progress, pending, total, app_issue, warning, not_assigned, other) + + SELECT + trn.id, + sum(frs.color = 1) as failed, + sum(frs.color = 5) as passed, + sum(frs.color = 3) as not_executed, + sum(frs.color = 2) as in_progress, + sum(frs.color = 4) as pending, + sum(frs.color != 0) as total, + sum(rr.color = 1 AND frs.color != 5) as app_issue, + sum(rr.color = 2 AND frs.color != 5) as warning, + sum(rr.color = 3 AND frs.color != 5) as not_assigned, + sum((rr.color = 4 OR rr.color = 5) AND frs.color != 5) as other + + from test_runs as trn + right join union_reporting.test_results as trs on trn.id=test_run_id + left join union_reporting.final_results as frs on trs.final_result_id = frs.id + left join union_reporting.result_resolution as rr on trs.test_resolution_id = rr.id + + Where trn.id = OLD.test_run_id; + END IF; + + CALL UPDATE_LAST_RESULT_COLORS_FOR_TEST ( + OLD.test_id, + (SELECT stability_count from projects where id = OLD.project_id) + ); + END + + + + + + + + + DROP TRIGGER IF EXISTS `test_results_AFTER_DELETE`; + + # + CREATE TRIGGER test_results_AFTER_DELETE AFTER DELETE ON test_results FOR EACH ROW + BEGIN + IF NOT EXISTS (SELECT * FROM imports WHERE testrun_id= OLD.test_run_id AND finish_status = 0) + THEN + + DELETE FROM testrun_statistic WHERE testrun_id = OLD.test_run_id; + + INSERT INTO testrun_statistic (testrun_id, failed, passed, not_executed, in_progress, pending, total, app_issue, warning, not_assigned, other) + + SELECT + trn.id, + sum(frs.color = 1) as failed, + sum(frs.color = 5) as passed, + sum(frs.color = 3) as not_executed, + sum(frs.color = 2) as in_progress, + sum(frs.color = 4) as pending, + sum(frs.color != 0) as total, + sum(rr.color = 1 AND frs.color != 5) as app_issue, + sum(rr.color = 2 AND frs.color != 5) as warning, + sum(rr.color = 3 AND frs.color != 5) as not_assigned, + sum((rr.color = 4 OR rr.color = 5) AND frs.color != 5) as other + + from test_runs as trn + right join union_reporting.test_results as trs on trn.id=test_run_id + left join union_reporting.final_results as frs on trs.final_result_id = frs.id + left join union_reporting.result_resolution as rr on trs.test_resolution_id = rr.id + + Where trn.id = OLD.test_run_id; + END IF; + END + + + + + From 78099e1216037db4d340356e184837451c004652 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Tue, 10 Mar 2020 11:18:20 +0300 Subject: [PATCH 12/17] Update swagger Add changelog --- CHANGELOG.md | 6 ++++-- src/main/webapp/doc/api-doc.yaml | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e59c6f3..6a36f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,12 @@ ## 0.3.8 (Unreleased) Features: - - [Doc] Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76) + - Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76) + - Mark import af failed when import is failed -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/79) Bugfixes: - - [BUG] Import was finished with Error! You are trying to edit entity which is locked -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/44) + - Import was finished with Error! You are trying to edit entity which is locked -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/44) + - Incorrect "Duration" count if import several *.json's -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/37) ## 0.3.7 (2020-03-02) diff --git a/src/main/webapp/doc/api-doc.yaml b/src/main/webapp/doc/api-doc.yaml index 0ddb523..2eb332f 100644 --- a/src/main/webapp/doc/api-doc.yaml +++ b/src/main/webapp/doc/api-doc.yaml @@ -2015,9 +2015,9 @@ definitions: testrun_id: type: integer description: 'ID of related Test Run' - is_finished: + finish_status: type: integer - description: '1 if finished and 0 if not' + description: '2 if failed, 1 if success, 0 if in progress' started: type: string description: 'Started (format: yyyy-MM-dd HH:mm:ss)' From 6dd64927057c3fc9ba0c67b00c1b2a296c993186 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Tue, 10 Mar 2020 11:33:47 +0300 Subject: [PATCH 13/17] Fix Cucumber import tests --- src/test/java/tests/workers/imports/CucumberHandlerTest.java | 2 ++ src/test/java/tests/workers/imports/ImporterTest.java | 4 ---- src/test/resources/reports/cucumber/testResults.json | 2 +- src/test/resources/reports/cucumber/testRun.json | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 src/test/java/tests/workers/imports/ImporterTest.java diff --git a/src/test/java/tests/workers/imports/CucumberHandlerTest.java b/src/test/java/tests/workers/imports/CucumberHandlerTest.java index 0964ef1..8121386 100644 --- a/src/test/java/tests/workers/imports/CucumberHandlerTest.java +++ b/src/test/java/tests/workers/imports/CucumberHandlerTest.java @@ -14,6 +14,7 @@ import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.TimeZone; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; @@ -27,6 +28,7 @@ public void tryParse(){ try { String string = "January 2, 2010"; DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH); + format.setTimeZone(TimeZone.getTimeZone("UTC")); cucumber = new Cucumber(FileUtils.getResourceFile("reports/cucumber/cucumber.json"), format.parse(string)); } catch (Exception e){ assertNull(e, String.format("Failed on Handler Creating: %s", e.getMessage())); diff --git a/src/test/java/tests/workers/imports/ImporterTest.java b/src/test/java/tests/workers/imports/ImporterTest.java deleted file mode 100644 index 8f0b5c7..0000000 --- a/src/test/java/tests/workers/imports/ImporterTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package tests.workers.imports; - -public class ImporterTest { -} diff --git a/src/test/resources/reports/cucumber/testResults.json b/src/test/resources/reports/cucumber/testResults.json index bb87b8b..4c989a6 100644 --- a/src/test/resources/reports/cucumber/testResults.json +++ b/src/test/resources/reports/cucumber/testResults.json @@ -1 +1 @@ -[{"final_result_id":2,"start_date":1262383196632,"finish_date":1262383200000,"fail_reason":""},{"final_result_id":1,"start_date":1262383191298,"finish_date":1262383196632,"fail_reason":"step was failed"},{"final_result_id":5,"start_date":1262383186947,"finish_date":1262383191298,"fail_reason":"step was skippedstep was skipped"}] \ No newline at end of file +[{"final_result_id":2,"start_date":1262390396632,"finish_date":1262390400000,"fail_reason":""},{"final_result_id":1,"start_date":1262390391298,"finish_date":1262390396632,"fail_reason":"step was failed"},{"final_result_id":5,"start_date":1262390386947,"finish_date":1262390391298,"fail_reason":"step was skippedstep was skipped"}] \ No newline at end of file diff --git a/src/test/resources/reports/cucumber/testRun.json b/src/test/resources/reports/cucumber/testRun.json index ef34cf6..c2fb8dd 100644 --- a/src/test/resources/reports/cucumber/testRun.json +++ b/src/test/resources/reports/cucumber/testRun.json @@ -1 +1 @@ -{"start_time":1262383186947,"finish_time":1262383200000} \ No newline at end of file +{"start_time":1262390386947,"finish_time":1262390400000} \ No newline at end of file From 544f200072926e1dd9f9e72d921169ce43a0f85c Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Tue, 10 Mar 2020 13:57:31 +0300 Subject: [PATCH 14/17] Fix comments --- CHANGELOG.md | 2 +- .../java/tests/workers/imports/CucumberHandlerTest.java | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a36f83..0dda22b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Features: - Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76) - - Mark import af failed when import is failed -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/79) + - Mark import as failed when import is failed -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/79) Bugfixes: - Import was finished with Error! You are trying to edit entity which is locked -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/44) diff --git a/src/test/java/tests/workers/imports/CucumberHandlerTest.java b/src/test/java/tests/workers/imports/CucumberHandlerTest.java index 8121386..f2c72df 100644 --- a/src/test/java/tests/workers/imports/CucumberHandlerTest.java +++ b/src/test/java/tests/workers/imports/CucumberHandlerTest.java @@ -2,8 +2,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import main.model.db.imports.ImportHandlers.Cucumber; -import main.model.db.imports.ImportHandlers.NUnitV3; -import main.model.db.imports.TestNameNodeType; import main.model.dto.*; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -11,13 +9,12 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; import java.util.Locale; import java.util.TimeZone; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; public class CucumberHandlerTest { private Cucumber cucumber; @@ -31,7 +28,7 @@ public void tryParse(){ format.setTimeZone(TimeZone.getTimeZone("UTC")); cucumber = new Cucumber(FileUtils.getResourceFile("reports/cucumber/cucumber.json"), format.parse(string)); } catch (Exception e){ - assertNull(e, String.format("Failed on Handler Creating: %s", e.getMessage())); + fail(String.format("Failed on Handler Creating: %s", e.getMessage())); } } From 874c046af1fd0ce219f108702a69aab168255ff7 Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Tue, 10 Mar 2020 17:41:12 +0300 Subject: [PATCH 15/17] hot fix build_name --- src/main/java/main/model/db/imports/Importer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/main/model/db/imports/Importer.java b/src/main/java/main/model/db/imports/Importer.java index bf58eb0..6552a2a 100644 --- a/src/main/java/main/model/db/imports/Importer.java +++ b/src/main/java/main/model/db/imports/Importer.java @@ -136,6 +136,7 @@ private void fillTestRunWithInputData(){ private void fillTestRunWithInputData(String fileName){ testRunTemplate.setBuild_name(getBuildName(testRunTemplate, fileName)); fillTestRunWithInputData(); + testRunTemplate.setBuild_name(null); } private String getBuildName(TestRunDto testRun, String fileName) { From e5a179a828e6e601df56df61c1bd4479d8c70a7e Mon Sep 17 00:00:00 2001 From: VladKostyukevich Date: Tue, 10 Mar 2020 17:46:51 +0300 Subject: [PATCH 16/17] hot fix build_name --- src/main/java/main/model/db/imports/Importer.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/main/model/db/imports/Importer.java b/src/main/java/main/model/db/imports/Importer.java index 6552a2a..0a4482e 100644 --- a/src/main/java/main/model/db/imports/Importer.java +++ b/src/main/java/main/model/db/imports/Importer.java @@ -124,21 +124,19 @@ private void fillTestSuiteWithInputData(){ } private void fillTestRunWithInputData(){ + fillTestRunWithInputData(null); + } + + private void fillTestRunWithInputData(String fileName){ testRun.setProject_id(this.projectId); testRun.setCi_build(testRunTemplate.getCi_build()); this.testRun.setAuthor(testRunTemplate.getAuthor()); this.testRun.setExecution_environment(testRunTemplate.getExecution_environment()); - this.testRun.setBuild_name(testRunTemplate.getBuild_name()); + this.testRun.setBuild_name(fileName == null ? testRunTemplate.getBuild_name() : getBuildName(testRunTemplate, fileName)); this.testRun.setId(testRunTemplate.getId()); this.testRun.setDebug(testRunTemplate.getDebug()); } - private void fillTestRunWithInputData(String fileName){ - testRunTemplate.setBuild_name(getBuildName(testRunTemplate, fileName)); - fillTestRunWithInputData(); - testRunTemplate.setBuild_name(null); - } - private String getBuildName(TestRunDto testRun, String fileName) { return (testRun.getBuild_name() != null && !testRun.getBuild_name().equals("")) ? testRun.getBuild_name() From 9f6a114bac061092817237a82c106ed300ae404b Mon Sep 17 00:00:00 2001 From: Vlad Kostyukevich Date: Wed, 11 Mar 2020 11:35:47 +0300 Subject: [PATCH 17/17] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dda22b..d6cbe39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -## 0.3.8 (Unreleased) +## 0.3.8 (2020-03-11) Features: - Update Swagger with Statistic endpoints -> [View Issue](https://github.com/aquality-automation/aquality-tracking/issues/76)