diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy new file mode 100644 index 0000000000..330c000d74 --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/ComplexFlowValidationResponse.groovy @@ -0,0 +1,51 @@ +package org.openkilda.functionaltests.helpers.model + +import org.openkilda.northbound.dto.v1.flows.FlowValidationDto +import org.openkilda.northbound.dto.v1.flows.PathDiscrepancyDto +import org.openkilda.northbound.dto.v2.haflows.HaFlowValidationResult +import org.openkilda.northbound.dto.v2.yflows.YFlowValidationResult + +import groovy.transform.ToString + +@ToString +class ComplexFlowValidationResponse { + private static final String COOKIE_ID_IN_RULE_DISCREPANCY_STRING_REGEX = /-?\d{19}/ + + boolean asExpected + List subFlowsDiscrepancies + + ComplexFlowValidationResponse(YFlowValidationResult yFlowValidation) { + this.asExpected = yFlowValidation.asExpected + this.subFlowsDiscrepancies = collectDiscrepanciesPerSubFlow(yFlowValidation.subFlowValidationResults) + } + + ComplexFlowValidationResponse(HaFlowValidationResult haFlowValidation) { + this.asExpected = haFlowValidation.asExpected + this.subFlowsDiscrepancies = collectDiscrepanciesPerSubFlow(haFlowValidation.subFlowValidationResults) + + } + + private static List collectDiscrepanciesPerSubFlow(List subFlowValidationDetails) { + List discrepanciesPerSubFlow = subFlowValidationDetails.groupBy { it.flowId }.collect { + assert (it.value.direction*.toUpperCase() as Set).size() == it.value.size(), "There is an error in the validation logic $it" + HashMap> discrepancy = [:] + it.value.each { + verifyValidateLogic(it) + it.asExpected ?: discrepancy.put(FlowDirection.getByDirection(it.direction.toLowerCase()), it.discrepancies) + } + discrepancy.isEmpty() ? null : new SubFlowValidationDiscrepancies(subFlowId: it.key, flowDiscrepancies: discrepancy) + + }.findAll() + discrepanciesPerSubFlow + } + + private static void verifyValidateLogic(FlowValidationDto validationDto) { + assert (validationDto.asExpected && validationDto.discrepancies.isEmpty()) || (!validationDto.asExpected && !validationDto.discrepancies.isEmpty()), + "There is an error in the validation logic $validationDto" + } + + Set retrieveAllRulesCookieFromDiscrepancy() { + def rules = subFlowsDiscrepancies.flowDiscrepancies*.values().flatten() + rules.collect { new Long((it =~ COOKIE_ID_IN_RULE_DISCREPANCY_STRING_REGEX)[0]) } + } +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy index b0a8aa120f..c34216929b 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/FlowDirection.groovy @@ -22,6 +22,6 @@ enum FlowDirection { return flowDirection } } - throw new IllegalArgumentException("Invalid value for encapsulation type") + throw new IllegalArgumentException("Invalid value for direction") } } diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy index 3d2fe4a117..909b235d6a 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/HaFlowExtended.groovy @@ -287,6 +287,11 @@ class HaFlowExtended { northboundV2.validateHaFlow(haFlowId) } + ComplexFlowValidationResponse validateAndCollectDiscrepancy() { + def validationResponse = validate() + new ComplexFlowValidationResponse(validationResponse) + } + HaFlowSyncResult sync() { log.debug("Sync ha-flow '${haFlowId}'") northboundV2.syncHaFlow(haFlowId) diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy new file mode 100644 index 0000000000..d0161a4d2b --- /dev/null +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/SubFlowValidationDiscrepancies.groovy @@ -0,0 +1,13 @@ +package org.openkilda.functionaltests.helpers.model + +import org.openkilda.northbound.dto.v1.flows.PathDiscrepancyDto + +import groovy.transform.ToString +import groovy.transform.TupleConstructor + +@TupleConstructor +@ToString +class SubFlowValidationDiscrepancies { + String subFlowId + Map> flowDiscrepancies +} diff --git a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy index 8ac9f97e00..9a3c390563 100644 --- a/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy +++ b/src-java/testing/functional-tests/src/main/groovy/org/openkilda/functionaltests/helpers/model/YFlowExtended.groovy @@ -262,6 +262,11 @@ class YFlowExtended { northboundV2.validateYFlow(yFlowId) } + ComplexFlowValidationResponse validateAndCollectDiscrepancy() { + def validationResponse = validate() + new ComplexFlowValidationResponse(validationResponse) + } + YFlowSyncResult sync() { log.debug("Synchronize Y-Flow '${yFlowId}'") northboundV2.synchronizeYFlow(yFlowId) diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy index 57fb1de9ff..8a32903712 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowDiversitySpec.groovy @@ -72,9 +72,8 @@ class HaFlowDiversitySpec extends HealthCheckSpecification { and: "HA-Flow passes flow validation" withPool { [haFlow1, haFlow2, haFlow3].eachParallel { HaFlowExtended haFlow -> - def validationResponse = haFlow.validate() - assert validationResponse.asExpected - assert validationResponse.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty() } + def validationResponse = haFlow.validateAndCollectDiscrepancy() + assert validationResponse.asExpected && validationResponse.subFlowsDiscrepancies.isEmpty() } } } @@ -127,9 +126,8 @@ class HaFlowDiversitySpec extends HealthCheckSpecification { and: "HA-Flow passes flow validation" withPool { [haFlow1, haFlow2].eachParallel { HaFlowExtended haFlow -> - def validationResponse = haFlow.validate() - assert validationResponse.asExpected - assert validationResponse.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty()} + def validationResponse = haFlow.validateAndCollectDiscrepancy() + assert validationResponse.asExpected && validationResponse.subFlowsDiscrepancies.isEmpty() } } } @@ -181,9 +179,8 @@ class HaFlowDiversitySpec extends HealthCheckSpecification { and: "HA-Flow passes flow validation" withPool { [haFlow1, haFlow2].eachParallel { HaFlowExtended haFlow -> - def validationResponse = haFlow.validate() - assert validationResponse.asExpected - assert validationResponse.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty()} + def validationResponse = haFlow.validateAndCollectDiscrepancy() + assert validationResponse.asExpected && validationResponse.subFlowsDiscrepancies.isEmpty() } } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy index c3b48ec87f..d07aa773c6 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/haflows/HaFlowValidationSpec.groovy @@ -2,7 +2,6 @@ package org.openkilda.functionaltests.spec.flows.haflows import static org.openkilda.functionaltests.extension.tags.Tag.HA_FLOW import static org.openkilda.functionaltests.extension.tags.Tag.SMOKE -import static org.openkilda.functionaltests.helpers.model.SwitchRules.missingRuleCookieIds import static org.openkilda.testing.Constants.RULES_DELETION_TIME import org.openkilda.functionaltests.HealthCheckSpecification @@ -39,11 +38,11 @@ class HaFlowValidationSpec extends HealthCheckSpecification { def haFlow = haFlowFactory.getRandom(swT) when: "Validate HA-Flow" - def validationResult = haFlow.validate() + def validationResult = haFlow.validateAndCollectDiscrepancy() then: "HA-Flow is validated successfully" validationResult.asExpected - validationResult.getSubFlowValidationResults().every { it.getDiscrepancies().isEmpty() } + validationResult.subFlowsDiscrepancies.isEmpty() } def "HA-Flow validation should fail in case of missing rule on #switchRole switch"() { @@ -59,11 +58,11 @@ class HaFlowValidationSpec extends HealthCheckSpecification { then: "HA-Flow validation returns deleted rule in 'Discrepancies' section" Wrappers.wait(RULES_DELETION_TIME) { - def validationResponse = haFlow.validate() - assert !validationResponse.asExpected - def missingRules = validationResponse.getSubFlowValidationResults().collect { it.getDiscrepancies() }.flatten() + def discrepancies = haFlow.validateAndCollectDiscrepancy() + assert !discrepancies.asExpected + def missingRules = discrepancies.retrieveAllRulesCookieFromDiscrepancy() assert missingRules.size() == 1, "We deleted only one rule" - assert missingRules.get(0).getRule().contains(haFlowRuleToDelete.getCookie().toString()) + assert missingRules.first() == haFlowRuleToDelete.getCookie() } where: @@ -91,11 +90,10 @@ class HaFlowValidationSpec extends HealthCheckSpecification { then: "HA-Flow validation returns rules related to deleted meter in 'Discrepancies' section" Wrappers.wait(RULES_DELETION_TIME) { - def validationResponse = haFlow.validate() - assert !validationResponse.asExpected - def missingMeters = validationResponse.getSubFlowValidationResults().collect { it.getDiscrepancies() }.flatten() - assert missingMeters.size() == expectedDeletedSwitchRules.size() - assert missingRuleCookieIds(missingMeters) == expectedDeletedSwitchRules.collect { it.getCookie() } as Set + def discrepancies = haFlow.validateAndCollectDiscrepancy() + assert !discrepancies.asExpected + def missingMeters = discrepancies.retrieveAllRulesCookieFromDiscrepancy() + assert missingMeters == expectedDeletedSwitchRules.collect { it.getCookie() } as Set } where: diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy index 45dcba9ae8..eb5a358732 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowCreateSpec.groovy @@ -73,9 +73,9 @@ class YFlowCreateSpec extends HealthCheckSpecification { def paths = yFlow.retrieveAllEntityPaths() and: "Y-Flow passes flow validation" - with(yFlow.validate()) { + with(yFlow.validateAndCollectDiscrepancy()) { it.asExpected - it.subFlowValidationResults.each { assert it.asExpected } + it.subFlowsDiscrepancies.isEmpty() } and: "Both sub-flows pass flow validation" diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy index 97cb481990..05232e81a8 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/flows/yflows/YFlowValidationSpec.groovy @@ -6,6 +6,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.error.yflow.YFlowNotFoundExpectedError import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.YFlowFactory import org.openkilda.functionaltests.model.stats.Direction import org.openkilda.messaging.payload.flow.FlowState @@ -94,25 +95,17 @@ class YFlowValidationSpec extends HealthCheckSpecification { switchHelper.deleteSwitchRules(swIdToManipulate, cookieToDelete) then: "Y-Flow is not valid" - def validateYFlowInfo = yFlow.validate() - !validateYFlowInfo.asExpected + def discrepancies = yFlow.validateAndCollectDiscrepancy() + !discrepancies.asExpected and: "Discrepancies has been detected for broken sub-flow REVERSE direction" - def reverseBrokenSubFlow = validateYFlowInfo.subFlowValidationResults - .find { it.flowId == subFl_1.flowId && it.direction == Direction.REVERSE.name() } - assert !reverseBrokenSubFlow.asExpected && reverseBrokenSubFlow.discrepancies + assert discrepancies.subFlowsDiscrepancies.find { it.subFlowId == subFl_1.flowId }.flowDiscrepancies.get(FlowDirection.REVERSE) and: "No discrepancies has been detected for broken sub-flow FORWARD direction" - def forwardBrokenSubFlow = validateYFlowInfo.subFlowValidationResults - .find { it.flowId == subFl_1.flowId && it.direction == Direction.FORWARD.name() } - assert forwardBrokenSubFlow.asExpected && forwardBrokenSubFlow.discrepancies.empty - + assert !discrepancies.subFlowsDiscrepancies.find { it.subFlowId == subFl_1.flowId }.flowDiscrepancies.get(FlowDirection.FORWARD) and: "No discrepancies has been detected for another sub-flow" - validateYFlowInfo.subFlowValidationResults - .findAll { it.flowId != subFl_1.flowId }.each { - assert it.asExpected && it.discrepancies.empty - } + assert !discrepancies.subFlowsDiscrepancies.find { it.subFlowId != subFl_1.flowId } and: "Simple flow validation detects discrepancies for the subFlow_1 REVERSE direction only" verifyAll(northbound.validateFlow(subFl_1.flowId)) { subFlow1 -> @@ -138,7 +131,8 @@ class YFlowValidationSpec extends HealthCheckSpecification { yFlow.waitForBeingInState(FlowState.UP) then: "Y-Flow/subFlow passes flow validation" - yFlow.validate().asExpected + def discrepanciesAfterSync = yFlow.validateAndCollectDiscrepancy() + discrepanciesAfterSync.asExpected && discrepanciesAfterSync.subFlowsDiscrepancies.isEmpty() yFlow.subFlows.each { northbound.validateFlow(it.flowId).each { direction -> assert direction.asExpected } } diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy index b094a0b4a7..82cb7623d0 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42HaFlowRttSpec.groovy @@ -17,6 +17,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.HaFlowFactory import org.openkilda.functionaltests.helpers.Wrappers +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.HaFlowExtended import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.SwitchTriplet @@ -135,11 +136,10 @@ class Server42HaFlowRttSpec extends HealthCheckSpecification { } and: "Ha-Flow is valid and UP" - haFlow.validate().subFlowValidationResults.each { validationInfo -> - if (validationInfo.direction == "forward") { - assert !validationInfo.asExpected - } else { - assert validationInfo.asExpected + verifyAll(haFlow.validateAndCollectDiscrepancy()) { validationResult -> + assert !validationResult.asExpected + validationResult.subFlowsDiscrepancies.each { + assert it.flowDiscrepancies.get(FlowDirection.FORWARD) && !it.flowDiscrepancies.get(FlowDirection.REVERSE) } } haFlow.retrieveDetails().status == FlowState.UP diff --git a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy index b05dee6d74..c9392b2f1e 100644 --- a/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy +++ b/src-java/testing/functional-tests/src/test/groovy/org/openkilda/functionaltests/spec/server42/Server42YFlowRttSpec.groovy @@ -24,6 +24,7 @@ import org.openkilda.functionaltests.HealthCheckSpecification import org.openkilda.functionaltests.extension.tags.Tags import org.openkilda.functionaltests.helpers.Wrappers import org.openkilda.functionaltests.helpers.builder.YFlowBuilder +import org.openkilda.functionaltests.helpers.model.FlowDirection import org.openkilda.functionaltests.helpers.model.FlowWithSubFlowsEntityPath import org.openkilda.functionaltests.helpers.model.SwitchRulesFactory import org.openkilda.functionaltests.helpers.model.SwitchTriplet @@ -412,13 +413,10 @@ class Server42YFlowRttSpec extends HealthCheckSpecification { } and: "Y-Flow is valid and UP" - verifyAll(yFlow.validate()) { validationResult -> + verifyAll(yFlow.validateAndCollectDiscrepancy()) { validationResult -> assert !validationResult.asExpected - validationResult.getSubFlowValidationResults().findAll { it.direction == "FORWARD" }.each { - assert !it.asExpected - } - validationResult.getSubFlowValidationResults().findAll { it.direction == "REVERSE" }.each { - assert it.asExpected + validationResult.subFlowsDiscrepancies.each { + assert it.flowDiscrepancies.get(FlowDirection.FORWARD) && !it.flowDiscrepancies.get(FlowDirection.REVERSE) } }