diff --git a/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/utils/ServerPortsUtils.java b/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/utils/ServerPortsUtils.java new file mode 100644 index 0000000000..b2fb2019ab --- /dev/null +++ b/modules/integration/tests-common/integration-test-utils/src/main/java/org/wso2/am/integration/test/utils/ServerPortsUtils.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.am.integration.test.utils; + +import java.io.IOException; +import java.net.Socket; + +public class ServerPortsUtils { + + public static String LOCALHOST = "localhost"; + public static final int httpPortLowerRange = 8080; + public static final int httpPortUpperRange = 8099; + public static final int httpsPortLowerRange = 9950; + public static final int httpsPortUpperRange = 9999; + + /** + * Check whether give port is available + * + * @param port Port Number + * @return status + */ + private static boolean isPortFree(int port, String host) { + + Socket s = null; + try { + s = new Socket(host, port); + // something is using the port and has responded. + return false; + } catch (IOException e) { + //port available + return true; + } finally { + if (s != null) { + try { + s.close(); + } catch (IOException e) { + throw new RuntimeException("Unable to close connection ", e); + } + } + } + } + + public static int getAvailableHttpPort(String host) { + return getAvailablePort(httpPortLowerRange, httpPortUpperRange, host); + } + + public static int getAvailableHttpsPort(String host) { + return getAvailablePort(httpsPortLowerRange, httpsPortUpperRange, host); + } + + /** + * Find a free port to start backend WebSocket server in given port range + * + * @param lowerPortLimit from port number + * @param upperPortLimit to port number + * @return Available Port Number + */ + private static int getAvailablePort(int lowerPortLimit, int upperPortLimit, String host) { + while (lowerPortLimit < upperPortLimit) { + if (ServerPortsUtils.isPortFree(lowerPortLimit, host)) { + return lowerPortLimit; + } + lowerPortLimit += 1; + } + return -1; + } + +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APIEndpointCertificateTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APIEndpointCertificateTestCase.java index df9f61ab28..0d2ca5897f 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APIEndpointCertificateTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/APIEndpointCertificateTestCase.java @@ -42,14 +42,18 @@ import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; import org.wso2.am.integration.test.utils.bean.APIRequest; import org.wso2.am.integration.test.utils.http.HttpRequestUtil; +import org.wso2.carbon.automation.engine.context.AutomationContext; import org.wso2.carbon.automation.engine.context.TestUserMode; import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; +import org.wso2.carbon.integration.common.admin.client.LogViewerClient; +import org.wso2.carbon.logging.view.data.xsd.LogEvent; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.URL; +import java.rmi.RemoteException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -78,6 +82,7 @@ public class APIEndpointCertificateTestCase extends APIManagerLifecycleBaseTest String apiId; WireMockServer wireMockServer; private String accessToken; + private LogViewerClient logViewerClient; @Factory(dataProvider = "userModeDataProvider") public APIEndpointCertificateTestCase(TestUserMode userMode) { @@ -137,6 +142,11 @@ public void initialize() throws Exception { accessToken = applicationKeyDTO.getToken().getAccessToken(); waitForAPIDeploymentSync(user.getUserName(), apiRequest.getName(), apiRequest.getVersion(), APIMIntegrationConstants.IS_API_EXISTS); + AutomationContext autoContext = new AutomationContext(); + logViewerClient = new LogViewerClient(autoContext.getContextUrls().getBackEndUrl(), + autoContext.getSuperTenant().getTenantAdmin().getUserName(), + autoContext.getSuperTenant().getTenantAdmin().getPassword()); + logViewerClient.clearLogs(); } @Test(groups = {"wso2.am"}, description = "Invoke API without inserting Endpoint Certificate") @@ -263,7 +273,9 @@ public void testSearchEndpointCertificates() throws ApiException, ParseException "testSearchEndpointCertificates"}) public void testInvokeAPI() throws ApiException, InterruptedException, XPathExpressionException, IOException { - Thread.sleep(60000); // Sleep to reload the transport + // Thread.sleep(60000); // Sleep to reload the transport + // Wait for SSLProfile with the uploaded certificate to be reloaded in Gateway + waitForSSLProfileReload(); Map requestHeaders = new HashMap<>(); requestHeaders.put("accept", "application/json"); requestHeaders.put("Authorization", "Bearer " + accessToken); @@ -282,7 +294,8 @@ public void testInvokeAPIAfterRemovingCertificate() throws InterruptedException, Assert.assertEquals(response.getStatusCode(), 200); response = restAPIPublisher.deleteEndpointCertificate("endpoint-2"); Assert.assertEquals(response.getStatusCode(), 200); - Thread.sleep(60500); // Sleep to reload the transport + // Thread.sleep(60500); // Sleep to reload the transport + waitForSSLProfileReload(); Map requestHeaders = new HashMap<>(); requestHeaders.put("accept", "application/json"); requestHeaders.put("Authorization", "Bearer " + accessToken); @@ -320,6 +333,28 @@ private void startSecureEndpoint(int securedEndpointPort) { wireMockServer.start(); } + private void waitForSSLProfileReload() throws RemoteException, InterruptedException { + LogEvent[] logEvents = new LogEvent[0]; + Thread.sleep(60000); + logEvents = logViewerClient.getAllRemoteSystemLogs(); + int retryAttempt = 0; + boolean isSSProfileReloaded = false; + while (retryAttempt < 5 && !isSSProfileReloaded) { + for (LogEvent logEvent : logEvents) { + if (logEvent.getMessage() + .contains("PassThroughHttpSender reloading SSL Config")) { + isSSProfileReloaded = true; + log.info("SSLProfile has been reloaded successfully"); + logViewerClient.clearLogs(); + break; + } + } + retryAttempt++; + log.info("SSLProfile has not been reloaded. Retry attempt - " + retryAttempt); + Thread.sleep(12000); + } + } + @AfterClass(alwaysRun = true) public void destroy() throws ApiException { diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/graphql/GraphqlSubscriptionTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/graphql/GraphqlSubscriptionTestCase.java index 5a964e61cb..e1b17452b3 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/graphql/GraphqlSubscriptionTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/graphql/GraphqlSubscriptionTestCase.java @@ -89,7 +89,6 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -108,7 +107,6 @@ public class GraphqlSubscriptionTestCase extends APIMIntegrationBaseTest { private static final String GRAPHQL_API_NAME = "SnowtoothGraphQLSubAPI"; private static final String GRAPHQL_API_CONTEXT = "snowtooth"; private static final String GRAPHQL_API_VERSION = "1.0.0"; - private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private int webSocketServerPort; private String webSocketServerHost; private String graphqlApiId; @@ -118,6 +116,7 @@ public class GraphqlSubscriptionTestCase extends APIMIntegrationBaseTest { String throttleAppId; String complexAppId; String depthAppId; + Server server = null; private enum AUTH_IN { HEADER, @@ -623,8 +622,6 @@ private void invokeGraphQLSubscriptionSuccess(WebSocketClient client, String acc */ private void startGraphQLSubscriptionServer(final int serverPort) { - executorService.execute(() -> { - WebSocketHandler wsHandler = new WebSocketHandler() { @Override public void configure(WebSocketServletFactory factory) { @@ -633,7 +630,7 @@ public void configure(WebSocketServletFactory factory) { } }; - Server server = new Server(serverPort); + server = new Server(serverPort); server.setHandler(wsHandler); try { server.start(); @@ -643,7 +640,6 @@ public void configure(WebSocketServletFactory factory) { log.error("Error while starting graphql backend server at port: " + serverPort, e); Assert.fail("Cannot start GraphQL WebSocket server"); } - }); } /** @@ -1017,6 +1013,9 @@ private void testThrottling(String accessToken) throws Exception { "Received response in not a Connection Ack response"); socket.setResponseMessage(null); for (int count = 1; count <= limit; count++) { + if (count == limit) { + Thread.sleep(3000); + } if (count == 1) { //Send initial graphQL subscription request message textMessage = "{\"id\":\"2\",\"type\":\"start\",\"payload\":{\"variables\":{},\"extensions\":{}," @@ -1065,6 +1064,9 @@ private void testThrottling(String accessToken) throws Exception { @AfterClass(alwaysRun = true) public void destroy() throws Exception { + if (server != null) { + server.stop(); + } userManagementClient.deleteRole(GRAPHQL_ROLE); userManagementClient.deleteUser(GRAPHQL_TEST_USER); restAPIStore.deleteApplication(appJWTId); @@ -1072,7 +1074,6 @@ public void destroy() throws Exception { restAPIStore.deleteApplication(depthAppId); restAPIStore.deleteApplication(throttleAppId); undeployAndDeleteAPIRevisionsUsingRest(graphqlApiId, restAPIPublisher); - executorService.shutdownNow(); super.cleanUp(); } } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/MandatoryPropertiesTestWithRestart.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/MandatoryPropertiesTestWithRestart.java index 6b42108eae..2019c75e6c 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/MandatoryPropertiesTestWithRestart.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/MandatoryPropertiesTestWithRestart.java @@ -20,7 +20,7 @@ import org.apache.http.HttpStatus; import org.testng.Assert; import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; @@ -67,7 +67,7 @@ public static Object[][] userModeDataProvider() { return new Object[][] { new Object[] { TestUserMode.SUPER_TENANT_ADMIN }}; } - @BeforeClass(alwaysRun = true) + @BeforeTest(alwaysRun = true) public void setEnvironment() throws Exception { super.init(userMode); superTenantKeyManagerContext = new AutomationContext(APIMIntegrationConstants.AM_PRODUCT_GROUP_NAME, diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NotificationTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NotificationTestCase.java index 74d5e1b0ff..a33a94f324 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NotificationTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NotificationTestCase.java @@ -93,18 +93,24 @@ public void setEnvironment() throws Exception { super.init(userMode); storeURLHttp = "https://localhost:9943/"; - } - - @Test(groups = {"wso2.am"}, description = "Testing Notification Feature") - public void notificationTestCase() throws Exception { - //Setting greenMail server ServerSetup setup = new ServerSetup(SMTP_TEST_PORT, "localhost", "smtp"); greenMail = new GreenMail(setup); //Creating user in greenMail server greenMail.setUser(USER_EMAIL_ADDRESS, EMAIL_USERNAME, EMAIL_PASSWORD); - greenMail.start(); - log.info("green mail server started "); + try { + greenMail.start(); + } catch (IllegalStateException e) { + log.warn("There was a problem starting GreenMail server. Retrying in 10 seconds"); + Thread.sleep(10000); + greenMail.start(); + } + log.info("green mail server started"); + + } + + @Test(groups = {"wso2.am"}, description = "Testing Notification Feature") + public void notificationTestCase() throws Exception { // Adding API String url = getGatewayURLNhttp() + "response"; @@ -212,6 +218,7 @@ public void destroy() throws Exception { undeployAndDeleteAPIRevisionsUsingRest(newApiId, restAPIPublisher); restAPIPublisher.deleteAPI(apiId); restAPIPublisher.deleteAPI(newApiId); + greenMail.stop(); } @DataProvider diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/SoapToRestTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/SoapToRestTestCase.java index 481b8cd416..66d0e394e5 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/SoapToRestTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/SoapToRestTestCase.java @@ -23,6 +23,7 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.google.gson.Gson; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; @@ -56,10 +57,16 @@ import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; import javax.ws.rs.core.Response; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStream; +import java.io.ByteArrayInputStream; import java.net.Socket; import java.net.URL; import java.util.ArrayList; @@ -202,22 +209,37 @@ public void testValidateInOutSequence() String inSequence = IOUtils.toString(getClass().getClassLoader().getResourceAsStream( "artifacts" + File.separator + "AM" + File.separator + "soap" + File.separator + "in-sequence-check-phone-numbers.xml"), "UTF-8"); + String inSequenceRandomOrderedElement = removeSpacesInSequence(inSequence); ResourcePolicyListDTO resourcePolicyInListDTO = restAPIPublisher .getApiResourcePolicies(soapToRestAPIId, "in", "checkPhoneNumbers", "post"); resourcePoliciesIn = resourcePolicyInListDTO.getList(); resourcePoliciesIn.forEach((item) -> { - assertEquals(item.getContent(), inSequence, "Invalid In-Sequence"); + try { + String itemElement = removeSpacesInSequence(item.getContent()); + log.info("Generated In sequence: " + item.getContent()); + boolean equals = inSequenceRandomOrderedElement.equals(itemElement); + assertEquals(equals, true, "Invalid In-Sequence"); + } catch (Exception e) { + throw new RuntimeException(e); + } }); // Validate out-sequence String outSequence = IOUtils.toString(getClass().getClassLoader().getResourceAsStream( "artifacts" + File.separator + "AM" + File.separator + "soap" + File.separator + "out-sequence-check-phone-numbers.xml"), "UTF-8"); + String outSequenceElement = removeSpacesInSequence(outSequence); ResourcePolicyListDTO resourcePolicyOutListDTO = restAPIPublisher .getApiResourcePolicies(soapToRestAPIId, "out", "checkPhoneNumbers", "post"); resourcePoliciesOut = resourcePolicyOutListDTO.getList(); resourcePoliciesOut.forEach((item) -> { - assertEquals(item.getContent(), outSequence, "Invalid Out-Sequence"); + try { + String itemElement = removeSpacesInSequence(item.getContent()); + log.info("Generated out sequence: " + item.getContent()); + assertEquals(itemElement, outSequenceElement, "Invalid Out-Sequence"); + } catch (Exception e) { + log.error(e.getMessage()); + } }); } @@ -485,6 +507,7 @@ public void testUpdateInOutSequence() throws Exception { String updatedInSequence = IOUtils.toString(getClass().getClassLoader().getResourceAsStream( "artifacts" + File.separator + "AM" + File.separator + "soap" + File.separator + "updated-in-sequence-check-phone-numbers.xml"), "UTF-8"); + String inSequenceRandomOrderedElement = removeSpacesInSequence(updatedInSequence); resourcePoliciesIn.forEach((item) -> { ResourcePolicyInfoDTO updatedResourcePoliciesIn = null; item.setContent(updatedInSequence); @@ -494,23 +517,33 @@ public void testUpdateInOutSequence() throws Exception { } catch (org.wso2.am.integration.clients.publisher.api.ApiException e) { log.error(e.getMessage()); } - assertEquals(updatedResourcePoliciesIn.getContent(), updatedInSequence, "In-Sequence not updated"); + try { + String itemElement = removeSpacesInSequence(updatedResourcePoliciesIn.getContent()); + log.info("Generated updated in sequence: " + updatedResourcePoliciesIn.getContent()); + boolean equals = inSequenceRandomOrderedElement.equals(itemElement); + assertEquals(equals, true, "In-Sequence not updated"); + } catch (Exception e) { + log.error(e.getMessage()); + } }); // Update out-sequence String updatedOutSequence = IOUtils.toString(getClass().getClassLoader().getResourceAsStream( "artifacts" + File.separator + "AM" + File.separator + "soap" + File.separator + "updated-out-sequence-check-phone-numbers.xml"), "UTF-8"); + String updatedOutSequenceElement = removeSpacesInSequence(updatedOutSequence); resourcePoliciesOut.forEach((item) -> { - item.setContent(updatedOutSequence); - ResourcePolicyInfoDTO updatedResourcePoliciesOut = null; - try { - updatedResourcePoliciesOut = restAPIPublisher - .updateApiResourcePolicies(soapToRestAPIId, item.getId(), item.getResourcePath(), item, null); - } catch (org.wso2.am.integration.clients.publisher.api.ApiException e) { - log.error(e.getMessage()); - } - assertEquals(updatedResourcePoliciesOut.getContent(), updatedOutSequence, "Out-Sequence not updated"); + item.setContent(updatedOutSequence); + ResourcePolicyInfoDTO updatedResourcePoliciesOut = null; + try { + updatedResourcePoliciesOut = restAPIPublisher + .updateApiResourcePolicies(soapToRestAPIId, item.getId(), item.getResourcePath(), item, null); + log.info("Generated updated out sequence: " + updatedResourcePoliciesOut.getContent()); + String updatedResourcePoliciesOutElement = removeSpacesInSequence(updatedResourcePoliciesOut.getContent()); + assertEquals(updatedResourcePoliciesOutElement, updatedOutSequenceElement, "Out-Sequence not updated"); + } catch (Exception e) { + log.error(e.getMessage()); + } }); } @@ -611,6 +644,30 @@ private File getTempFileWithContent(String schema) throws Exception { return temp; } + public static String removeSpacesInSequence(String xml) throws Exception { + String closedXml = "" + xml + ""; + InputStream stream = new ByteArrayInputStream(closedXml.getBytes()); + XMLStreamReader parser; + StAXOMBuilder builder; + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + parser = factory.createXMLStreamReader(stream); + XMLStreamReader filteredReader = factory.createFilteredReader(parser, new StreamFilter() { + public boolean accept(XMLStreamReader r) { + return !r.isWhiteSpace(); + } + }); + builder = new StAXOMBuilder(filteredReader); + } catch (XMLStreamException e) { + String msg = "Error in initializing the parser."; + log.error(msg, e); + throw new Exception(msg, e); + } + + return builder.getDocumentElement().toString().replace(" ",""); + } + @DataProvider public static Object[][] userModeDataProvider() { return new Object[][]{ diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/ContentSearchTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/ContentSearchTestCase.java index 4287a596dd..ccffa3e5b6 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/ContentSearchTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/ContentSearchTestCase.java @@ -223,7 +223,7 @@ public void testDocumentContentSearch() throws Exception { } else { log.warn("Document content search in publisher failed. Received response : " + searchResultListDTO .getCount() + " Retrying..."); - Thread.sleep(3000); + Thread.sleep(Math.min(3000L * (i + 1), 30000L)); } } } @@ -243,7 +243,7 @@ public void testDocumentContentSearch() throws Exception { } else { log.warn("Document content search in store failed. Received response : " + searchResultListDTO .getCount() + " Retrying..."); - Thread.sleep(3000); + Thread.sleep(Math.min(3000L * (i + 1), 30000L)); } } } diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/admin/throttlingpolicy/SubscriptionThrottlingPolicyTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/admin/throttlingpolicy/SubscriptionThrottlingPolicyTestCase.java index ade97c4e34..e5ba6c3052 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/admin/throttlingpolicy/SubscriptionThrottlingPolicyTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/restapi/admin/throttlingpolicy/SubscriptionThrottlingPolicyTestCase.java @@ -43,6 +43,7 @@ import org.wso2.am.integration.test.utils.base.APIMIntegrationBaseTest; import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; import org.wso2.am.integration.test.utils.bean.APIRequest; +import org.wso2.am.integration.tests.throttling.ThrottlingUtils; import org.wso2.carbon.automation.engine.context.TestUserMode; import org.wso2.carbon.automation.test.utils.http.client.HttpRequestUtil; import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; @@ -272,15 +273,20 @@ public void testSubscriptionLevelThrottling() throws Exception { requestHeaders1.put("content-type", "application/json"); HttpResponse response1; boolean isThrottled1 = false; + int totalNumberOfRequests = 15; + ThrottlingUtils.waitUntilNextClockHourIfCurrentHourIsInLastNMinutes(3); for (int i = 0; i < 15; i++) { - response1 = HttpRequestUtil.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION) + API_END_POINT_METHOD, - requestHeaders1); - if (response1.getResponseCode() == 429) { - Assert.assertTrue(i >= 10); - isThrottled1 = true; - break; - } - Thread.sleep(1000); + if (i == totalNumberOfRequests - 1) { + Thread.sleep(ThrottlingUtils.WAIT_FOR_JMS_THROTTLE_EVENT_IN_MILLISECONDS); + } + response1 = HttpRequestUtil.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION) + API_END_POINT_METHOD, + requestHeaders1); + if (response1.getResponseCode() == 429) { + Assert.assertTrue(i >= 10); + isThrottled1 = true; + break; + } + Thread.sleep(1000); } Assert.assertTrue(isThrottled1, "Request not throttled by " + policyName1); restAPIStore.removeSubscription(subscriptionDTO); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/throttling/ThrottlingUtils.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/throttling/ThrottlingUtils.java new file mode 100644 index 0000000000..7acce05b35 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/throttling/ThrottlingUtils.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.am.integration.tests.throttling; + +import java.util.Calendar; + +/* + *Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + *WSO2 Inc. licenses this file to you under the Apache License, + *Version 2.0 (the "License"); you may not use this file except + *in compliance with the License. + *You may obtain a copy of the License at + * + *http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + *KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +public class ThrottlingUtils { + public static int WAIT_FOR_JMS_THROTTLE_EVENT_IN_MILLISECONDS = 3000; + + /** + * Wait until next hour starts if the current hour has only n minutes left. + * @param n + * @throws InterruptedException + */ + public static void waitUntilNextClockHourIfCurrentHourIsInLastNMinutes(int n) throws InterruptedException { + int timeUntilNextHour = getTimeToNextHourInMinutes(); + if (n >= timeUntilNextHour) { + Thread.sleep(timeUntilNextHour * 60 * 1000); + } + } + + public static int getTimeToNextHourInMinutes() { + Calendar calendar = Calendar.getInstance(); + int minutesInTime = calendar.get(Calendar.MINUTE); + return 60 - minutesInTime; + } +} \ No newline at end of file diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/websocket/WebSocketAPITestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/websocket/WebSocketAPITestCase.java index acb5eb3592..073c262f51 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/websocket/WebSocketAPITestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/websocket/WebSocketAPITestCase.java @@ -100,7 +100,6 @@ enum AUTH_IN { HEADER, QUERY } - private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private final String apiName = "WebSocketAPI"; private final String applicationName = "WebSocketApplication"; private final String applicationJWTName = "WebSocketJWTTypeApplication"; @@ -131,6 +130,7 @@ enum AUTH_IN { long throttleMarkTime = 0; String apiVersion2 = "2.0.0"; String endPointApplication = "EndPointApplication"; + Server server = null; @Factory(dataProvider = "userModeDataProvider") public WebSocketAPITestCase(TestUserMode userMode) { @@ -160,15 +160,7 @@ public void setEnvironment() throws Exception { (new File(wsEventPublisherSource + wsThrottleOutEventPublisherSource), new File(wsEventPublisherTarget + wsThrottleOutEventPublisherSource), false); webSocketServerHost = InetAddress.getLocalHost().getHostName(); - int lowerPortLimit = 9950; - int upperPortLimit = 9999; - webSocketServerPort = getAvailablePort(lowerPortLimit, upperPortLimit); - if (webSocketServerPort == -1) { - throw new APIManagerIntegrationTestException("No available port in the range " + - lowerPortLimit + "-" + upperPortLimit + " was found"); - } - log.info("Selected port " + webSocketServerPort + " to start backend server"); - startWebSocketServer(webSocketServerPort); + startWebSocketServer(); } @Test(description = "Publish WebSocket API") @@ -498,33 +490,24 @@ private void waitForReply(WebSocketClientImpl clientSocket) { /** * Starts backend web socket server in given port * - * @param serverPort Port that WebSocket Server starts */ - private void startWebSocketServer(final int serverPort) { - - executorService.execute(new Runnable() { - public void run() { - - WebSocketHandler wsHandler = new WebSocketHandler() { - @Override - public void configure(WebSocketServletFactory factory) { - - factory.register(WebSocketServerImpl.class); - } - }; - Server server = new Server(serverPort); - server.setHandler(wsHandler); - try { - server.start(); - log.info("WebSocket backend server started at port: " + serverPort); - } catch (InterruptedException ignore) { - } catch (Exception e) { - log.error("Error while starting backend server at port: " + serverPort, e); - Assert.fail("Cannot start WebSocket server"); - } + private void startWebSocketServer() { + WebSocketHandler wsHandler = new WebSocketHandler() { + @Override + public void configure(WebSocketServletFactory factory) { + factory.register(WebSocketServerImpl.class); } - - }); + }; + server = new Server(serverPort); + server.setHandler(wsHandler); + try { + server.start(); + log.info("WebSocket backend server started at port: " + serverPort); + } catch (InterruptedException ignore) { + } catch (Exception e) { + log.error("Error while starting backend server at port: " + serverPort, e); + Assert.fail("Cannot start WebSocket server"); + } } /** @@ -563,6 +546,7 @@ private void testThrottling(String accessToken) throws Exception { log.info("Repeating the test as throttling testing time duration is dispersed into two " + "separate units of time"); testThrottling(accessToken); + return; } assertEquals(socket.getResponseMessage(), "Error code: 4003 reason: Websocket frame throttled out", "Received response is not matching"); @@ -626,9 +610,10 @@ private void invokeAPI(WebSocketClient client, String accessToken, AUTH_IN in, H @AfterClass(alwaysRun = true) public void destroy() throws Exception { - + if (server != null) { + server.stop(); + } serverConfigurationManager.restoreToLastConfiguration(false); - executorService.shutdownNow(); super.cleanUp(); } } diff --git a/modules/integration/tests-integration/tests-restart/src/test/java/org/wso2/am/integration/tests/server/restart/GraphqlServerRestartTestCase.java b/modules/integration/tests-integration/tests-restart/src/test/java/org/wso2/am/integration/tests/server/restart/GraphqlServerRestartTestCase.java index ffeeadc6fc..4497870ba0 100644 --- a/modules/integration/tests-integration/tests-restart/src/test/java/org/wso2/am/integration/tests/server/restart/GraphqlServerRestartTestCase.java +++ b/modules/integration/tests-integration/tests-restart/src/test/java/org/wso2/am/integration/tests/server/restart/GraphqlServerRestartTestCase.java @@ -391,7 +391,10 @@ private File getTempFileWithContent(String schema) throws Exception { @AfterClass(alwaysRun = true) public void cleanUpArtifacts() throws Exception { - userManagementClient.deleteRole(GRAPHQL_ROLE); + // Clean up the role only if it is available + if(userManagementClient.roleNameExists(GRAPHQL_ROLE)){ + userManagementClient.deleteRole(GRAPHQL_ROLE); + } userManagementClient.deleteUser(GRAPHQL_TEST_USER); restAPIStore.deleteApplication(testAppId1); restAPIStore.deleteApplication(testAppId2);