From 103f3f61ff490cf68fe639ec949bcbf2bea9762d Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:05:47 +0100 Subject: [PATCH 1/5] :white_check_mark: [Job] Renamed 'jobIntegrationBase' cucumber tag to 'jobService' Signed-off-by: Alberto Codutti --- .github/workflows/kapua-ci.yaml | 4 ++-- qa/RunKapuaTests_asGitAction.sh | 2 +- .../integration/service/job/RunJobServiceI9nTest.java | 11 +++++++---- .../features/job/JobExecutionServiceI9n.feature | 6 +++--- .../test/resources/features/job/JobServiceI9n.feature | 6 +++--- .../features/job/JobTargetsServiceI9n.feature | 6 +++--- .../features/jobScheduling/TriggerServiceI9n.feature | 2 +- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/workflows/kapua-ci.yaml b/.github/workflows/kapua-ci.yaml index efda7145e3b..a6e4d889710 100755 --- a/.github/workflows/kapua-ci.yaml +++ b/.github/workflows/kapua-ci.yaml @@ -165,7 +165,7 @@ jobs: with: tag: '@jobs or @scheduler' needs-docker-images: 'false' - test-jobsIntegrationBase: + test-jobService: needs: build runs-on: ubuntu-latest timeout-minutes: 45 @@ -174,7 +174,7 @@ jobs: uses: actions/checkout@v4 - uses: ./.github/actions/runTestsTaggedAs with: - tag: '@jobsIntegrationBase' + tag: '@jobService' needs-docker-images: 'true' test-jobsIntegration: needs: build diff --git a/qa/RunKapuaTests_asGitAction.sh b/qa/RunKapuaTests_asGitAction.sh index be4b9d8f8e5..34c015cbfb3 100755 --- a/qa/RunKapuaTests_asGitAction.sh +++ b/qa/RunKapuaTests_asGitAction.sh @@ -5,7 +5,7 @@ #RUNS BOTH UNIT AND INTEGRATION TESTS AND FINALLY BUILDS THE PROJECT #FIRT, JUNIT TESTS ARE LAUNCHED, IF THEY PASS CUCUMBER TESTS ARE THEN EXECUTED -cucumberTags=('@brokerAcl' '@tag' '@broker' '@device' '@deviceManagement' '@connection' '@datastore' '@user' '@userIntegrationBase' '@userIntegration' '@security' '@jobs' '@scheduler' '@jobsIntegrationBase' '@triggerService' '@account' '@translator' '@jobEngineStepDefinitions' '@jobEngineStartOfflineDevice' '@jobEngineRestartOnlineDevice' '@jobEngineStartOnlineDevice' '@jobEngineRestartOfflineDevice' '@jobEngineRestartOnlineDeviceSecondPart' '@jobsIntegration' '@jobEngineServiceStop' '@endpoint' '@deviceRegistry' '@role' '@group') +cucumberTags=('@brokerAcl' '@tag' '@broker' '@device' '@deviceManagement' '@connection' '@datastore' '@user' '@userIntegrationBase' '@userIntegration' '@security' '@jobs' '@scheduler' '@jobService' '@triggerService' '@account' '@translator' '@jobEngineStepDefinitions' '@jobEngineStartOfflineDevice' '@jobEngineRestartOnlineDevice' '@jobEngineStartOnlineDevice' '@jobEngineRestartOfflineDevice' '@jobEngineRestartOnlineDeviceSecondPart' '@jobsIntegration' '@jobEngineServiceStop' '@endpoint' '@deviceRegistry' '@role' '@group') exitCodesTests=() #will contain exit code for each batch of tests #checks if the last build command exited normally and exits if necessary diff --git a/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java b/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java index b0f0b5cb430..1736c114afc 100644 --- a/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java +++ b/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -18,16 +18,19 @@ @RunWith(Cucumber.class) @CucumberOptions( - features = {"classpath:features/job/JobServiceI9n.feature", + features = { + "classpath:features/job/JobServiceI9n.feature", "classpath:features/job/JobTargetsServiceI9n.feature", "classpath:features/job/JobExecutionServiceI9n.feature" }, - glue = {"org.eclipse.kapua.service.job.steps", + glue = { + "org.eclipse.kapua.service.job.steps", "org.eclipse.kapua.service.user.steps", "org.eclipse.kapua.qa.common", "org.eclipse.kapua.qa.integration.steps" }, - plugin = {"pretty", + plugin = { + "pretty", "html:target/cucumber/JobServiceI9n", "json:target/JobServiceI9n_cucumber.json"}, monochrome = true) diff --git a/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature index 4308d95271f..c41ccfdee79 100644 --- a/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 @@ -10,9 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobsIntegrationBase -@jobExecutionService @env_docker_base +@jobService +@jobExecutionService Feature: Job Execution service CRUD tests The Job service is responsible for maintaining the status of the target step executions. diff --git a/qa/integration/src/test/resources/features/job/JobServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobServiceI9n.feature index b809ddec505..061e40b7ab0 100644 --- a/qa/integration/src/test/resources/features/job/JobServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobServiceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 @@ -10,9 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobsIntegrationBase -@jobService @env_docker_base +@jobService +@jobService Feature: Job service CRUD tests The Job service is responsible for executing scheduled actions on various targets. diff --git a/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature index 0ee2d53561d..e6a6684429c 100644 --- a/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 @@ -10,9 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobsIntegrationBase -@jobTargetService @env_docker_base +@jobService +@jobTargetService Feature: Job Target service CRUD tests The Job service is responsible for maintaining a list of job targets. diff --git a/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature b/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature index ec7c4fb88ef..f935d64a57f 100644 --- a/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature +++ b/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature @@ -10,7 +10,7 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobsIntegrationBase +@jobService @env_docker_base Feature: Trigger service tests From 360f05fd49eec8a7df93236cef36d30ed1592992 Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:09:33 +0100 Subject: [PATCH 2/5] :white_check_mark: [Job] Added 'jobEngine' cucumber tag to JobEngine-related feature files Signed-off-by: Alberto Codutti --- .../JobEngineServiceKeystoreStepDefinitionsI9n.feature | 3 ++- .../jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature | 3 ++- .../jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature | 3 ++- .../JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature | 3 ++- .../jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature | 3 ++- .../jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature | 3 ++- .../jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature index 3fd26b87760..1ae7660b004 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature @@ -10,9 +10,10 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### +@env_docker +@jobEngine @jobEngineStepDefinitions @deviceManagementKeystore -@env_docker Feature: Job Engine Service - Keystore Step Definitions diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature index 68be0f3623c..632c033d98d 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature @@ -10,8 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobEngineRestartOfflineDevice @env_docker +@jobEngine +@jobEngineRestartOfflineDevice Feature: JobEngineService tests for restarting job with offline device diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature index 8b17d083a16..a9006f77921 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature @@ -10,8 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobEngineRestartOnlineDevice @env_docker +@jobEngine +@jobEngineRestartOnlineDevice Feature: JobEngineService restart job tests with online device diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature index d7168de2915..0f707943612 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature @@ -10,8 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobEngineRestartOnlineDeviceSecondPart @env_docker +@jobEngine +@jobEngineRestartOnlineDeviceSecondPart Feature: JobEngineService restart job tests with online device - second part diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature index 4a918acb9b2..85aa2c49806 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature @@ -10,8 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobEngineStartOfflineDevice @env_docker +@jobEngine +@jobEngineStartOfflineDevice Feature: JobEngineService tests for starting job with offline device diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature index 2d92386e066..fd0df9f6ba7 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature @@ -10,8 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobEngineStartOnlineDevice @env_docker +@jobEngine +@jobEngineStartOnlineDevice Feature: JobEngineService start job tests with online device diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature index 441f655016b..e536d4cdba5 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature @@ -10,8 +10,9 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobEngineServiceStop @env_docker +@jobEngine +@jobEngineServiceStop Feature: JobEngineService stop job tests with online device Job Engine Service test scenarios for stopping job. This feature file contains scenarios for stopping job with one target and one step, From ae5c93de954bba1277a1008c8aea28776e0a3e14 Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:10:53 +0100 Subject: [PATCH 3/5] :white_check_mark: [Job] Added 'jobEngine' cucumber tag to JobEngine-related feature files Signed-off-by: Alberto Codutti --- .../JobEngineServiceKeystoreStepDefinitionsI9n.feature | 2 +- .../jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature | 2 +- .../jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature | 2 +- .../JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature | 2 +- .../jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature | 2 +- .../jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature | 2 +- .../jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature index 1ae7660b004..2431fa2d5e6 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature index 632c033d98d..70990c1dcf8 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature index a9006f77921..73abf95c015 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature index 0f707943612..7a8ed4835f7 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature index 85aa2c49806..14d0b7baaf2 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature index fd0df9f6ba7..19b9a253e3d 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature index e536d4cdba5..edd6dd9e7ac 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others +# Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others # # This program and the accompanying materials are made # available under the terms of the Eclipse Public License 2.0 From 4f156daf2dbb5fcda6f43bdd6c1b92e63e05b186 Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:49:24 +0100 Subject: [PATCH 4/5] :recycle: [Test] Added new set of test cases to test JobEngine basic operations Signed-off-by: Alberto Codutti --- .github/workflows/kapua-ci.yaml | 13 +- .../eclipse/kapua/qa/common/BasicSteps.java | 197 +++++++------ .../org/eclipse/kapua/qa/common/DBHelper.java | 6 +- .../qa/common/TestJAXBContextProvider.java | 31 ++- .../qa/integration/steps/DockerSteps.java | 15 +- .../service/job/RunJobServiceI9nTest.java | 3 +- .../jobEngine/RunJobEngineService9nTest.java | 39 +++ .../job/JobExecutionServiceI9n.feature | 77 ++--- .../features/job/JobServiceI9n.feature | 7 +- .../features/job/JobTargetsServiceI9n.feature | 7 +- ...eServiceKeystoreStepDefinitionsI9n.feature | 5 +- .../JobEngineServiceOperations.feature | 263 ++++++++++++++++++ ...gineServiceRestartOfflineDeviceI9n.feature | 5 +- ...ngineServiceRestartOnlineDeviceI9n.feature | 5 +- ...ceRestartOnlineDeviceSecondPartI9n.feature | 5 +- ...EngineServiceStartOfflineDeviceI9n.feature | 5 +- ...bEngineServiceStartOnlineDeviceI9n.feature | 5 +- ...obEngineServiceStopOnlineDeviceI9n.feature | 5 +- .../ExecuteOnDeviceConnectI9n.feature | 2 +- .../jobScheduling/TriggerServiceI9n.feature | 2 +- .../device/registry/steps/BrokerSteps.java | 34 ++- .../device/registry/steps/KuraDevice.java | 18 +- .../service/job/steps/JobEngineSteps.java | 126 ++++++++- .../job/steps/JobExecutionServiceSteps.java | 47 +++- .../service/job/steps/JobServiceSteps.java | 84 +++--- .../service/job/steps/JobServiceTestBase.java | 34 ++- .../job/steps/JobStepServiceSteps.java | 37 ++- .../job/steps/JobTargetServiceSteps.java | 125 ++++++++- 28 files changed, 995 insertions(+), 207 deletions(-) create mode 100644 qa/integration/src/test/java/org/eclipse/kapua/integration/service/jobEngine/RunJobEngineService9nTest.java create mode 100644 qa/integration/src/test/resources/features/jobEngine/JobEngineServiceOperations.feature diff --git a/.github/workflows/kapua-ci.yaml b/.github/workflows/kapua-ci.yaml index a6e4d889710..9f2d69e84e5 100755 --- a/.github/workflows/kapua-ci.yaml +++ b/.github/workflows/kapua-ci.yaml @@ -174,7 +174,18 @@ jobs: uses: actions/checkout@v4 - uses: ./.github/actions/runTestsTaggedAs with: - tag: '@jobService' + tag: '@job and @it' + needs-docker-images: 'true' + test-jobEngineOperations: + needs: build + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - name: Clones Kapua repo inside the runner + uses: actions/checkout@v4 + - uses: ./.github/actions/runTestsTaggedAs + with: + tag: '@jobEngineOperations' needs-docker-images: 'true' test-jobsIntegration: needs: build diff --git a/qa/common/src/main/java/org/eclipse/kapua/qa/common/BasicSteps.java b/qa/common/src/main/java/org/eclipse/kapua/qa/common/BasicSteps.java index 2b8399c9b13..e80d8b57b2a 100644 --- a/qa/common/src/main/java/org/eclipse/kapua/qa/common/BasicSteps.java +++ b/qa/common/src/main/java/org/eclipse/kapua/qa/common/BasicSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2022 Red Hat Inc and others. + * Copyright (c) 2017, 2024 Red Hat Inc and others. * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -76,7 +76,6 @@ public class BasicSteps extends TestBase { public static final String LIFECYCLE_CONSUMER_CONTAINER_NAME = "lifecycle-consumer"; public static final String AUTH_SERVICE_CONTAINER_NAME = "auth-service"; public static final String API_CONTAINER_NAME = "rest-api"; - public static final int JOB_ENGINE_CONTAINER_PORT = 8080; public static final String LAST_CREDENTIAL_ID = "LastCredentialId"; @@ -93,30 +92,114 @@ public class BasicSteps extends TestBase { private static final String ASSERT_ERROR_NAME = "AssertErrorName"; private static final String ASSERT_ERROR_CAUGHT = "AssertErrorCaught"; - private DBHelper database; + private final DBHelper database; @Inject public BasicSteps(StepData stepData, DBHelper database) { super(stepData); + this.database = database; } @Before(value = "@setup and (@env_docker or @env_docker_base)", order = 0) public void initParametersDocker(Scenario scenario) { logger.info("=====> Init parameters for docker environment..."); - setProperties(scenario, "kapuadb", "true", "localhost", "3306", "DEFAULT", "org.h2.Driver", - "jdbc:h2:tcp", "certificates/jwt/test.key", "certificates/jwt/test.cert", "localhost", "http://job-engine:8080/v1", "trusted", "MODE=MySQL"); + setProperties(scenario, + "kapuadb", + "true", + "localhost", + "3306", + "DEFAULT", + "org.h2.Driver", + "jdbc:h2:tcp", + "certificates/jwt/test.key", + "certificates/jwt/test.cert", + "localhost", + "http://job-engine:8080/v1", + "trusted", + "MODE=MySQL"); logger.info("=====> Init parameters for docker environment... DONE"); } @Before(value = "@setup and @env_none", order = 0) public void initParametersEmbedded(Scenario scenario) { logger.info("=====> Init parameters for embedded environment..."); - setProperties(scenario, "kapuadb", "true", "", "", "H2", "org.h2.Driver", "jdbc:h2:mem:", - "certificates/jwt/test.key", "certificates/jwt/test.cert", "localhost", "http://localhost:8080/v1", "trusted", null); + setProperties(scenario, + "kapuadb", + "true", + "", + "", + "H2", + "org.h2.Driver", + "jdbc:h2:mem:", + "certificates/jwt/test.key", + "certificates/jwt/test.cert", + "localhost", + "http://localhost:8080/v1", + "trusted", + null); logger.info("=====> Init parameters for embedded environment... DONE"); } + @Before(value = "(@env_docker or @env_docker_base) and not (@setup or @teardown)", order = 0) + public void beforeScenarioDockerFull(Scenario scenario) { + beforeCommon(scenario); + } + + @Before(value = "@env_none and not (@setup or @teardown)", order = 0) + public void beforeScenarioDockerBase(Scenario scenario) { + beforeCommon(scenario); + + databaseInit(); + } + + @After(value = "@env_docker_base and @setup", order = 0) + public void afterScenarioDockerBaseSetup(Scenario scenario) { + databaseInit(); + } + + @After(value = "(@env_docker or @env_docker_base) and not (@setup or @teardown)", order = 0) + public void afterScenarioDockerFull(Scenario scenario) { + // afterScenarioDocker(scenario); + logger.info("Database cleanup..."); + database.deleteAll(); + logger.info("Database cleanup... DONE"); + SecurityUtils.getSubject().logout(); + KapuaSecurityUtils.clearSession(); + } + + @After(value = "@env_none and not (@setup or @teardown)", order = 0) + public void afterScenarioNone(Scenario scenario) { + logger.info("Database drop..."); + try { + database.dropAll(); + database.close(); + } catch (Exception e) { + logger.error("Failed execute @After", e); + } + logger.info("Database drop... DONE"); + KapuaSecurityUtils.clearSession(); + } + + protected void beforeCommon(Scenario scenario) { + this.scenario = scenario; + stepData.clear(); + } + + protected void databaseInit() { + database.init(); + // Create KapuaSession using KapuaSecurityUtils and kapua-sys user as logged in user. + // All operations on database are performed using system user. + // Only for unit tests. Integration tests assume that a real login is performed. + KapuaSession kapuaSession = new KapuaSession(null, SYS_SCOPE_ID, SYS_USER_ID); + KapuaSecurityUtils.setSession(kapuaSession); + } + + + // + // Data Table Types + // + @DataTableType public CucAccount cucAccount(Map entry) { return new CucAccount( @@ -330,6 +413,9 @@ public CucUserProfile cucUserProfile(Map entry) { entry.get("email")); } + // + // Parameter Types + // @ParameterType(".*") public org.eclipse.kapua.transport.message.jms.JmsTopic topic(String topic) { return new JmsTopic(topic); @@ -337,13 +423,26 @@ public org.eclipse.kapua.transport.message.jms.JmsTopic topic(String topic) { @ParameterType(value = "true|True|TRUE|false|False|FALSE") public boolean booleanValue(String value) { - return Boolean.valueOf(value); - } + return Boolean.parseBoolean(value); + } + + private void setProperties(Scenario scenario, + String schema, + String updateSchema, + String dbHost, + String dbPort, + String dbConnResolver, + String dbDriver, + String jdbcConnection, + String jwtKey, + String jwtCertificate, + String brokerHost, + String jobEngineUrl, + String jobEngineAuthMode, + String additionalOptions) { - private void setProperties(Scenario scenario, String schema, String updateSchema, - String dbHost, String dbPort, String dbConnResolver, String dbDriver, String jdbcConnection, - String jwtKey, String jwtCertificate, String brokerHost, String jobEngineUrl, String jobEngineAuthMode, String additionalOptions) { SystemSetting.resetInstance(); + System.setProperty(SystemSettingKey.DB_SCHEMA.key(), schema); System.setProperty(SystemSettingKey.DB_SCHEMA_UPDATE.key(), updateSchema); System.setProperty(SystemSettingKey.DB_CONNECTION_HOST.key(), dbHost); @@ -392,80 +491,6 @@ private void setSpecificProperties(Scenario scenario) { } } - @Before - public void checkWaitMultipier() { - if (WAIT_MULTIPLIER != 1.0d) { - logger.info("Wait multiplier active: {}", WAIT_MULTIPLIER); - } - } - - @Before(value = "(@env_docker or @env_docker_base) and not (@setup or @teardown)", order = 0) - public void beforeScenarioDockerFull(Scenario scenario) { - beforeCommon(scenario); - } - - @Before(value = "@env_none and not (@setup or @teardown)", order = 0) - public void beforeScenarioDockerBase(Scenario scenario) { - beforeCommon(scenario); - databaseInit(); - } - - @After(value = "(@env_docker or @env_docker_base) and not (@setup or @teardown)", order = 0) - public void afterScenarioDockerFull(Scenario scenario) { - afterScenarioDocker(scenario); - } - - @After(value = "@env_docker_base and @setup", order = 0) - public void afterScenarioDockerBaseSetup(Scenario scenario) { - databaseInit(); - } - - @After(value = "@env_none and not (@setup or @teardown)", order = 0) - public void afterScenarioNone(Scenario scenario) { - afterScenarioNoDocker(scenario); - } - - protected void beforeCommon(Scenario scenario) { - this.scenario = scenario; - stepData.clear(); - } - - protected void databaseInit() { - database.init(); - // Create KapuaSession using KapuaSecurtiyUtils and kapua-sys user as logged in user. - // All operations on database are performed using system user. - // Only for unit tests. Integration tests assume that a real login is performed. - KapuaSession kapuaSession = new KapuaSession(null, SYS_SCOPE_ID, SYS_USER_ID); - KapuaSecurityUtils.setSession(kapuaSession); - } - - protected void afterScenarioDocker(Scenario scenario) { - logger.info("Database cleanup..."); - database.deleteAll(); - logger.info("Database cleanup... DONE"); - SecurityUtils.getSubject().logout(); - KapuaSecurityUtils.clearSession(); - } - - protected void afterScenarioNoDocker(Scenario scenario) { - logger.info("Database drop..."); - try { - database.dropAll(); - database.close(); - } catch (Exception e) { - logger.error("Failed execute @After", e); - } - logger.info("Database drop... DONE"); - KapuaSecurityUtils.clearSession(); - } - - @Given("A placeholder step") - public void doNothing() { - // An empty placeholder step. Just a breakpoint anchor point. Used to pause - // test execution by placing a breakpoint into. - Integer a = 10; - } - @Given("Scope with ID {int}") public void setSpecificScopeId(Integer id) { stepData.put(LAST_ACCOUNT_ID, getKapuaId(id)); diff --git a/qa/common/src/main/java/org/eclipse/kapua/qa/common/DBHelper.java b/qa/common/src/main/java/org/eclipse/kapua/qa/common/DBHelper.java index b080b346828..3ba27c97195 100644 --- a/qa/common/src/main/java/org/eclipse/kapua/qa/common/DBHelper.java +++ b/qa/common/src/main/java/org/eclipse/kapua/qa/common/DBHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -100,7 +100,7 @@ public void deleteAllAndClose() { */ public void deleteAll() { KapuaConfigurableServiceSchemaUtilsWithResources.scriptSession(FULL_SCHEMA_PATH, DELETE_SCRIPT); - Optional.ofNullable(cacheManager).ifPresent(cm -> cm.invalidateAll()); + Optional.ofNullable(cacheManager).ifPresent(KapuaCacheManager::invalidateAll); } public void dropAll() throws SQLException { @@ -118,7 +118,7 @@ public void dropAll() throws SQLException { } else { logger.warn("================================> invoked drop all on closed connection!"); } - Optional.ofNullable(cacheManager).ifPresent(cm -> cm.invalidateAll()); + Optional.ofNullable(cacheManager).ifPresent(KapuaCacheManager::invalidateAll); } } diff --git a/qa/common/src/main/java/org/eclipse/kapua/qa/common/TestJAXBContextProvider.java b/qa/common/src/main/java/org/eclipse/kapua/qa/common/TestJAXBContextProvider.java index 7d176045afa..3b239bf124b 100644 --- a/qa/common/src/main/java/org/eclipse/kapua/qa/common/TestJAXBContextProvider.java +++ b/qa/common/src/main/java/org/eclipse/kapua/qa/common/TestJAXBContextProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2016, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -14,7 +14,17 @@ import org.eclipse.kapua.KapuaException; import org.eclipse.kapua.commons.configuration.metatype.TscalarImpl; +import org.eclipse.kapua.commons.rest.model.IsJobRunningResponse; import org.eclipse.kapua.commons.rest.model.errors.ExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobAlreadyRunningExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobInvalidTargetExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobMissingStepExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobMissingTargetExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobNotRunningExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobResumingExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobRunningExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobStartingExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.JobStoppingExceptionInfo; import org.eclipse.kapua.commons.service.event.store.api.EventStoreRecordCreator; import org.eclipse.kapua.commons.service.event.store.api.EventStoreRecordListResult; import org.eclipse.kapua.commons.service.event.store.api.EventStoreRecordQuery; @@ -133,13 +143,28 @@ public JAXBContext getJAXBContext() throws KapuaException { // Jobs Job.class, - JobStartOptionsClient.class, - JobStartOptions.class, JobListResult.class, JobXmlRegistry.class, + + // Job Engine + JobStartOptionsClient.class, + JobStartOptions.class, JobTargetSublist.class, + IsJobRunningResponse.class, JobStepPropertiesOverrides.class, + // Job Engine Client + JobAlreadyRunningExceptionInfo.class, + JobInvalidTargetExceptionInfo.class, + JobMissingStepExceptionInfo.class, + JobMissingTargetExceptionInfo.class, + JobNotRunningExceptionInfo.class, + JobResumingExceptionInfo.class, + JobRunningExceptionInfo.class, + JobStartingExceptionInfo.class, + JobStoppingExceptionInfo.class, + + // Device Management Command DeviceCommandInput.class, DeviceCommandOutput.class, diff --git a/qa/integration-steps/src/main/java/org/eclipse/kapua/qa/integration/steps/DockerSteps.java b/qa/integration-steps/src/main/java/org/eclipse/kapua/qa/integration/steps/DockerSteps.java index e0770152bfc..215e9a04b9b 100644 --- a/qa/integration-steps/src/main/java/org/eclipse/kapua/qa/integration/steps/DockerSteps.java +++ b/qa/integration-steps/src/main/java/org/eclipse/kapua/qa/integration/steps/DockerSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -305,9 +305,20 @@ public void startDockerEnvironmentWithResources(List dockerContainers) t } } - private void cleanDockerEnvironmentInternal() throws DockerException, InterruptedException { + /** + * Stops all running Docker containers and removes the Docker network + * + * @throws Exception + * @since 2.1.0 + */ + @Given("Stop Docker environment") + public void cleanDockerEnvironmentInternal() throws Exception { removeContainers( Arrays.asList( + BasicSteps.TELEMETRY_CONSUMER_CONTAINER_NAME, + BasicSteps.LIFECYCLE_CONSUMER_CONTAINER_NAME, + BasicSteps.AUTH_SERVICE_CONTAINER_NAME, + BasicSteps.MESSAGE_BROKER_CONTAINER_NAME, BasicSteps.JOB_ENGINE_CONTAINER_NAME, BasicSteps.EVENTS_BROKER_CONTAINER_NAME, BasicSteps.ES_CONTAINER_NAME, diff --git a/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java b/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java index 1736c114afc..9b80438a033 100644 --- a/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java +++ b/qa/integration/src/test/java/org/eclipse/kapua/integration/service/job/RunJobServiceI9nTest.java @@ -32,7 +32,8 @@ plugin = { "pretty", "html:target/cucumber/JobServiceI9n", - "json:target/JobServiceI9n_cucumber.json"}, + "json:target/JobServiceI9n_cucumber.json" + }, monochrome = true) public class RunJobServiceI9nTest { } diff --git a/qa/integration/src/test/java/org/eclipse/kapua/integration/service/jobEngine/RunJobEngineService9nTest.java b/qa/integration/src/test/java/org/eclipse/kapua/integration/service/jobEngine/RunJobEngineService9nTest.java new file mode 100644 index 00000000000..4f277d8da84 --- /dev/null +++ b/qa/integration/src/test/java/org/eclipse/kapua/integration/service/jobEngine/RunJobEngineService9nTest.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2024, 2024 Eurotech and/or its affiliates and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.integration.service.jobEngine; + +import io.cucumber.junit.Cucumber; +import io.cucumber.junit.CucumberOptions; +import org.junit.runner.RunWith; + +@RunWith(Cucumber.class) +@CucumberOptions( + features = { + "classpath:features/jobEngine/JobEngineServiceOperations.feature", + }, + glue = { + "org.eclipse.kapua.service.job.steps", + "org.eclipse.kapua.service.user.steps", + "org.eclipse.kapua.qa.common", + "org.eclipse.kapua.qa.integration.steps", + "org.eclipse.kapua.service.account.steps", + "org.eclipse.kapua.service.device.registry.steps", + }, + plugin = { + "pretty", + "html:target/cucumber/JobEngineServiceOfflineDeviceI9n", + "json:target/JobEngineServiceOfflineDeviceI9n_cucumber.json" + }, + monochrome = true) +public class RunJobEngineService9nTest { +} diff --git a/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature index c41ccfdee79..30d95e989ff 100644 --- a/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature @@ -11,11 +11,12 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker_base -@jobService +@it # This is an IT because Job.*Service operations may require a Job Engine instance running +@job @jobExecutionService Feature: Job Execution service CRUD tests - The Job service is responsible for maintaining the status of the target step executions. + The Job service is responsible for maintaining the status of the target step executions. @setup Scenario: Setup test resources @@ -26,38 +27,38 @@ Feature: Job Execution service CRUD tests | events-broker | | job-engine | -Scenario: Regular job execution creation + Scenario: Regular job execution creation Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob" And A regular job execution item Then No exception was thrown And The job execution matches the creator -Scenario: Update job id of an existing execution item + Scenario: Update job id of an existing execution item Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob" And A regular job execution item Then I create a job with the name "TestJob2" When I update the job id for the execution item Then No exception was thrown -Scenario: Update the end time of an existing execution item + Scenario: Update the end time of an existing execution item Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob" And A regular job execution item When I update the end time of the execution item @@ -65,26 +66,26 @@ Scenario: Update the end time of an existing execution item When I search for the last job execution in the database Then The job execution items match -Scenario: Delete a job execution item + Scenario: Delete a job execution item Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob" And A regular job execution item Then I delete the last job execution in the database When I search for the last job execution in the database Then There is no such job execution item in the database -Scenario: Delete a job execution item twice + Scenario: Delete a job execution item twice Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob" And A regular job execution item Then I delete the last job execution in the database @@ -92,13 +93,13 @@ Scenario: Delete a job execution item twice Then I delete the last job execution in the database Then An exception was thrown -Scenario: Create and count several execution items for a job + Scenario: Create and count several execution items for a job Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob" And A regular job execution item And A regular job execution item @@ -108,13 +109,13 @@ Scenario: Create and count several execution items for a job When I count the execution items for the current job Then I count 4 -Scenario: Query for executions of a specific job + Scenario: Query for executions of a specific job Given I login as user with name "kapua-sys" and password "kapua-password" And I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | Given I create a job with the name "TestJob1" And A regular job execution item And A regular job execution item @@ -132,13 +133,13 @@ Scenario: Query for executions of a specific job Then I count 3 -Scenario: Query for executions of a specific job using start date + Scenario: Query for executions of a specific job using start date Given I login as user with name "kapua-sys" and password "kapua-password" * I configure the job service - | type | name | value | - | boolean | infiniteChildEntities | true | - | integer | maxNumberChildEntities | 5 | + | type | name | value | + | boolean | infiniteChildEntities | true | + | integer | maxNumberChildEntities | 5 | * I create a job with the name "TestJob" * A regular job execution item * A regular job execution item @@ -151,12 +152,12 @@ Scenario: Query for executions of a specific job using start date When I query for the execution items for the current job starting from date in the past Then I count 4 -Scenario: Job execution factory sanity checks + Scenario: Job execution factory sanity checks And I test the sanity of the job execution factory -@teardown - Scenario: Stop test environment - Given Stop full docker environment + @teardown + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance And Reset Security Context diff --git a/qa/integration/src/test/resources/features/job/JobServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobServiceI9n.feature index 061e40b7ab0..6ab4702502c 100644 --- a/qa/integration/src/test/resources/features/job/JobServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobServiceI9n.feature @@ -11,7 +11,8 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker_base -@jobService +@it # This is an IT because Job.*Service operations may require a Job Engine instance running +@job @jobService Feature: Job service CRUD tests @@ -256,7 +257,7 @@ Feature: Job service CRUD tests Then No exception was thrown @teardown - Scenario: Stop test environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance And Reset Security Context \ No newline at end of file diff --git a/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature index e6a6684429c..a60115f98a0 100644 --- a/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobTargetsServiceI9n.feature @@ -11,7 +11,8 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker_base -@jobService +@it # This is an IT because Job.*Service operations may require a Job Engine instance running +@job @jobTargetService Feature: Job Target service CRUD tests @@ -157,7 +158,7 @@ Feature: Job Target service CRUD tests When I test the sanity of the job target factory @teardown - Scenario: Stop test environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance And Reset Security Context diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature index 2431fa2d5e6..2c6a0764355 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceKeystoreStepDefinitionsI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineStepDefinitions @deviceManagementKeystore @@ -151,6 +152,6 @@ Feature: Job Engine Service - Keystore Step Definitions And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance \ No newline at end of file diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceOperations.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceOperations.feature new file mode 100644 index 00000000000..e081ff20a73 --- /dev/null +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceOperations.feature @@ -0,0 +1,263 @@ +############################################################################### +# Copyright (c) 2024, 2024 Eurotech and/or its affiliates and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Eurotech - initial API and implementation +############################################################################### +@env_docker +@it +@jobEngine +@jobEngineOperations + +Feature: JobEngineService stop job tests with online device + Job Engine Service test scenarios for stopping job. This feature file contains scenarios for stopping job with one target and one step, + one target and multiple steps, multiple targets and one step and multiple targets and multiple steps. + + @setup + Scenario: Setup test resources + Given Init Security Context + And Init Jaxb Context + And Start Docker environment with resources + | db | + | events-broker | + | job-engine | + | message-broker | + | broker-auth-service | + | consumer-lifecycle | + + Scenario: Start a Job - Without JobTarget + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I create a job with the name "Test Job - Empty Targets" + Then I expect the exception "JobMissingTargetException" with the text "does not have targets configured" + And I start a job + And An exception was thrown + + Scenario: Start a Job - Without JobStep + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I create a device with name "Test Target" + And I create a job with the name "TestJob - Empty Steps" + And I add device targets to job + | Test Target | + Then I expect the exception "JobMissingStepException" with the text "does not have steps configured" + And I start a job + And An exception was thrown + + Scenario: Start a Job - JobTarget ok + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 1 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_OK" + + Scenario: Start a Job - JobTarget failed + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I create a device with name "Test Target" + And I create a job with the name "TestJob" + And I add device targets to job + | Test Target | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 1 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_FAILED" + + Scenario: Start a Job - JobTarget ok then ok + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 1 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_OK" + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 2 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_OK" + + Scenario: Start a Job - JobTarget failed then ok + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I create a device with name "rpione3" + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 1 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_FAILED" + Then I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 2 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_OK" + + Scenario: Start a Job - Two JobSteps + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + And I search for step definition with the name + | Bundle Stop | + And I add job step to job with name "Test Step - Bundle Stop" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + When I start a job + And I wait job to finish its execution up to 10s + Then I confirm that job has 1 job execution + And I confirm that job target in job has step index 1 and status "PROCESS_OK" + + Scenario: Check a Job - Running status + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Command Execution | + And I add job step to job with name "Test Step - Command Exec" and with selected job step definition and properties + | name | type | value | + | commandInput | org.eclipse.kapua.service.device.management.command.DeviceCommandInput | ping-c108.8.8.830000false | + | timeout | java.lang.Long | 15000 | + Then I confirm job is not running + When I start a job + And I wait for 5 seconds + Then I confirm job is running + When I wait job to finish its execution up to 30s + Then I confirm job is not running + Then I confirm that job has 1 job execution + And I confirm that job target in job has step index 0 and status "PROCESS_OK" + + Scenario: Stop a Job - Not running, never run + Given I login as user with name "kapua-sys" and password "kapua-password" + And I create a device with name "Test Target" + And I create a job with the name "TestJob" + And I add device targets to job + | Test Target | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + Then I expect the exception "JobNotRunningException" with the text "cannot be stopped because it is not running" + And I stop the job + And An exception was thrown + + Scenario: Stop a Job - Not running, but was + + Given I login as user with name "kapua-sys" and password "kapua-password" + And I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + When I start a job + And I wait job to finish its execution up to 10s + Then I expect the exception "JobNotRunningException" with the text "cannot be stopped because it is not running" + And I stop the job + And An exception was thrown + + Scenario: Stop a Job - Running + Given I login as user with name "kapua-sys" and password "kapua-password" + And I start the Kura Mock + And Device birth message is sent + And Device "rpione3" is connected within 10s + And I create a job with the name "TestJob" + And I add device targets to job + | rpione3 | + And I search for step definition with the name + | Command Execution | + And I add job step to job with name "Test Step - Command Exec" and with selected job step definition and properties + | name | type | value | + | commandInput | org.eclipse.kapua.service.device.management.command.DeviceCommandInput | ping-c108.8.8.830000false | + | timeout | java.lang.Long | 15000 | + And I search for step definition with the name + | Bundle Start | + And I add job step to job with name "Test Step - Bundle Start" and with selected job step definition and properties + | name | type | value | + | bundleId | java.lang.String | 34 | + | timeout | java.lang.Long | 5000 | + And I start a job + And I wait for 5 seconds + When I stop the job + Then I wait job to finish its execution up to 10s + And I confirm that job has 1 job execution + And I confirm that job target in job has step index 1 and status "PROCESS_AWAITING" + When I start a job + Then I wait job to finish its execution up to 10s + And I confirm that job has 2 job execution + And I confirm that job target in job has step index 1 and status "PROCESS_OK" + + @teardown + Scenario: Tear down test resources + Given I logout + And KuraMock is disconnected + And Stop Docker environment + And Clean Locator Instance \ No newline at end of file diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature index 70990c1dcf8..2504a7ed398 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOfflineDeviceI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineRestartOfflineDevice @@ -1020,6 +1021,6 @@ Feature: JobEngineService tests for restarting job with offline device And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature index 73abf95c015..11aad3f16e2 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineRestartOnlineDevice @@ -503,6 +504,6 @@ Feature: JobEngineService restart job tests with online device And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature index 7a8ed4835f7..c401b75f0e5 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceRestartOnlineDeviceSecondPartI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineRestartOnlineDeviceSecondPart @@ -430,6 +431,6 @@ Feature: JobEngineService restart job tests with online device - second part And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature index 14d0b7baaf2..4b41facd4c0 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOfflineDeviceI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineStartOfflineDevice @@ -1134,6 +1135,6 @@ Feature: JobEngineService tests for starting job with offline device And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature index 19b9a253e3d..b1f7a8fab8c 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStartOnlineDeviceI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineStartOnlineDevice @@ -863,6 +864,6 @@ Feature: JobEngineService start job tests with online device And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance diff --git a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature index edd6dd9e7ac..1ebfd8d64c0 100644 --- a/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceStopOnlineDeviceI9n.feature @@ -11,6 +11,7 @@ # Eurotech - initial API and implementation ############################################################################### @env_docker +@it @jobEngine @jobEngineServiceStop @@ -514,6 +515,6 @@ Feature: JobEngineService stop job tests with online device # And I logout @teardown - Scenario: Stop full docker environment - Given Stop full docker environment + Scenario: Tear down test resources + Given Stop Docker environment And Clean Locator Instance diff --git a/qa/integration/src/test/resources/features/jobScheduling/ExecuteOnDeviceConnectI9n.feature b/qa/integration/src/test/resources/features/jobScheduling/ExecuteOnDeviceConnectI9n.feature index d8f674f19ca..e10749eb185 100644 --- a/qa/integration/src/test/resources/features/jobScheduling/ExecuteOnDeviceConnectI9n.feature +++ b/qa/integration/src/test/resources/features/jobScheduling/ExecuteOnDeviceConnectI9n.feature @@ -10,8 +10,8 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobsIntegration @env_docker +@jobsIntegration Feature: JobEngineService execute job on device connect diff --git a/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature b/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature index f935d64a57f..810c6d01616 100644 --- a/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature +++ b/qa/integration/src/test/resources/features/jobScheduling/TriggerServiceI9n.feature @@ -10,8 +10,8 @@ # Contributors: # Eurotech - initial API and implementation ############################################################################### -@jobService @env_docker_base +@job Feature: Trigger service tests diff --git a/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/BrokerSteps.java b/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/BrokerSteps.java index 011d74d5b99..c0e71b9b03b 100644 --- a/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/BrokerSteps.java +++ b/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/BrokerSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,6 +17,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import javax.inject.Inject; @@ -188,6 +189,10 @@ public void afterScenario() { @When("I start the Kura Mock") public void startKuraMock() { if (!kuraDevices.isEmpty()) { + // Cleanup of any leftover KuraMock, if any + for (KuraDevice kuraDevice : kuraDevices) { + kuraDevice.mqttClientDisconnect(); + } kuraDevices.clear(); } @@ -244,6 +249,33 @@ public void deviceBirthMessage() throws Exception { } } + /** + * Checks that the {@link Device} with the given {@link Device#getClientId()} has {@link DeviceConnection#getStatus()} {@link DeviceConnectionStatus#CONNECTED} within the given time. + * + * @param clientId The {@link Device#getClientId()} to check + * @param waitSeconds The max time of wait in seconds + * @throws Exception + * @since 1.2.0 + */ + @When("Device {string} is connected within {int}s") + public void deviceConnected(String clientId, int waitSeconds) throws Exception { + + long now = System.currentTimeMillis(); + while ((System.currentTimeMillis() - now) < (waitSeconds * 1000L)){ + Device kuraDevice = deviceRegistryService.findByClientId(getCurrentScopeId(), clientId); + + if (kuraDevice != null && + kuraDevice.getConnection() != null && + DeviceConnectionStatus.CONNECTED.equals(kuraDevice.getConnection().getStatus())) { + return; + } + + TimeUnit.MILLISECONDS.sleep(100); + } + + Assert.fail("Device " + clientId + "not connected within " + waitSeconds + "s"); + } + @When("Device(s) (is/are) connected within {int} second(s)") public void deviceConnected(int timeout) throws Exception { try { diff --git a/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/KuraDevice.java b/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/KuraDevice.java index 996705c79d4..9c30988b186 100644 --- a/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/KuraDevice.java +++ b/service/device/registry/test-steps/src/main/java/org/eclipse/kapua/service/device/registry/steps/KuraDevice.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -34,6 +34,7 @@ import java.nio.file.Paths; import java.util.Date; import java.util.List; +import java.util.concurrent.TimeUnit; public class KuraDevice implements MqttCallback { @@ -62,6 +63,7 @@ public class KuraDevice implements MqttCallback { private String deployGetBundles; private String deployExecStart34; private String deployExecStart95; + private String deployExecStop34; private String deployExecStop77; // INVENTORY-V1 @@ -175,6 +177,7 @@ public KuraDevice() { deployGetBundles = "$EDC/kapua-sys/rpione3/DEPLOY-V2/GET/bundles"; deployExecStart34 = "$EDC/kapua-sys/rpione3/DEPLOY-V2/EXEC/start/34"; deployExecStart95 = "$EDC/kapua-sys/rpione3/DEPLOY-V2/EXEC/start/95"; + deployExecStop34 = "$EDC/kapua-sys/rpione3/DEPLOY-V2/EXEC/stop/34"; deployExecStop77 = "$EDC/kapua-sys/rpione3/DEPLOY-V2/EXEC/stop/77"; // INVENTORY-V1 @@ -292,6 +295,7 @@ private void mqttClientSetupForMoreDevices() { cmdExecCommand = $EDC_KAPUA_SYS + clientId + "/CMD-V1/EXEC/command"; deployExecStart34 = $EDC_KAPUA_SYS + clientId + "/DEPLOY-V2/EXEC/start/34"; deployExecStart95 = $EDC_KAPUA_SYS + clientId + "/DEPLOY-V2/EXEC/start/95"; + deployExecStop34 = $EDC_KAPUA_SYS + clientId + "/DEPLOY-V2/EXEC/stop/34"; deployExecStop77 = $EDC_KAPUA_SYS + clientId + "/DEPLOY-V2/EXEC/stop/77"; assetExecRead = $EDC_KAPUA_SYS + clientId + "/ASSET-V1/EXEC/read"; @@ -405,6 +409,16 @@ public void messageArrived(String topic, MqttMessage mqttMessage) throws Excepti } // CMD-V1 else if (topic.equals(cmdExecCommand)) { + KuraPayload kuraRequestPayload = new KuraPayload(); + kuraRequestPayload.readFromByteArray(requestPayload); + + String command = (String) kuraRequestPayload.getMetrics().get("command.command"); + + if ("ping".equals(command)) { + // Mimic command request `ping -c 10 8.8.8.8 + TimeUnit.SECONDS.sleep(10); + } + callbackParam = extractCallback(requestPayload); responseTopic = $EDC + CLIENT_ACCOUNT + "/" + callbackParam.getClientId() + "/CMD-V1/REPLY/" + callbackParam.getRequestId(); @@ -530,7 +544,7 @@ else if (topic.equals(deployGetPackages)) { bundleStateChanged = true; mqttClient.publish(responseTopic, responsePayload, 0, false); - } else if (topic.equals(deployExecStop77)) { + } else if (topic.equals(deployExecStop34) || topic.equals(deployExecStop77)) { callbackParam = extractCallback(requestPayload); responseTopic = $EDC + CLIENT_ACCOUNT + "/" + callbackParam.getClientId() + DEPLOY_V2_REPLY + callbackParam.getRequestId(); diff --git a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobEngineSteps.java b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobEngineSteps.java index c01f3c2ac46..17d735bfce0 100644 --- a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobEngineSteps.java +++ b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobEngineSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -26,8 +26,10 @@ import org.eclipse.kapua.model.id.KapuaId; import org.eclipse.kapua.qa.common.StepData; import org.eclipse.kapua.service.job.Job; +import org.junit.Assert; import javax.inject.Inject; +import java.util.concurrent.TimeUnit; @Singleton public class JobEngineSteps extends JobServiceTestBase { @@ -66,6 +68,126 @@ public void startJob() throws Exception { } } + // Wait Job Running + + /** + * Waits the last {@link Job} in context to finish it execution up the given wait time + * + * @param waitSeconds The max time to wait + * @throws Exception + * @since 2.1.0 + */ + @And("I wait job to finish its execution up to {int}s") + public void waitJobInContextUpTo(int waitSeconds) throws Exception { + Job job = (Job) stepData.get(JOB); + + waitJobUpTo(job, waitSeconds); + } + + /** + * Looks for a {@link Job} by its {@link Job#getName()} and waits to finish it execution up the given wait time + * + * @param jobName The {@link Job#getName()} to look for + * @param waitSeconds The max time to wait + * @throws Exception + * @since 2.1.0 + */ + @And("I wait job {string} to finish its execution up to {int}s") + public void waitJobByNameUpTo(String jobName, int waitSeconds) throws Exception { + Job job = findJob(jobName); + + waitJobUpTo(job, waitSeconds); + } + + /** + * Wait the given {@link Job} to finish its execution up the given wait time + * + * @param job The {@link Job} to monitor + * @param waitSeconds The max time to wait + * @throws Exception + * @since 2.1.0 + */ + private void waitJobUpTo(Job job, int waitSeconds) throws Exception { + long now = System.currentTimeMillis(); + while ((System.currentTimeMillis() - now) < (waitSeconds * 1000L)) { + if (!jobEngineService.isRunning(job.getScopeId(), job.getId())) { + return; + } + + TimeUnit.MILLISECONDS.sleep(100); + } + + Assert.fail("Job " + job.getName() + "did not completed its execution within " + waitSeconds + "s"); + } + + // Check Job Running + + /** + * Checks that the last {@link Job} in context is running + * + * @throws Exception + * @since 2.1.0 + */ + @And("I confirm job is running") + public void checkJobInContextIsRunning() throws Exception { + Job job = (Job) stepData.get(JOB); + + checkJobIsRunning(job, true); + } + + /** + * Looks for a {@link Job} by its {@link Job#getName()} and checks that is running + * + * @param jobName The {@link Job#getName()} to look for + * @throws Exception + * @since 2.1.0 + */ + @And("I confirm job {string} is running") + public void checkJobByNameIsRunning(String jobName) throws Exception { + Job job = findJob(jobName); + + checkJobIsRunning(job, true); + } + + /** + * Checks that the last {@link Job} in context is not running + * + * @throws Exception + * @since 2.1.0 + */ + @And("I confirm job is not running") + public void checkJobInContextIsNotRunning() throws Exception { + Job job = (Job) stepData.get(JOB); + + checkJobIsRunning(job, false); + } + + /** + * Looks for a {@link Job} by its {@link Job#getName()} and checks that is not running + * + * @param jobName The {@link Job#getName()} to look for + * @throws Exception + * @since 2.1.0 + */ + @And("I confirm job {string} is not running") + public void checkJobByNameIsNotRunning(String jobName) throws Exception { + Job job = findJob(jobName); + + checkJobIsRunning(job, false); + } + + /** + * Checks the running status of the given {@link Job} + * + * @param job The {@link Job} to check + * @param expectedRunning Whether expecting running or not + * @throws Exception + * @since 2.1.0 + */ + private void checkJobIsRunning(Job job, boolean expectedRunning) throws Exception { + Assert.assertEquals(expectedRunning, jobEngineService.isRunning(job.getScopeId(), job.getId())); + } + @When("I restart a job") public void restartJob() throws Exception { primeException(); @@ -83,7 +205,7 @@ public void restartJob() throws Exception { @And("I stop the job") public void iStopTheJob() throws Exception { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); try { primeException(); jobEngineService.stopJob(getCurrentScopeId(), job.getId()); diff --git a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobExecutionServiceSteps.java b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobExecutionServiceSteps.java index 38536c18f22..acb57217905 100644 --- a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobExecutionServiceSteps.java +++ b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobExecutionServiceSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -144,6 +144,51 @@ public void deleteLastJobExecution() throws Exception { } } + // Check Job Execution + + /** + * Checks that the last {@link Job} in context has the given number of {@link JobExecution}s + * + * @param expectedNumberOfExecution Expected number of {@link JobExecution}s + * @throws Exception + * @since 2.1.0 + */ + @When("I confirm that job has {int} job execution") + public void checkJobInContextHasExecution(int expectedNumberOfExecution) throws Exception { + Job job = (Job) stepData.get(JOB); + + checkJobHasExecution(job, expectedNumberOfExecution); + } + + /** + * Looks for a {@link Job} by its {@link Job#getName()} and checks that has the given number of {@link JobExecution}s + * + * @param jobName The {@link Job#getName()} to look for + * @param expectedNumberOfExecution Expected number of {@link JobExecution}s + * @throws Exception + * @since 2.1.0 + */ + @When("I confirm that job {string} has {int} job execution") + public void checkJobByNameHasExecution(String jobName, int expectedNumberOfExecution) throws Exception { + Job job = findJob(jobName); + + checkJobHasExecution(job, expectedNumberOfExecution); + } + + /** + * Checks that the given {@link Job} has the given number of {@link JobExecution}s + * + * @param job The {@link Job} to check + * @param expectedNumberOfExecution Expected number of {@link JobExecution}s + * @throws Exception + * @since 2.1.0 + */ + private void checkJobHasExecution(Job job, int expectedNumberOfExecution) throws Exception { + long actualNumberOfExecution = jobExecutionService.countByJobId(job.getScopeId(), job.getId()); + + Assert.assertEquals(expectedNumberOfExecution, actualNumberOfExecution); + } + @When("I count the execution items for the current job") public void countExecutionsForJob() throws Exception { Job job = (Job) stepData.get("Job"); diff --git a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceSteps.java b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceSteps.java index 5d9720d836d..c46794eefcd 100644 --- a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceSteps.java +++ b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -120,10 +120,10 @@ public void createANamedJob(String name) throws Exception { JobCreator jobCreator = (JobCreator) stepData.get(JOB_CREATOR); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); stepData.remove(CURRENT_JOB_ID); Job job = jobService.create(jobCreator); - stepData.put("Job", job); + stepData.put(JOB, job); stepData.put(CURRENT_JOB_ID, job.getId()); } catch (KapuaException ex) { verifyException(ex); @@ -165,10 +165,10 @@ public void createJobFromCreator() throws Exception { JobCreator jobCreator = (JobCreator) stepData.get(JOB_CREATOR); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); stepData.remove(CURRENT_JOB_ID); Job job = jobService.create(jobCreator); - stepData.put("Job", job); + stepData.put(JOB, job); stepData.put(CURRENT_JOB_ID, job.getId()); } catch (KapuaException ex) { verifyException(ex); @@ -177,13 +177,13 @@ public void createJobFromCreator() throws Exception { @When("I change the job name to {string}") public void updateExistingJobName(String newName) throws Exception { - Job oldJob = (Job) stepData.get("Job"); + Job oldJob = (Job) stepData.get(JOB); oldJob.setName(newName); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job newJob = jobService.update(oldJob); - stepData.put("Job", newJob); + stepData.put(JOB, newJob); } catch (KapuaException ex) { verifyException(ex); } @@ -191,13 +191,13 @@ public void updateExistingJobName(String newName) throws Exception { @When("I change the job description to {string}") public void updateExistingJobDescription(String newDescription) throws Exception { - Job oldJob = (Job) stepData.get("Job"); + Job oldJob = (Job) stepData.get(JOB); oldJob.setDescription(newDescription); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job newJob = jobService.update(oldJob); - stepData.put("Job", newJob); + stepData.put(JOB, newJob); } catch (KapuaException ex) { verifyException(ex); } @@ -205,13 +205,13 @@ public void updateExistingJobDescription(String newDescription) throws Exception @When("I change the job XML definition to {string}") public void updateExistingJobXMLDefinition(String newDefinition) throws Exception { - Job oldJob = (Job) stepData.get("Job"); + Job oldJob = (Job) stepData.get(JOB); oldJob.setJobXmlDefinition(newDefinition); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job newJob = jobService.update(oldJob); - stepData.put("Job", newJob); + stepData.put(JOB, newJob); } catch (KapuaException ex) { verifyException(ex); } @@ -219,16 +219,16 @@ public void updateExistingJobXMLDefinition(String newDefinition) throws Exceptio @When("I add the current step to the last job") public void updateJobWithSteps() throws Exception { - Job oldJob = (Job) stepData.get("Job"); + Job oldJob = (Job) stepData.get(JOB); List tmpStepList = oldJob.getJobSteps(); JobStep step = (JobStep) stepData.get("Step"); tmpStepList.add(step); oldJob.setJobSteps(tmpStepList); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job newJob = jobService.update(oldJob); - stepData.put("Job", newJob); + stepData.put(JOB, newJob); } catch (KapuaException ex) { verifyException(ex); } @@ -236,7 +236,7 @@ public void updateJobWithSteps() throws Exception { @When("I delete the job") public void deleteJobFromDatabase() throws Exception { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); primeException(); try { jobService.delete(job.getScopeId(), job.getId()); @@ -250,9 +250,9 @@ public void findJobInDatabase() throws Exception { KapuaId currentJobId = (KapuaId) stepData.get(CURRENT_JOB_ID); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job job = jobService.find(getCurrentScopeId(), currentJobId); - stepData.put("Job", job); + stepData.put(JOB, job); } catch (KapuaException ex) { verifyException(ex); } @@ -281,9 +281,9 @@ public void queryForJobWithName(String name) throws Exception { tmpQuery.setPredicate(tmpQuery.attributePredicate(JobAttributes.NAME, name)); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job job = jobService.query(tmpQuery).getFirstItem(); - stepData.put("Job", job); + stepData.put(JOB, job); Assert.assertEquals(name, job.getName()); } catch (KapuaException ex) { verifyException(ex); @@ -292,7 +292,7 @@ public void queryForJobWithName(String name) throws Exception { @Then("The job entity matches the creator") public void checkJobAgainstCreator() { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); JobCreator jobCreator = (JobCreator) stepData.get(JOB_CREATOR); Assert.assertEquals("The job scope does not match the creator.", jobCreator.getScopeId(), job.getScopeId()); Assert.assertEquals("The job name does not match the creator.", jobCreator.getName(), job.getName()); @@ -301,35 +301,35 @@ public void checkJobAgainstCreator() { @Then("The job has int step(s)") public void checkNumberOfJobSteps(int num) { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertEquals("The job item has the wrong number of steps", num, job.getJobSteps().size()); } @Then("I find a job item in the database") public void checkThatAJobWasFound() { - Assert.assertNotNull("Unexpected null value for the job.", stepData.get("Job")); + Assert.assertNotNull("Unexpected null value for the job.", stepData.get(JOB)); } @Then("There is no such job item in the database") public void checkThatNoJobWasFound() { - Assert.assertNull("Unexpected job item was found!", stepData.get("Job")); + Assert.assertNull("Unexpected job item was found!", stepData.get(JOB)); } @Then("The job name is {string}") public void checkJobItemName(String name) { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertEquals("The job name does not match!", name, job.getName()); } @Then("The job description is {string}") public void checkJobItemDescription(String description) { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertEquals("The job description does not match!", description, job.getDescription()); } @Then("The job XML definition is {string}") public void checkJobItemXMLDefinition(String definition) { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertEquals("The job XML definition does not match!", definition, job.getJobXmlDefinition()); } @@ -344,13 +344,13 @@ public void testJobFactorySanity() { @Then("I find a job with name {string}") public void iFindAJobWithName(String jobName) { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertEquals(job.getName(), jobName); } @Then("I try to delete the job with name {string}") public void iDeleteTheJobWithName(String jobName) throws Exception { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); try { primeException(); if (job.getName().equals(jobName)) { @@ -363,12 +363,12 @@ public void iDeleteTheJobWithName(String jobName) throws Exception { @Then("I try to edit job to name {string}") public void iTryToEditJobToName(String jobName) throws Throwable { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); job.setName(jobName); try { primeException(); Job newJob = jobService.update(job); - stepData.put("Job", newJob); + stepData.put(JOB, newJob); } catch (KapuaException ex) { verifyException(ex); } @@ -381,9 +381,9 @@ public void iQueryForTheJobWithTheNameAndIFoundIt(String jobName) throws Excepti tmpQuery.setPredicate(tmpQuery.attributePredicate(JobAttributes.NAME, jobName)); primeException(); try { - stepData.remove("Job"); + stepData.remove(JOB); Job job = jobService.query(tmpQuery).getFirstItem(); - stepData.put("Job", job); + stepData.put(JOB, job); Assert.assertEquals(jobName, job.getName()); } catch (KapuaException ex) { verifyException(ex); @@ -419,7 +419,7 @@ public void iTryToCreateJobWithInvalidSymbolsInName(String invalidCharacters) th @Then("I find a job with description {string}") public void iFindAJobWithDescription(String jobDescription) throws Throwable { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertEquals(job.getDescription(), jobDescription); } @@ -442,7 +442,7 @@ public void iChangeNameOfJobFromTo(String oldName, String newName) throws Throwa Job job = queryResult.getFirstItem(); job.setName(newName); jobService.update(job); - stepData.put("Job", job); + stepData.put(JOB, job); } catch (Exception e) { verifyException(e); } @@ -450,7 +450,7 @@ public void iChangeNameOfJobFromTo(String oldName, String newName) throws Throwa @And("There is no job with name {string} in database") public void thereIsNoJobWithNameInDatabase(String jobName) { - Job job = (Job) stepData.get("Job"); + Job job = (Job) stepData.get(JOB); Assert.assertNotEquals(job.getName(), jobName); } @@ -463,7 +463,7 @@ public void iChangeTheJobDescriptionFromTo(String oldDescription, String newDesc Job job = queryResult.getFirstItem(); job.setDescription(newDescription); jobService.update(job); - stepData.put("Job", job); + stepData.put(JOB, job); } catch (Exception e) { verifyException(e); } @@ -478,7 +478,7 @@ private void tryToCreateJob(String characters) throws Exception { try { primeException(); Job job = jobService.create(jobCreator); - stepData.put("Job", job); + stepData.put(JOB, job); stepData.put(CURRENT_JOB_ID, job.getId()); } catch (KapuaException ex) { verifyException(ex); @@ -494,12 +494,12 @@ private void tryToUpdateJobName(String characters) throws Exception { jobCreator.setName(JOB_NAME + i); try { primeException(); - stepData.remove("Job"); + stepData.remove(JOB); Job job = jobService.create(jobCreator); job.setName(jobName); jobService.update(job); stepData.put(CURRENT_JOB_ID, job.getId()); - stepData.put("Job", job); + stepData.put(JOB, job); } catch (KapuaException ex) { verifyException(ex); } diff --git a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceTestBase.java b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceTestBase.java index 94b9e20fde9..c6c75a0cce8 100644 --- a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceTestBase.java +++ b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobServiceTestBase.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -12,8 +12,15 @@ *******************************************************************************/ package org.eclipse.kapua.service.job.steps; +import org.eclipse.kapua.KapuaEntityNotFoundException; +import org.eclipse.kapua.locator.KapuaLocator; import org.eclipse.kapua.qa.common.StepData; import org.eclipse.kapua.qa.common.TestBase; +import org.eclipse.kapua.service.job.Job; +import org.eclipse.kapua.service.job.JobAttributes; +import org.eclipse.kapua.service.job.JobFactory; +import org.eclipse.kapua.service.job.JobQuery; +import org.eclipse.kapua.service.job.JobService; public class JobServiceTestBase extends TestBase { @@ -21,6 +28,7 @@ public class JobServiceTestBase extends TestBase { protected static final String JOB_NAME = "jobName"; protected static final String TEST_JOB = "Test job"; protected static final String CURRENT_JOB_ID = "CurrentJobId"; + protected static final String JOB = "Job"; protected static final String JOB_CREATOR = "JobCreator"; // Job Execution @@ -45,7 +53,31 @@ public class JobServiceTestBase extends TestBase { protected static final String JOB_TARGET = "JobTarget"; protected static final String JOB_TARGET_LIST = "JobTargetList"; + private JobService jobService; + + private JobFactory jobFactory; + protected JobServiceTestBase(StepData stepData) { super(stepData); + + KapuaLocator locator = KapuaLocator.getInstance(); + + jobService = locator.getService(JobService.class); + jobFactory = locator.getFactory(JobFactory.class); + } + + public Job findJob(String jobName) throws Exception { + JobQuery jobQuery = jobFactory.newQuery(getCurrentScopeId()); + jobQuery.setPredicate( + jobQuery.attributePredicate(JobAttributes.NAME, jobName) + ); + + Job job = jobService.query(jobQuery).getFirstItem(); + + if (job == null) { + throw new KapuaEntityNotFoundException(Job.TYPE, jobName); + } + + return job; } } diff --git a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobStepServiceSteps.java b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobStepServiceSteps.java index 58085120722..b2f2f218968 100644 --- a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobStepServiceSteps.java +++ b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobStepServiceSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -26,6 +26,7 @@ import org.eclipse.kapua.model.query.predicate.AttributePredicate; import org.eclipse.kapua.qa.common.StepData; import org.eclipse.kapua.qa.common.cucumber.CucJobStepProperty; +import org.eclipse.kapua.service.job.Job; import org.eclipse.kapua.service.job.step.JobStep; import org.eclipse.kapua.service.job.step.JobStepAttributes; import org.eclipse.kapua.service.job.step.JobStepCreator; @@ -44,6 +45,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; @Singleton public class JobStepServiceSteps extends JobServiceTestBase { @@ -101,6 +103,39 @@ public void iPrepareAJobStepCreatorWithPropertyList(String name, List cucJobStepProperties) throws Exception{ + Job job = (Job) stepData.get(JOB); + JobStepDefinition jobStepDefinition = (JobStepDefinition) stepData.get(JOB_STEP_DEFINITION); + + JobStepCreator jobStepCreator = jobStepFactory.newCreator(job.getScopeId()); + jobStepCreator.setJobId(job.getId()); + jobStepCreator.setName(jobStepName); + jobStepCreator.setJobStepDefinitionId(jobStepDefinition.getId()); + jobStepCreator.setStepProperties( + cucJobStepProperties.stream() + .map( + (cucJobStepProperty) -> jobStepFactory.newStepProperty( + cucJobStepProperty.getName(), + cucJobStepProperty.getType(), + cucJobStepProperty.getValue() + ) + ) + .collect(Collectors.toList()) + ); + + JobStep jobStep = jobStepService.create(jobStepCreator); + stepData.put(JOB_STEP, jobStep); + } + @And("I prepare a JobStepCreator with the name {string} and properties") // TODO Review implementation. These should be tested specifically for each JobStepDefinition public void iPrepareAJobStepCreatorWithPropertyList1(String name, List tmpProperty) { diff --git a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobTargetServiceSteps.java b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobTargetServiceSteps.java index 228de86d467..ea7e630c583 100644 --- a/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobTargetServiceSteps.java +++ b/service/job/test-steps/src/main/java/org/eclipse/kapua/service/job/steps/JobTargetServiceSteps.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others + * Copyright (c) 2021, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -20,12 +20,19 @@ import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import org.eclipse.kapua.KapuaEntityNotFoundException; import org.eclipse.kapua.KapuaException; import org.eclipse.kapua.locator.KapuaLocator; +import org.eclipse.kapua.model.KapuaEntity; import org.eclipse.kapua.model.id.KapuaId; import org.eclipse.kapua.model.query.predicate.AttributePredicate; import org.eclipse.kapua.qa.common.StepData; import org.eclipse.kapua.service.device.registry.Device; +import org.eclipse.kapua.service.device.registry.DeviceAttributes; +import org.eclipse.kapua.service.device.registry.DeviceFactory; +import org.eclipse.kapua.service.device.registry.DeviceListResult; +import org.eclipse.kapua.service.device.registry.DeviceQuery; +import org.eclipse.kapua.service.device.registry.DeviceRegistryService; import org.eclipse.kapua.service.job.Job; import org.eclipse.kapua.service.job.targets.JobTarget; import org.eclipse.kapua.service.job.targets.JobTargetAttributes; @@ -41,12 +48,17 @@ import javax.inject.Inject; import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; @Singleton public class JobTargetServiceSteps extends JobServiceTestBase { private static final String DEVICE = "Device"; + private DeviceFactory deviceFactory; + private DeviceRegistryService deviceRegistryService; + private JobTargetService jobTargetService; private JobTargetFactory jobTargetFactory; final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -65,6 +77,9 @@ public void beforeScenarioNone(Scenario scenario) { public void setServices() { KapuaLocator locator = KapuaLocator.getInstance(); + deviceFactory= locator.getFactory(DeviceFactory.class); + deviceRegistryService = locator.getService(DeviceRegistryService.class); + jobTargetService = locator.getService(JobTargetService.class); jobTargetFactory = locator.getFactory(JobTargetFactory.class); } @@ -126,6 +141,40 @@ public void iSearchForTheJobTargetsInDatabase() { stepData.updateCount(jobTargets.size()); } + /** + * Adds {@link Device}s with the given {@link Device#getClientId()}s as a {@link JobTarget} of the {@link Job} in context. + * + * @param clientIds The {@link Device#getClientId()}s to add + * @throws Exception + * @since 2.1.0 + */ + @And("I add device target(s) to job") + public void addDeviceTargetsToJob(List clientIds) throws Exception { + DeviceQuery deviceQuery = deviceFactory.newQuery(getCurrentScopeId()); + deviceQuery.setPredicate( + deviceQuery.attributePredicate(DeviceAttributes.CLIENT_ID, clientIds) + ); + + DeviceListResult devices = deviceRegistryService.query(deviceQuery); + + List deviceIds = devices.getItems() + .stream() + .map(KapuaEntity::getId) + .collect(Collectors.toList()); + + Job job = (Job) stepData.get("Job"); + + JobTargetCreator jobTargetCreator = jobTargetFactory.newCreator(getCurrentScopeId()); + jobTargetCreator.setJobId(job.getId()); + + List jobTargets = new ArrayList<>(); + for (KapuaId deviceId : deviceIds) { + jobTargetCreator.setJobTargetId(deviceId); + JobTarget jobTarget = jobTargetService.create(jobTargetCreator); + stepData.put(JOB_TARGET, jobTarget); + } + stepData.put(JOB_TARGET_LIST, jobTargets); + } @And("I add target(s) to job") public void addTargetsToJob() throws Exception { @@ -327,7 +376,81 @@ public void testTheJobTargetFactory() { Assert.assertNotNull(jobTargetFactory.newQuery(SYS_SCOPE_ID)); } + + // Check Job Targets + + /** + * Checks that the {@link JobTarget} in context for the {@link Job} in context has the expected {@link JobTarget#getStepIndex()} and {@link JobTarget#getStatus()} + * + * @param expectedStepIndex The expected {@link JobTarget#getStepIndex()} + * @param expectedJobTargetStatus The expected {@link JobTarget#getStatus()} + * @throws Exception + * @since 2.1.0 + */ + @When("I confirm that job target in job has step index {int} and status {string}") + public void checkJobTargetForJobInContextHas(int expectedStepIndex, String expectedJobTargetStatus) throws Exception { + + JobTarget jobTarget = (JobTarget) stepData.get(JOB_TARGET); + + checkJobTargetForJobHas(jobTarget, expectedStepIndex, expectedJobTargetStatus); + } + + /** + * Checks that the {@link JobTarget} that matches the {@link Device} with the given {@link Device#getClientId()} for the {@link Job} in context has the expected {@link JobTarget#getStepIndex()} and {@link JobTarget#getStatus()} + * + * @param clientId The {@link Device#getClientId()} to look for + * @param expectedStepIndex The expected {@link JobTarget#getStepIndex()} + * @param expectedJobTargetStatus The expected {@link JobTarget#getStatus()} + * @throws Exception + * @since 2.1.0 + */ + @And("I confirm that device job target {string} in job has step index {int} and status {string}") + public void checkJobTargetByNameForJobHas(String clientId, int expectedStepIndex, String expectedJobTargetStatus) throws Exception { + Device device = deviceRegistryService.findByClientId(getCurrentScopeId(), clientId); + + if (device == null) { + throw new KapuaEntityNotFoundException(Device.TYPE, clientId); + } + + Job job = (Job) stepData.get(JOB); + + JobTargetQuery jobTargetQuery = jobTargetFactory.newQuery(job.getScopeId()); + jobTargetQuery.setPredicate( + jobTargetQuery.andPredicate( + jobTargetQuery.attributePredicate(JobTargetAttributes.JOB_ID, job.getId()), + jobTargetQuery.attributePredicate(JobTargetAttributes.JOB_TARGET_ID, device.getId()) + ) + ); + + JobTarget jobTarget = jobTargetService.query(jobTargetQuery).getFirstItem(); + + if (jobTarget == null) { + throw new KapuaEntityNotFoundException(JobTarget.TYPE, device.getId()); + } + + checkJobTargetForJobHas(jobTarget, expectedStepIndex, expectedJobTargetStatus); + } + + /** + * Checks that given {@link JobTarget} has the expected {@link JobTarget#getStepIndex()} and {@link JobTarget#getStatus()} + * + * @param expectedStepIndex The expected {@link JobTarget#getStepIndex()} + * @param expectedJobTargetStatus The expected {@link JobTarget#getStatus()} + * @throws Exception + * @since 2.1.0 + */ + private void checkJobTargetForJobHas(JobTarget jobTarget, int expectedStepIndex, String expectedJobTargetStatus) throws Exception { + JobTarget updatedJobTarget = jobTargetService.find(jobTarget.getScopeId(), jobTarget.getId()); + + Assert.assertEquals(expectedStepIndex, updatedJobTarget.getStepIndex()); + Assert.assertEquals(JobTargetStatus.valueOf(expectedJobTargetStatus), updatedJobTarget.getStatus()); + + stepData.put(JOB_TARGET, updatedJobTarget); + } + + // // Private methods + // private JobTargetCreator prepareJobTargetCreator() { KapuaId currentJobId = (KapuaId) stepData.get(CURRENT_JOB_ID); Device device = (Device) stepData.get(DEVICE); From cd00157c6004535f4646f622bc49c3d347d7dee8 Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Wed, 22 Jan 2025 17:18:55 +0100 Subject: [PATCH 5/5] :bug: [Test] Fixed backport issues and incompatibilities Signed-off-by: Alberto Codutti --- .../engine/app/web/jaxb/JobEngineJAXBContextProvider.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/job-engine/app/web/src/main/java/org/eclipse/kapua/job/engine/app/web/jaxb/JobEngineJAXBContextProvider.java b/job-engine/app/web/src/main/java/org/eclipse/kapua/job/engine/app/web/jaxb/JobEngineJAXBContextProvider.java index 882e0f07ff3..0cda2848c23 100644 --- a/job-engine/app/web/src/main/java/org/eclipse/kapua/job/engine/app/web/jaxb/JobEngineJAXBContextProvider.java +++ b/job-engine/app/web/src/main/java/org/eclipse/kapua/job/engine/app/web/jaxb/JobEngineJAXBContextProvider.java @@ -13,6 +13,7 @@ package org.eclipse.kapua.job.engine.app.web.jaxb; import org.eclipse.kapua.KapuaException; +import org.eclipse.kapua.commons.rest.model.IsJobRunningResponse; import org.eclipse.kapua.commons.rest.model.errors.CleanJobDataExceptionInfo; import org.eclipse.kapua.commons.rest.model.errors.EntityNotFoundExceptionInfo; import org.eclipse.kapua.commons.rest.model.errors.ExceptionInfo; @@ -33,6 +34,7 @@ import org.eclipse.kapua.commons.rest.model.errors.ThrowableInfo; import org.eclipse.kapua.commons.util.xml.JAXBContextProvider; import org.eclipse.kapua.job.engine.JobStartOptions; +import org.eclipse.kapua.job.engine.client.JobStartOptionsClient; import org.eclipse.kapua.job.engine.commons.model.JobStepPropertiesOverrides; import org.eclipse.kapua.job.engine.commons.model.JobTargetSublist; import org.eclipse.kapua.service.authentication.AuthenticationXmlRegistry; @@ -107,21 +109,23 @@ public JAXBContext getJAXBContext() throws KapuaException { IllegalNullArgumentExceptionInfo.class, // Job Engine + JobStartOptionsClient.class, JobStartOptions.class, JobTargetSublist.class, + IsJobRunningResponse.class, JobStepPropertiesOverrides.class, - // Jobs Exception Info + // Job Engine Client CleanJobDataExceptionInfo.class, JobAlreadyRunningExceptionInfo.class, JobEngineExceptionInfo.class, - JobScopedEngineExceptionInfo.class, JobInvalidTargetExceptionInfo.class, JobMissingStepExceptionInfo.class, JobMissingTargetExceptionInfo.class, JobNotRunningExceptionInfo.class, JobResumingExceptionInfo.class, JobRunningExceptionInfo.class, + JobScopedEngineExceptionInfo.class, JobStartingExceptionInfo.class, JobStoppingExceptionInfo.class,