package alien4cloud.it.provider; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import alien4cloud.it.Context; import alien4cloud.it.provider.util.AttributeUtil; import alien4cloud.it.provider.util.HttpUtil; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import cucumber.api.java.en.And; import cucumber.api.java.en.Then; @Slf4j public class HttpStepsDefinitions { @And("^The URL which is defined in attribute \"([^\"]*)\" of the node \"([^\"]*)\" should work$") public void The_URL_which_is_defined_in_attribute_of_the_node_should_work(String attributeName, String nodeName) throws Throwable { The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain(attributeName, nodeName, null); } @And("^The URL which is defined in attribute \"([^\"]*)\" of the node \"([^\"]*)\" suffixed by \"([^\"]*)\" should work$") public void The_URL_which_is_defined_in_attribute_of_the_node_should_work(String attributeName, String nodeName, String suffix) throws Throwable { String baseUrl = AttributeUtil.getAttribute(nodeName, attributeName); String toCheck = null; if (baseUrl != null) { if (baseUrl.endsWith("/")) { toCheck = baseUrl.concat(suffix); } else { toCheck = baseUrl.concat("/").concat(suffix); } } HttpUtil.checkUrl(toCheck, null, 2 * 60 * 1000L); } @And("^The URL which is defined in attribute \"([^\"]*)\" of the node \"([^\"]*)\" should work and the html should contain \"([^\"]*)\"$") public void The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain(String attributeName, String nodeName, String expectedContent) throws Throwable { HttpUtil.checkUrl(AttributeUtil.getAttribute(nodeName, attributeName), expectedContent, 2 * 60 * 1000L); } @Then("^I store the attribute \"(.*?)\" of the node \"(.*?)\" as registered string \"(.*?)\"$") public void i_store_the_attribute_of_the_node_as_registered_string(String attributeName, String nodeName, String key) throws Throwable { String attributeValue = AttributeUtil.getAttribute(nodeName, attributeName); Context.getInstance().registerStringContent(key, attributeValue); } @And("^I call the URL which is defined in registered string \"([^\"]*)\" with path \"([^\"]*)\" and fetch the response and store it in the context as \"([^\"]*)\"$") public void fetchUrlContentFromRegisteredString(String urlKey, String path, String key) throws Throwable { String url = Context.getInstance().getRegisteredStringContent(urlKey); String response = HttpUtil.fetchUrl(url + path, 2 * 60 * 1000L); Context.getInstance().registerStringContent(key, response); } @And("^I call the URL which is defined in attribute \"([^\"]*)\" of the node \"([^\"]*)\" with path \"([^\"]*)\" and fetch the response and store it in the context as \"([^\"]*)\"$") public void fetchUrlContent(String attributeName, String nodeName, String path, String key) throws Throwable { String response = HttpUtil.fetchUrl(AttributeUtil.getAttribute(nodeName, attributeName) + path, 2 * 60 * 1000L); Context.getInstance().registerStringContent(key, response); } @And("^The URL\\(s\\) which are defined in attribute \"([^\"]*)\" of the (\\d+) instance\\(s\\) of the node \"([^\"]*)\" should work and the html should contain \"([^\"]*)\"$") public void The_URL_s_which_are_defined_in_attribute_of_the_instance_s_of_the_node_should_work_and_the_html_should_contain(String attributeName, int numberOfInstances, String nodeName, String expectedContent) throws Throwable { Map<String, String> allAttributes = AttributeUtil.getAttributes(nodeName, attributeName); Assert.assertEquals(numberOfInstances, allAttributes.size()); for (String url : allAttributes.values()) { HttpUtil.checkUrl(url, expectedContent, 2 * 60 * 1000L); } } @And("^The URL which is defined in attribute \"([^\"]*)\" of the node \"([^\"]*)\" should work and the html should contain \"([^\"]*)\" and \"([^\"]*)\"$") public void The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain_and(String attributeName, String nodeName, String expectedContent, String otherExpectedContent) throws Throwable { The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain(attributeName, nodeName, expectedContent); The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain(attributeName, nodeName, otherExpectedContent); } private class CheckUrlWorker implements Runnable { private String attributeName; private String nodeName; private String expectedContent; public CheckUrlWorker(String attributeName, String nodeName, String expectedContent) { this.attributeName = attributeName; this.nodeName = nodeName; this.expectedContent = expectedContent; } @Override public void run() { try { The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain(attributeName, nodeName, expectedContent); } catch (InterruptedException e) { log.info("Check URL for " + attributeName + " of node " + nodeName + "has been interrupted"); } catch (Throwable throwable) { throw new RuntimeException(throwable); } } } private class CheckUrlCallback implements FutureCallback<Object> { private AtomicInteger failureCount = new AtomicInteger(0); private AtomicBoolean success = new AtomicBoolean(false); @Override public synchronized void onSuccess(Object result) { this.success.set(true); this.notify(); } @Override public synchronized void onFailure(Throwable t) { log.info("CheckUrlWorker failed", t); if (failureCount.incrementAndGet() == 2) { this.notify(); } } public synchronized boolean isSuccessful() { return success.get(); } } @And("^The URL which is defined in attribute \"([^\"]*)\" of the node \"([^\"]*)\" should work and the html should contain \"([^\"]*)\" or \"([^\"]*)\"$") public void The_URL_which_is_defined_in_attribute_of_the_node_should_work_and_the_html_should_contain_or(final String attributeName, final String nodeName, final String expectedContent, final String otherExpectedContent) throws Throwable { final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); t.setName("CheckURLThread"); return t; } })); ListenableFuture future = executor.submit(new CheckUrlWorker(attributeName, nodeName, expectedContent)); ListenableFuture otherFuture = executor.submit(new CheckUrlWorker(attributeName, nodeName, otherExpectedContent)); CheckUrlCallback futureCallback = new CheckUrlCallback(); Futures.addCallback(future, futureCallback); Futures.addCallback(otherFuture, futureCallback); synchronized (futureCallback) { futureCallback.wait(); } if (!futureCallback.isSuccessful()) { throw new RuntimeException("None of the urls to check is valid"); } else { log.info("Test has been successfull"); } executor.shutdownNow(); } }