From b25601b2abe3b78482d2fba893c24144d0801789 Mon Sep 17 00:00:00 2001 From: Alexander Bainczyk Date: Thu, 14 Jun 2018 19:30:58 +0200 Subject: [PATCH 1/2] bug fixes * Clicking 'Cancel' in the symbol parameter modal redirects to the startpage * Aborting a learning process does not work * Deleting a project that has test reports or learner results throws JPA exception * Time during learning is not displayed correctly * Browser refresh on the start page leads to empty page --- CHANGELOG.md | 5 +++ .../alex/data/dao/ProjectDAOImpl.java | 19 +++++++++- .../repositories/LearnerResultRepository.java | 11 ++++++ .../alex/learning/rest/LearnerResource.java | 15 +++++--- .../alex/learning/services/Learner.java | 7 ++-- .../repositories/TestReportRepository.java | 11 ++++++ .../alex/data/dao/ProjectDAOImplTest.java | 38 ++++++++++++++++++- .../learning/rest/LearnerResourceTest.java | 4 +- .../alex/learning/services/LearnerTest.java | 2 +- .../project-edit-modal.component.html | 4 ++ .../project-edit-modal.component.js | 8 ++-- ...mbol-parameter-create-modal.component.html | 2 +- ...symbol-parameter-edit-modal.component.html | 2 +- .../learner-view/learner-view.component.js | 7 +++- frontend/src/main/javascript/src/js/routes.js | 5 ++- 15 files changed, 118 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f0d4975b..a26252606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# ALEX 1.5.1 + +This release only contains some bug fixes. + + # ALEX 1.5.0 ## Breaking Changes diff --git a/backend/src/main/java/de/learnlib/alex/data/dao/ProjectDAOImpl.java b/backend/src/main/java/de/learnlib/alex/data/dao/ProjectDAOImpl.java index 954a113c7..abf53b263 100644 --- a/backend/src/main/java/de/learnlib/alex/data/dao/ProjectDAOImpl.java +++ b/backend/src/main/java/de/learnlib/alex/data/dao/ProjectDAOImpl.java @@ -26,6 +26,7 @@ import de.learnlib.alex.learning.entities.LearnerResult; import de.learnlib.alex.learning.repositories.LearnerResultRepository; import de.learnlib.alex.testing.entities.TestSuite; +import de.learnlib.alex.testing.repositories.TestReportRepository; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; @@ -68,6 +69,9 @@ public class ProjectDAOImpl implements ProjectDAO { /** The repository for learner results. */ private LearnerResultRepository learnerResultRepository; + /** The repository for test reports. */ + private TestReportRepository testReportRepository; + /** The FileDAO to use. Will be injected. */ private FileDAO fileDAO; @@ -85,14 +89,17 @@ public class ProjectDAOImpl implements ProjectDAO { * The FileDAO to use. * @param projectUrlDAO * The ProjectUrlDAO to use. + * @param testReportRepository + * The repository for test reports. */ @Inject public ProjectDAOImpl(ProjectRepository projectRepository, LearnerResultRepository learnerResultRepository, - @Lazy FileDAO fileDAO, @Lazy ProjectUrlDAO projectUrlDAO) { + TestReportRepository testReportRepository, @Lazy FileDAO fileDAO, @Lazy ProjectUrlDAO projectUrlDAO) { this.projectRepository = projectRepository; this.learnerResultRepository = learnerResultRepository; this.fileDAO = fileDAO; this.projectUrlDAO = projectUrlDAO; + this.testReportRepository = testReportRepository; } @Override @@ -111,6 +118,10 @@ public Project create(final Project project) throws ValidationException { testSuite.setProject(project); project.getTests().add(testSuite); + if (project.getUrls().isEmpty()) { + throw new ValidationException("The project has to have at least one URL."); + } + project.getUrls().forEach(url -> { url.setId(null); url.setProject(project); @@ -164,6 +175,10 @@ public Project update(User user, Project project) throws NotFoundException, Vali .collect(Collectors.toList()); projectUrlDAO.checkAccess(user, project, urls); + if (project.getUrls().isEmpty()) { + throw new ValidationException("The project has to have at least one URL."); + } + try { project.setUser(user); project.setGroups(projectInDb.getGroups()); @@ -204,6 +219,8 @@ public void delete(User user, Long projectId) throws NotFoundException { final Project project = projectRepository.findOne(projectId); checkAccess(user, project); + testReportRepository.deleteAllByProject_Id(projectId); + learnerResultRepository.deleteAllByProject_Id(projectId); projectRepository.delete(project); // delete the project directory diff --git a/backend/src/main/java/de/learnlib/alex/learning/repositories/LearnerResultRepository.java b/backend/src/main/java/de/learnlib/alex/learning/repositories/LearnerResultRepository.java index 0041bde2d..f8f244d1e 100644 --- a/backend/src/main/java/de/learnlib/alex/learning/repositories/LearnerResultRepository.java +++ b/backend/src/main/java/de/learnlib/alex/learning/repositories/LearnerResultRepository.java @@ -116,4 +116,15 @@ public interface LearnerResultRepository extends JpaRepository { @Transactional(readOnly = true) @SuppressWarnings("checkstyle:methodname") List findAllByProject_Id(Long projectId); + + /** + * Delete all test reports by project id. + * + * @param projectId + * The id of the project. + * @return The number of deleted test reports. + */ + @Transactional + @SuppressWarnings("checkstyle:methodname") + Long deleteAllByProject_Id(Long projectId); } diff --git a/backend/src/test/java/de/learnlib/alex/data/dao/ProjectDAOImplTest.java b/backend/src/test/java/de/learnlib/alex/data/dao/ProjectDAOImplTest.java index d80d8ff08..208f30a75 100644 --- a/backend/src/test/java/de/learnlib/alex/data/dao/ProjectDAOImplTest.java +++ b/backend/src/test/java/de/learnlib/alex/data/dao/ProjectDAOImplTest.java @@ -23,6 +23,7 @@ import de.learnlib.alex.data.entities.SymbolGroup; import de.learnlib.alex.data.repositories.ProjectRepository; import de.learnlib.alex.learning.repositories.LearnerResultRepository; +import de.learnlib.alex.testing.repositories.TestReportRepository; import org.hamcrest.MatcherAssert; import org.junit.Before; import org.junit.Test; @@ -35,6 +36,7 @@ import javax.persistence.RollbackException; import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -65,11 +67,15 @@ public class ProjectDAOImplTest { @Mock private ProjectUrlDAO projectUrlDAO; + @Mock + private TestReportRepository testReportRepository; + private ProjectDAO projectDAO; @Before public void setUp() { - projectDAO = new ProjectDAOImpl(projectRepository, learnerResultRepository, fileDAO, projectUrlDAO); + projectDAO = new ProjectDAOImpl(projectRepository, learnerResultRepository, testReportRepository, fileDAO, + projectUrlDAO); } @Test @@ -91,6 +97,30 @@ public void shouldCreateAValidEmptyProject() { assertThat(p.getId(), is(equalTo(1L))); } + @Test(expected = ValidationException.class) + public void shouldNotCreateAProjectIfUrlsAreEmpty() throws NotFoundException { + User user = new User(USER_ID); + + Project project = new Project(); + project.setId(PROJECT_ID); + project.setUser(user); + + projectDAO.create(project); + } + + @Test(expected = ValidationException.class) + public void shouldNotUpdateAProjectIfUrlsAreEmpty() throws NotFoundException { + User user = new User(USER_ID); + + Project project = new Project(); + project.setId(PROJECT_ID); + project.setUser(user); + + given(projectRepository.findOne(PROJECT_ID)).willReturn(project); + + projectDAO.update(user, project); + } + @Test public void shouldCreateAValidPreFilledProject() { SymbolGroup testGroup = new SymbolGroup(); @@ -111,6 +141,7 @@ public void shouldCreateAValidPreFilledProject() { @Test(expected = ValidationException.class) public void shouldHandleConstraintViolationExceptionOnProjectCreationGracefully() { Project project = new Project(); + project.setUrls(Collections.singletonList(new ProjectUrl())); // given(projectRepository.save(project)).willThrow(ConstraintViolationException.class); @@ -120,6 +151,7 @@ public void shouldHandleConstraintViolationExceptionOnProjectCreationGracefully( @Test(expected = ValidationException.class) public void shouldHandleDataIntegrityViolationExceptionOnProjectCreationGracefully() { Project project = new Project(); + project.setUrls(Collections.singletonList(new ProjectUrl())); // given(projectRepository.save(project)).willThrow(DataIntegrityViolationException.class); @@ -129,6 +161,7 @@ public void shouldHandleDataIntegrityViolationExceptionOnProjectCreationGraceful @Test(expected = ValidationException.class) public void shouldHandleTransactionSystemExceptionOnProjectCreationGracefully() { Project project = new Project(); + project.setUrls(Collections.singletonList(new ProjectUrl())); // ConstraintViolationException constraintViolationException; constraintViolationException = new ConstraintViolationException("Project is not valid!", new HashSet<>()); @@ -218,6 +251,7 @@ public void shouldHandleConstraintViolationExceptionOnProjectUpdateGracefully() user.setId(USER_ID); Project project = new Project(); + project.setUrls(Collections.singletonList(new ProjectUrl())); project.setUser(user); project.setId(PROJECT_ID); @@ -235,6 +269,7 @@ public void shouldHandleDataIntegrityViolationExceptionOnProjectUpdateGracefully Project project = new Project(); project.setUser(user); project.setId(PROJECT_ID); + project.setUrls(Collections.singletonList(new ProjectUrl())); given(projectRepository.save(project)).willThrow(DataIntegrityViolationException.class); given(projectRepository.findOne(PROJECT_ID)).willReturn(project); @@ -248,6 +283,7 @@ public void shouldHandleTransactionSystemExceptionOnProjectUpdateGracefully() th user.setId(USER_ID); Project project = new Project(); + project.setUrls(Collections.singletonList(new ProjectUrl())); project.setUser(user); project.setId(PROJECT_ID); diff --git a/backend/src/test/java/de/learnlib/alex/learning/rest/LearnerResourceTest.java b/backend/src/test/java/de/learnlib/alex/learning/rest/LearnerResourceTest.java index 1f3654eb8..68a65b1f6 100644 --- a/backend/src/test/java/de/learnlib/alex/learning/rest/LearnerResourceTest.java +++ b/backend/src/test/java/de/learnlib/alex/learning/rest/LearnerResourceTest.java @@ -297,7 +297,7 @@ public void shouldStopIfTheLearningIsActive() { Response response = target("/learner/" + PROJECT_TEST_ID + "/stop").request().header("Authorization", adminToken).get(); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); - verify(learner).stop(admin); + verify(learner).stop(PROJECT_TEST_ID); } @Test @@ -312,7 +312,7 @@ public void shouldNotStopIfTheLearningIsNotActive() { assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); String expectedJSON = "{\"active\":false}"; assertEquals(expectedJSON, response.readEntity(String.class)); - verify(learner, never()).stop(admin); + verify(learner, never()).stop(PROJECT_TEST_ID); } @Test diff --git a/backend/src/test/java/de/learnlib/alex/learning/services/LearnerTest.java b/backend/src/test/java/de/learnlib/alex/learning/services/LearnerTest.java index 35fef0556..eedf8f972 100644 --- a/backend/src/test/java/de/learnlib/alex/learning/services/LearnerTest.java +++ b/backend/src/test/java/de/learnlib/alex/learning/services/LearnerTest.java @@ -118,7 +118,7 @@ public void shouldResumeAThread() throws NotFoundException { @Test public void shouldStopAThread() throws NotFoundException { - learner.stop(user); + learner.stop(-1L); } @Test diff --git a/frontend/src/main/javascript/src/js/components/modals/project-edit-modal/project-edit-modal.component.html b/frontend/src/main/javascript/src/js/components/modals/project-edit-modal/project-edit-modal.component.html index e470204e6..1e88a047c 100644 --- a/frontend/src/main/javascript/src/js/components/modals/project-edit-modal/project-edit-modal.component.html +++ b/frontend/src/main/javascript/src/js/components/modals/project-edit-modal/project-edit-modal.component.html @@ -8,6 +8,10 @@