From a4ea48d682cd37a8dc92e519cbc46ab06f5e832d Mon Sep 17 00:00:00 2001 From: Zdenek Vales Date: Wed, 4 Mar 2020 20:05:20 +0100 Subject: [PATCH] #23: Base of algorithm for detecting MOVs. Tests. --- .../crce/apicomp/impl/mov/ApiDescription.java | 20 ++ .../{webservice => mov}/WsdlMovDetector.java | 59 +++- .../crce/apicomp/mov/WsdlMovDetectorTest.java | 255 ++++++++++++++++++ 3 files changed, 320 insertions(+), 14 deletions(-) create mode 100644 modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/ApiDescription.java rename modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/{webservice => mov}/WsdlMovDetector.java (69%) create mode 100644 modules/crce-api-compatibility-checker/src/test/java/cz/zcu/kiv/crce/apicomp/mov/WsdlMovDetectorTest.java diff --git a/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/ApiDescription.java b/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/ApiDescription.java new file mode 100644 index 00000000..5a8670c4 --- /dev/null +++ b/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/ApiDescription.java @@ -0,0 +1,20 @@ +package cz.zcu.kiv.crce.apicomp.impl.mov; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ApiDescription extends HashMap>> { + + public void addOperations(String hostname, String pathToEndpoint, List operations) { + if (!containsKey(hostname)) { + put(hostname, new HashMap<>()); + } + + if (!get(hostname).containsKey(pathToEndpoint)) { + get(hostname).put(pathToEndpoint, operations); + } else { + get(hostname).get(pathToEndpoint).addAll(operations); + } + } +} diff --git a/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/webservice/WsdlMovDetector.java b/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/WsdlMovDetector.java similarity index 69% rename from modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/webservice/WsdlMovDetector.java rename to modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/WsdlMovDetector.java index b9cc6329..984e954d 100644 --- a/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/webservice/WsdlMovDetector.java +++ b/modules/crce-api-compatibility-checker/src/main/java/cz/zcu/kiv/crce/apicomp/impl/mov/WsdlMovDetector.java @@ -1,5 +1,6 @@ -package cz.zcu.kiv.crce.apicomp.impl.webservice; +package cz.zcu.kiv.crce.apicomp.impl.mov; +import cz.zcu.kiv.crce.apicomp.impl.webservice.WebserviceIndexerConstants; import cz.zcu.kiv.crce.metadata.Capability; import java.util.ArrayList; @@ -17,17 +18,17 @@ public WsdlMovDetector(Capability api1, Capability api2) { this.api2 = api2; } - public void detectMov() { - Map>> api1EndpointUrls = collectEndpointUrls(api1); - Map>> api2EndpointUrls = collectEndpointUrls(api2); + public boolean[] detectMov(ApiDescription a1, ApiDescription a2) { + Map>> api1EndpointUrls = a1; + Map>> api2EndpointUrls = a2; boolean hostDiff = false; boolean pathDiff = false; boolean operationDiff = false; // determine whether hosts are same in both APIs - for (String hostName : api2EndpointUrls.keySet()) { - hostDiff |= api2EndpointUrls.containsKey(hostName); + for (String hostName : api1EndpointUrls.keySet()) { + hostDiff |= !api2EndpointUrls.containsKey(hostName); } // determine if paths to endpoints are same in both APIs @@ -37,13 +38,7 @@ public void detectMov() { operationDiff = determineOperationDiff(api1EndpointUrls, api2EndpointUrls); - - // what now? - if (hostDiff && pathDiff && operationDiff) { - // everything is different -> cannot detect - } else if (hostDiff && pathDiff && !operationDiff) { - - } + return new boolean[] {hostDiff, pathDiff, operationDiff}; } private boolean determinePathDiff(Map>> api1EndpointUrls, Map>> api2EndpointUrls) { @@ -76,6 +71,7 @@ private boolean determinePathDiff(Map>> api1End if (!pathDiffTmp) { // all endpoint paths from host 1 are in host 2 samePathSets++; + break; } } } @@ -96,7 +92,42 @@ private boolean determinePathDiff(Map>> api1End * @return */ private boolean determineOperationDiff(Map>> api1EndpointUrls, Map>> api2EndpointUrls) { - return false; + int sameOperationSets = 0; + int totalOperationSets = 0; + + for (Map> endpoints1 : api1EndpointUrls.values()) { + for (List operations1 : endpoints1.values()) { + totalOperationSets++; + + for (Map> endpoints2 : api2EndpointUrls.values()) { + if (endpoints2.size() == endpoints1.size()) { + // same number of endpoints in host + boolean operationDiff = false; + + for (List operations2 : endpoints2.values()) { + if (operations1.size() == operations2.size()) { + // same number of operations in endpoints + for (String operation1Name : operations1) { + if (!operations2.contains(operation1Name)) { + operationDiff = true; + break; + } + } + + if (!operationDiff) { + // same operations found + sameOperationSets++; + break; + } + } + } + + } + } + } + } + + return sameOperationSets != totalOperationSets; } // ws -> endpoint -> operations diff --git a/modules/crce-api-compatibility-checker/src/test/java/cz/zcu/kiv/crce/apicomp/mov/WsdlMovDetectorTest.java b/modules/crce-api-compatibility-checker/src/test/java/cz/zcu/kiv/crce/apicomp/mov/WsdlMovDetectorTest.java new file mode 100644 index 00000000..f9040786 --- /dev/null +++ b/modules/crce-api-compatibility-checker/src/test/java/cz/zcu/kiv/crce/apicomp/mov/WsdlMovDetectorTest.java @@ -0,0 +1,255 @@ +package cz.zcu.kiv.crce.apicomp.mov; + +import cz.zcu.kiv.crce.apicomp.impl.mov.ApiDescription; +import cz.zcu.kiv.crce.apicomp.impl.mov.WsdlMovDetector; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class WsdlMovDetectorTest { + + @Test + public void testDetectMov_same() { + ApiDescription api1 = createApi1(), + api2 = createApi1(); + + WsdlMovDetector detector = new WsdlMovDetector(null, null); + boolean[] diffs = detector.detectMov(api1, api2); + + assertFalse("Hosts should be the same!", diffs[0]); + assertFalse("Paths to endpoints should be the same!", diffs[1]); + assertFalse("Operations should be the same!", diffs[2]); + } + + @Test + public void testDetectMov_shuffledOp() { + ApiDescription api1 = createApi1(), + api2 = createApi1_shuffledOperations(); + + WsdlMovDetector detector = new WsdlMovDetector(null, null); + boolean[] diffs = detector.detectMov(api1, api2); + + assertFalse("Hosts should be the same!", diffs[0]); + assertFalse("Paths to endpoints should be the same!", diffs[1]); + assertFalse("Operations should be the same!", diffs[2]); + } + + @Test + public void testDetectMov_differentHost() { + ApiDescription api1 = createApi1(), + api2 = createApi1_diffHost(); + + WsdlMovDetector detector = new WsdlMovDetector(null, null); + boolean[] diffs = detector.detectMov(api1, api2); + + assertTrue("Hosts should not be the same!", diffs[0]); + assertFalse("Paths to endpoints should be the same!", diffs[1]); + assertFalse("Operations should be the same!", diffs[2]); + } + + @Test + public void testDetectMov_differentEndpoints() { + ApiDescription api1 = createApi1(), + api2 = createApi1_diffEndpoint(); + + WsdlMovDetector detector = new WsdlMovDetector(null, null); + boolean[] diffs = detector.detectMov(api1, api2); + + assertFalse("Hosts should be the same!", diffs[0]); + assertTrue("Paths to endpoints should not be the same!", diffs[1]); + assertFalse("Operations should be the same!", diffs[2]); + } + + @Test + public void testDetectMov_differentOperations() { + ApiDescription api1 = createApi1(), + api2 = createApi1_diffOperations(); + + WsdlMovDetector detector = new WsdlMovDetector(null, null); + boolean[] diffs = detector.detectMov(api1, api2); + + assertFalse("Hosts should be the same!", diffs[0]); + assertFalse("Paths to endpoints should be the same!", diffs[1]); + assertTrue("Operations should not be the same!", diffs[2]); + } + + @Test + public void testDetectMov_differentHostAndEndpoints() { + ApiDescription api1 = createApi1(), + api2 = createApi1_diffHostAndEndpoints(); + + WsdlMovDetector detector = new WsdlMovDetector(null, null); + boolean[] diffs = detector.detectMov(api1, api2); + + assertTrue("Hosts should not be the same!", diffs[0]); + assertTrue("Paths to endpoints should not be the same!", diffs[1]); + assertFalse("Operations should be the same!", diffs[2]); + } + + /** + * host -> e1 -> o1-1 + * o1-2 + * o1-3 + * -> e2 -> o2-1 + * o2-2 + * o2-3 + * o2-4 + * + * @return + */ + private ApiDescription createApi1() { + ApiDescription apiDescription = new ApiDescription(); + + List endpoint1operations = Arrays.asList( + "operation1-1", + "operation1-2", + "operation1-3" + ); + + List endpoint2operations = Arrays.asList( + "operation2-1", + "operation2-2", + "operation2-3", + "operation2-4" + ); + + apiDescription.addOperations("http://host-1.com", "/path/to/endpoint1", endpoint1operations); + apiDescription.addOperations("http://host-1.com", "/path/to/endpoint2", endpoint2operations); + + return apiDescription; + } + + /** + * Same as API 1 but operation names are shuffled + * @return + */ + private ApiDescription createApi1_shuffledOperations() { + ApiDescription apiDescription = new ApiDescription(); + + List endpoint1operations = Arrays.asList( + "operation1-3", + "operation1-1", + "operation1-2" + ); + + List endpoint2operations = Arrays.asList( + "operation2-3", + "operation2-2", + "operation2-4", + "operation2-1" + ); + + apiDescription.addOperations("http://host-1.com", "/path/to/endpoint2", endpoint2operations); + apiDescription.addOperations("http://host-1.com", "/path/to/endpoint1", endpoint1operations); + + return apiDescription; + } + + /** + * Same as API 1 but host is different + * @return + */ + private ApiDescription createApi1_diffHost() { + ApiDescription apiDescription = new ApiDescription(); + + List endpoint1operations = Arrays.asList( + "operation1-1", + "operation1-2", + "operation1-3" + ); + + List endpoint2operations = Arrays.asList( + "operation2-1", + "operation2-2", + "operation2-3", + "operation2-4" + ); + + apiDescription.addOperations("http://different-host-1.com", "/path/to/endpoint1", endpoint1operations); + apiDescription.addOperations("http://different-host-1.com", "/path/to/endpoint2", endpoint2operations); + + return apiDescription; + } + + /** + * Same as API 1 but path to endpoints are different + * @return + */ + private ApiDescription createApi1_diffEndpoint() { + ApiDescription apiDescription = new ApiDescription(); + + List endpoint1operations = Arrays.asList( + "operation1-1", + "operation1-2", + "operation1-3" + ); + + List endpoint2operations = Arrays.asList( + "operation2-1", + "operation2-2", + "operation2-3", + "operation2-4" + ); + + apiDescription.addOperations("http://host-1.com", "/this/way/to/endpoint1", endpoint1operations); + apiDescription.addOperations("http://host-1.com", "/this/way/to/endpoint2", endpoint2operations); + + return apiDescription; + } + + /** + * Same as API 1 but operation names are different. + * @return + */ + private ApiDescription createApi1_diffOperations() { + ApiDescription apiDescription = new ApiDescription(); + + List endpoint1operations = Arrays.asList( + "function1-1", + "function1-2", + "function1-3" + ); + + List endpoint2operations = Arrays.asList( + "function2-1", + "function2-2", + "function2-3", + "function2-4" + ); + + apiDescription.addOperations("http://host-1.com", "/path/to/endpoint1", endpoint1operations); + apiDescription.addOperations("http://host-1.com", "/path/to/endpoint2", endpoint2operations); + + return apiDescription; + } + + /** + * Api 1 but hostname and enpoint names are different + * @return + */ + private ApiDescription createApi1_diffHostAndEndpoints() { + ApiDescription apiDescription = new ApiDescription(); + + List endpoint1operations = Arrays.asList( + "operation1-1", + "operation1-2", + "operation1-3" + ); + + List endpoint2operations = Arrays.asList( + "operation2-1", + "operation2-2", + "operation2-3", + "operation2-4" + ); + + apiDescription.addOperations("http://different-host-1.com", "/this/way/to/endpoint1", endpoint1operations); + apiDescription.addOperations("http://different-host-1.com", "/this/way/to/endpoint2", endpoint2operations); + + return apiDescription; + } +}