Skip to content

Commit

Permalink
Merge branch 'developer'
Browse files Browse the repository at this point in the history
  • Loading branch information
abainczyk committed Apr 21, 2021
2 parents 2ae5e8b + 72f5860 commit 1d204d3
Show file tree
Hide file tree
Showing 47 changed files with 239 additions and 240 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:

- name: Tag latest images with release version
run: |
VERSION="2.1.0"
VERSION="2.1.1"
IMAGES="alex-frontend alex-backend alex-cli alex-docs"
for img in $IMAGES
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# ALEX 2.1.1

## Fixes

* Fix bug where test cases could not be executed.
* Fix bug where tests could not be saved when pre steps have changed.


# ALEX 2.1.0

## Breaking Changes
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ For **Windows 10**

### Production

1. [Download](https://github.com/LearnLib/alex/releases/latest) the `docker-compose.alex-2.1.0.yml` file.
2. Run `docker-compose -f docker-compose.alex-2.1.0.yml pull` once.
3. Run `docker-compose -f docker-compose.alex-2.1.0.yml up`.
1. [Download](https://github.com/LearnLib/alex/releases/latest) the `docker-compose.alex-2.1.1.yml` file.
2. Run `docker-compose -f docker-compose.alex-2.1.1.yml pull` once.
3. Run `docker-compose -f docker-compose.alex-2.1.1.yml up`.
4. Open `127.0.0.1` in a web browser to access the frontend.

**Services**
Expand Down
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN tar -xzf ltsmin-v3.0.2-linux.tgz
RUN mv v3.0.2 ltsmin

FROM openjdk:15
COPY --from=builder-backend /backend/target/ALEX-2.1.0.jar /usr/share/java/alex/alex.jar
COPY --from=builder-backend /backend/target/ALEX-2.1.1.jar /usr/share/java/alex/alex.jar
COPY --from=builder-ltsmin /ltsmin/ltsmin /opt/ltsmin
WORKDIR /var/lib/alex

Expand Down
2 changes: 1 addition & 1 deletion backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<packaging>jar</packaging>

<name>Automata Learning Experience (ALEX)</name>
<version>2.1.0</version>
<version>2.1.1</version>
<groupId>de.learnlib.alex</groupId>

<description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public TestSuite generate(User user, Long projectId, Long testNo, TestSuiteGener
}

for (TestCase tc : testSuite.getTestCases()) {
testDAO.update(user, project.getId(), tc);
testDAO.update(user, project.getId(), tc.getId(), tc);
}

return testSuite;
Expand Down
118 changes: 61 additions & 57 deletions backend/src/main/java/de/learnlib/alex/testing/dao/TestDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,11 @@ private List<Test> create(User user, Long projectId, List<Test> tests, TestSuite
}

public Test get(User user, Long projectId, Long testId) {
final Project project = projectRepository.findById(projectId).orElse(null);
return get(user, project, testId);
final var project = projectRepository.findById(projectId).orElse(null);
final var test = testRepository.findById(testId).orElse(null);
checkAccess(user, project, test);
loadLazyRelations(test);
return test;
}

public List<Test> get(User user, Long projectId, List<Long> ids) {
Expand All @@ -262,67 +265,75 @@ public Test getRoot(User user, Long projectId) {
return root;
}

public void update(User user, Long projectId, Test test) {
final Project project = projectRepository.findById(projectId).orElse(null);
public Test update(User user, Long projectId, Long testId, Test test) {
final var project = projectRepository.findById(projectId).orElse(null);
final var testInDB = testRepository.findById(testId).orElse(null);
checkAccess(user, project, test);
checkRunningTestProcess(user, project, test);

// check lock status
testPresenceService.checkLockStatus(projectId, test.getId(), user.getId());

// make sure the name of the Test Case is unique
Test testInDB = testRepository.findOneByParent_IdAndName(test.getParentId(), test.getName());
if (testInDB != null && !testInDB.getId().equals(test.getId())) {
final var testWithSameName = testRepository.findOneByParent_IdAndName(test.getParentId(), test.getName());
if (testWithSameName != null && !testWithSameName.getId().equals(testInDB.getId())) {
throw new ValidationException("To update a test case or suite its name must be unique within its parent.");
}

final Test root = testRepository.findFirstByProject_IdOrderByIdAsc(test.getProjectId());
if (test.getId().equals(root.getId()) && !test.getName().equals("Root")) {
final var rootTestSuite = testRepository.findFirstByProject_IdOrderByIdAsc(test.getProjectId());
if (test.getId().equals(rootTestSuite.getId()) && !test.getName().equals("Root")) {
throw new ValidationException("The name of the root test suite may not be changed.");
}

testInDB = get(user, test.getProjectId(), test.getId());

test.setId(testInDB.getId());
test.setProject(testInDB.getProject());
test.setParent(getParent(user, projectId, testInDB.getParentId()));

if (test instanceof TestSuite) {
updateTestSuite(user, (TestSuite) test, test.getProject());
} else if (test instanceof TestCase) {
updateTestCase(user, (TestCase) test, test.getProject());
if (testInDB instanceof TestSuite && test instanceof TestSuite) {
final var updatedTestSuite = updateTestSuite((TestSuite) testInDB, (TestSuite) test);
loadLazyRelations(updatedTestSuite);
return updatedTestSuite;
} else if (testInDB instanceof TestCase && test instanceof TestCase) {
final var updatedTestCase = updateTestCase(user, (TestCase) testInDB, (TestCase) test);
loadLazyRelations(updatedTestCase);
return updatedTestCase;
} else {
throw new IllegalStateException("Cannot update a test case with a test suite or vice versa.");
}
}

private List<Long> getStepsWithIds(List<TestCaseStep> steps) {
return steps.stream()
.filter(s -> s.getId() != null)
.map(TestCaseStep::getId)
.collect(Collectors.toList());
}

private void updateTestCase(User user, TestCase testCase, Project project) {
private Test updateTestCase(User user, TestCase testCaseInDB, TestCase testCase) {
checkIfOutputMappingNamesAreUnique(testCase);

beforeSaving(user, project, testCase);

testCase.setGenerated(false);
testCase.setUpdatedOn(ZonedDateTime.now());
testCase.setLastUpdatedBy(user);

final List<Long> allStepIds = new ArrayList<>(); // all ids that still exist in the db
allStepIds.addAll(getStepsWithIds(testCase.getPreSteps()));
allStepIds.addAll(getStepsWithIds(testCase.getSteps()));
allStepIds.addAll(getStepsWithIds(testCase.getPostSteps()));

testCaseStepRepository.deleteAllByTestCase_IdAndIdNotIn(testCase.getId(), allStepIds);

// delete all test case steps that have been removed in the update.
saveTestCaseSteps(testCase.getPreSteps());
saveTestCaseSteps(testCase.getSteps());
saveTestCaseSteps(testCase.getPostSteps());

testRepository.save(testCase);
testCaseInDB.setName(testCase.getName());
testCaseInDB.setGenerated(false);
testCaseInDB.setUpdatedOn(ZonedDateTime.now());
testCaseInDB.setLastUpdatedBy(user);

testCaseInDB.getPreSteps().clear();
testCaseInDB.getSteps().clear();
testCaseInDB.getPostSteps().clear();
testRepository.save(testCaseInDB);

testCaseInDB.getPreSteps().addAll(testCase.getPreSteps());
testCaseInDB.getSteps().addAll(testCase.getSteps());
testCaseInDB.getPostSteps().addAll(testCase.getPostSteps());
removeIdsFromSteps(testCaseInDB);
beforeSaving(user, testCaseInDB.getProject(), testCaseInDB);

saveTestCaseSteps(testCaseInDB.getPreSteps());
saveTestCaseSteps(testCaseInDB.getSteps());
saveTestCaseSteps(testCaseInDB.getPostSteps());
testRepository.save(testCaseInDB);

return testCaseInDB;
}

private void removeIdsFromSteps(TestCase testCase) {
Stream.of(testCase.getPreSteps(), testCase.getSteps(), testCase.getPostSteps())
.flatMap(Collection::stream)
.forEach(s -> {
s.setId(null);
s.getPSymbol().setId(null);
s.getPSymbol().getOutputMappings().forEach(om -> om.setId(null));
s.getPSymbol().getParameterValues().forEach(om -> om.setId(null));
});
}

private void checkIfOutputMappingNamesAreUnique(TestCase testCase) {
Expand All @@ -336,10 +347,9 @@ private void checkIfOutputMappingNamesAreUnique(TestCase testCase) {
SymbolOutputMappingUtils.checkIfMappedNamesAreUnique(oms);
}

private void updateTestSuite(User user, TestSuite testSuite, Project project) {
testSuite.getTests().forEach(t -> t.setParent(null));
beforeSaving(user, project, testSuite);
testRepository.save(testSuite);
private Test updateTestSuite(TestSuite testSuiteInDB, TestSuite testSuite) {
testSuiteInDB.setName(testSuite.getName());
return testRepository.save(testSuiteInDB);
}

public void delete(User user, Long projectId, Long testId) {
Expand Down Expand Up @@ -568,13 +578,6 @@ private void saveTestCaseSteps(List<TestCaseStep> steps) {
});
}

private Test get(User user, Project project, Long testId) {
final Test test = testRepository.findById(testId).orElse(null);
checkAccess(user, project, test);
loadLazyRelations(test);
return test;
}

private void loadLazyRelations(TestResult testResult) {
if (testResult instanceof TestCaseResult) {
Hibernate.initialize(((TestCaseResult) testResult).getOutputs());
Expand Down Expand Up @@ -606,7 +609,8 @@ private void beforeSaving(User user, Project project, Test test) {
if (test instanceof TestSuite) {
TestSuite testSuite = (TestSuite) test;
for (Long testId : testSuite.getTestsAsIds()) {
Test otherTest = get(user, project, testId);
final var otherTest = testRepository.findById(testId).orElse(null);
checkAccess(user, project, otherTest);
testSuite.addTest(otherTest);
}
} else if (test instanceof TestCase) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@ public ResponseEntity<Test> update(@PathVariable("projectId") Long projectId,
@PathVariable("testId") Long testId,
@RequestBody Test test) {
final var user = authContext.getUser();
testDAO.update(user, projectId, test);
webhookService.fireEvent(user, new TestEvent.Updated(test));
return ResponseEntity.ok(test);
final var updatedTest = testDAO.update(user, projectId, testId, test);
webhookService.fireEvent(user, new TestEvent.Updated(updatedTest));
return ResponseEntity.ok(updatedTest);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ server:

alex:
filesRootDir: "./target/postgresql/files"
version: "2.1.0"
version: "2.1.1"
admin:
email: "[email protected]"
password: "admin"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package de.learnlib.alex.integrationtests.resources;

import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -270,6 +271,42 @@ public void shouldUpdateTest() throws Exception {
assertEquals(testCase.getName(), testCaseIdDb.getName());
}

@Test
public void shouldUpdateTestMoveStepToPreSteps() throws Exception {
final var testCase = createTestCaseWithSteps(project.getId(), "test", null, jwtUser1);

final var step = testCase.getSteps().remove(0);
testCase.getPreSteps().add(step);

final var res = testApi.update(testCase.getProjectId(), testCase.getId(), objectMapper.writeValueAsString(testCase), jwtUser1);
assertEquals(HttpStatus.OK.value(), res.getStatus());

final var updatedTestCase = res.readEntity(TestCase.class);
assertAll(
() -> assertEquals(2, updatedTestCase.getPreSteps().size()),
() -> assertEquals(1, updatedTestCase.getSteps().size()),
() -> assertEquals(0, updatedTestCase.getPostSteps().size())
);
}

@Test
public void shouldUpdateTestMoveStepToPostSteps() throws Exception {
final var testCase = createTestCaseWithSteps(project.getId(), "test", null, jwtUser1);

final var step = testCase.getSteps().remove(0);
testCase.getPostSteps().add(step);

final var res = testApi.update(testCase.getProjectId(), testCase.getId(), objectMapper.writeValueAsString(testCase), jwtUser1);
assertEquals(HttpStatus.OK.value(), res.getStatus());

final var updatedTestCase = res.readEntity(TestCase.class);
assertAll(
() -> assertEquals(1, updatedTestCase.getPreSteps().size()),
() -> assertEquals(1, updatedTestCase.getSteps().size()),
() -> assertEquals(1, updatedTestCase.getPostSteps().size())
);
}

@Test
public void shouldUpdateTestLockedByUser() throws Exception {
WebSocketUser webSocketUser = new WebSocketUser("webSocketUser", client, port);
Expand Down
2 changes: 1 addition & 1 deletion backend/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ server:

alex:
filesRootDir: "./target/test-files"
version: "2.1.0"
version: "2.1.1"
admin:
email: "[email protected]"
password: "admin"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.1.0",
"version": "2.1.1",
"type": "project",
"project": {
"name": "ALEX",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.1.0",
"version": "2.1.1",
"type": "project",
"project": {
"name": "ALEX",
Expand Down
2 changes: 1 addition & 1 deletion cli/examples/google/project.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.1.0",
"version": "2.1.1",
"type": "project",
"project": {
"name": "google",
Expand Down
2 changes: 1 addition & 1 deletion cli/examples/google/symbol-groups.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.1.0",
"version": "2.1.1",
"type": "symbolGroups",
"symbolGroups": [
{
Expand Down
2 changes: 1 addition & 1 deletion cli/examples/google/symbols.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.1.0",
"version": "2.1.1",
"type": "symbols",
"symbols": [
{
Expand Down
2 changes: 1 addition & 1 deletion cli/examples/google/tests.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.1.0",
"version": "2.1.1",
"type": "tests",
"tests": [
{
Expand Down
2 changes: 1 addition & 1 deletion cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "alex-cli",
"version": "2.1.0",
"version": "2.1.1",
"repository": {
"url": "https://github.com/LearnLib/alex/tree/developer/cli"
},
"description": "A command line interface for executing tests and learning experiments with ALEX v2.1.0",
"description": "A command line interface for executing tests and learning experiments with ALEX v2.1.1",
"main": "alex-cli.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
Expand Down
2 changes: 1 addition & 1 deletion cli/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@
*
* @type {string}
*/
module.exports.VERSION = "2.1.0"
module.exports.VERSION = "2.1.1"
Loading

0 comments on commit 1d204d3

Please sign in to comment.