From d8e99b426a162ce3a9f5d7b6346cf9ddb6bea80c Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:05:47 +0100 Subject: [PATCH 1/4] :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 e17f3c0fb84..f16ab7d7948 100755 --- a/.github/workflows/kapua-ci.yaml +++ b/.github/workflows/kapua-ci.yaml @@ -162,7 +162,7 @@ jobs: with: tag: '@jobs or @scheduler' needs-docker-images: 'false' - test-jobsIntegrationBase: + test-jobService: needs: build runs-on: ubuntu-latest timeout-minutes: 45 @@ -171,7 +171,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 d4620d791b9..50b7943b995 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 da603e9e072..4612072a8d9 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 78b67856d27..c69be228d01 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 42b49e9ff4f..c20d95c9557 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 3d84b48af505496b422c59b957e22400e9147961 Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:09:33 +0100 Subject: [PATCH 2/4] :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 deea0527ae4..906811b04f4 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 dfa1a121ad1..5411ba81220 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 8a754d3eacf..10811025732 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 2f1e9e59f13..d58f55b01b6 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 3be6ff7b970..d7e0e63e52a 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 89c58b3ab4d..2f9f9d1534b 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 6a68c9ab737..e1d73fd0093 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 1e0ee047ed1d63f3421e57caff6e0b57068e1e84 Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:10:53 +0100 Subject: [PATCH 3/4] :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 906811b04f4..97b7214a1a4 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 5411ba81220..c327bcbabc9 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 10811025732..d51daa26f93 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 d58f55b01b6..ef024337c78 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 d7e0e63e52a..16923f87555 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 2f9f9d1534b..5d7c5e436f1 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 e1d73fd0093..696a3b133c4 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 821c561ef6b9e0e77aac710683c7efb10d4f9e7f Mon Sep 17 00:00:00 2001 From: Alberto Codutti Date: Mon, 16 Dec 2024 17:49:24 +0100 Subject: [PATCH 4/4] :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 | 7 +- .../features/job/JobServiceI9n.feature | 7 +- .../features/job/JobTargetsServiceI9n.feature | 7 +- ...eServiceKeystoreStepDefinitionsI9n.feature | 5 +- .../JobEngineServiceOperations.feature | 262 ++++++++++++++++++ ...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, 959 insertions(+), 172 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 f16ab7d7948..7fb3b56c726 100755 --- a/.github/workflows/kapua-ci.yaml +++ b/.github/workflows/kapua-ci.yaml @@ -171,7 +171,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 daada3dbb2e..ae6079dfebf 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 50b7943b995..fb9c22b6d07 100644 --- a/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.feature +++ b/qa/integration/src/test/resources/features/job/JobExecutionServiceI9n.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 @jobExecutionService Feature: Job Execution service CRUD tests @@ -155,7 +156,7 @@ Feature: Job Execution service CRUD tests And I test the sanity of the job execution 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/job/JobServiceI9n.feature b/qa/integration/src/test/resources/features/job/JobServiceI9n.feature index 4612072a8d9..f36a777accd 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 @@ -255,7 +256,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 c69be228d01..6ed256a1feb 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 @@ -156,7 +157,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 97b7214a1a4..f276d267cba 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 @@ -150,6 +151,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..a896428cadf --- /dev/null +++ b/qa/integration/src/test/resources/features/jobEngine/JobEngineServiceOperations.feature @@ -0,0 +1,262 @@ +############################################################################### +# 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 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 c327bcbabc9..91343912621 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 @@ -1019,6 +1020,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 d51daa26f93..4c238143fb0 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 @@ -502,6 +503,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 ef024337c78..bd517a6c55a 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 @@ -429,6 +430,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 16923f87555..228678f872d 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 @@ -1133,6 +1134,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 5d7c5e436f1..fc70d79fc55 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 @@ -862,6 +863,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 696a3b133c4..a142ee947dc 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 @@ -513,6 +514,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 7b848b659b3..6b47d31f3ea 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 c20d95c9557..826e80e5099 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);