You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by du...@apache.org on 2020/04/09 13:50:43 UTC
svn commit: r38870 [5/6] - in /release/sling: ./ src/ src/main/
src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/sling/ src/main/java/org/apache/sling/testing/
src/main/java/org/apache/sling/testing/clients/ src/main...
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/JsonUtils.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/JsonUtils.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/JsonUtils.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import org.apache.sling.testing.clients.ClientException;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+
+public class JsonUtils {
+ /**
+ * Get {@link JsonNode} from a a String containing JSON.
+ *
+ * @param jsonString A string containing JSON
+ * @return A {@link JsonNode} that is the root node of the JSON structure.
+ * @throws ClientException if error occurs while reading json string
+ */
+ public static JsonNode getJsonNodeFromString(String jsonString) throws ClientException {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ return mapper.readTree(jsonString);
+ } catch (JsonProcessingException e) {
+ throw new ClientException("Could not read json file.", e);
+ } catch (IOException e) {
+ throw new ClientException("Could not read json node.", e);
+ }
+ }
+}
\ No newline at end of file
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/PortAllocator.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/PortAllocator.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/PortAllocator.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import java.net.ServerSocket;
+import java.util.HashSet;
+import java.util.Set;
+
+public class PortAllocator {
+
+ private static Set<Integer> allocatedPorts;
+
+ static {
+ allocatedPorts = new HashSet<Integer>();
+ }
+
+ public Integer allocatePort() {
+ while (true) {
+ int port = tryAllocation();
+
+ boolean portAdded = checkAndAddPort(port);
+
+ if (portAdded) {
+ return port;
+ }
+ }
+ }
+
+ private int tryAllocation() {
+ try {
+ ServerSocket serverSocket = new ServerSocket(0);
+ int port = serverSocket.getLocalPort();
+ serverSocket.close();
+ return port;
+ } catch (Exception e) {
+ throw new RuntimeException("Can't allocate a port");
+ }
+ }
+
+ private synchronized boolean checkAndAddPort(int port) {
+ return allocatedPorts.add(port);
+ }
+
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/ResourceUtil.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/ResourceUtil.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/ResourceUtil.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class ResourceUtil {
+
+ /**
+ * We must get the Resource as a stream from the ContextClassLoader and not from the normal classLoader
+ * acquired by using getClass.getClassLoader, since we must be able to load resources from different threads
+ * e.g. running in ant.
+ *
+ * @param resourcePath path to the resource
+ * @return resource as InputStream
+ */
+ public static InputStream getResourceAsStream(final String resourcePath) {
+ final String path = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath;
+ return Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+ }
+
+ /**
+ * Helper method to read a resource from class using {@link Class#getResourceAsStream(String)}
+ * and convert into a String.
+ *
+ * @param resource The resource to read.
+ * @return The requested resource as String, resolved using
+ * {@link Class#getResourceAsStream(String)}, or {@code null}
+ * if the requested resource cannot be resolved for some reason
+ * @throws IOException if the Resource Stream cannot be read
+ */
+ public static String readResourceAsString(final String resource) throws IOException {
+ InputStream resourceAsStream = ResourceUtil.getResourceAsStream(resource);
+ if (resourceAsStream != null) {
+ StringBuilder sb = new StringBuilder();
+ String line;
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(resourceAsStream, UTF_8.name()));
+ while ((line = reader.readLine()) != null) {
+ if (sb.length() > 0) {
+ sb.append("\n");
+ }
+ sb.append(line);
+ }
+ } finally {
+ resourceAsStream.close();
+ }
+ return sb.toString();
+ }
+ return null;
+ }
+
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/ServerErrorRetryStrategy.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/ServerErrorRetryStrategy.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/ServerErrorRetryStrategy.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ServiceUnavailableRetryStrategy;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+import org.apache.sling.testing.clients.SystemPropertiesConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.apache.http.HttpStatus.*;
+
+/**
+ * {code ServiceUnavailableRetryStrategy} strategy for retrying request in case of a 5XX response code
+ */
+public class ServerErrorRetryStrategy implements ServiceUnavailableRetryStrategy {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ServerErrorRetryStrategy.class);
+
+ public ServerErrorRetryStrategy() {
+ super();
+ }
+
+ @Override
+ public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context) {
+ boolean needsRetry = executionCount <= SystemPropertiesConfig.getHttpRetries() && responseRetryCondition(response);
+
+ if (SystemPropertiesConfig.isHttpLogRetries() && needsRetry && LOG.isWarnEnabled()) {
+ LOG.warn("Request retry needed due to service unavailable response");
+ LOG.warn("Response headers contained:");
+ Arrays.stream(response.getAllHeaders()).forEach(h -> LOG.warn("Header {}:{}", h.getName(), h.getValue()));
+ try {
+ String content = EntityUtils.toString(response.getEntity());
+ LOG.warn("Response content: {}", content);
+ } catch (IOException exc) {
+ LOG.warn("Response as no content");
+ }
+ }
+ return needsRetry;
+ }
+
+ @Override
+ public long getRetryInterval() {
+ return SystemPropertiesConfig.getHttpRetriesDelay();
+ }
+
+ private boolean responseRetryCondition(final HttpResponse response) {
+ final Integer statusCode = response.getStatusLine().getStatusCode();
+ final Collection<Integer> errorCodes = SystemPropertiesConfig.getHttpRetriesErrorCodes();
+ if (errorCodes != null && !errorCodes.isEmpty()) {
+ return errorCodes.contains(statusCode);
+ } else {
+ return statusCode >= SC_INTERNAL_SERVER_ERROR &&
+ statusCode < SC_INTERNAL_SERVER_ERROR + 100;
+ }
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/SlingParameter.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/SlingParameter.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/SlingParameter.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ */
+public class SlingParameter {
+
+ private String typeHint = null;
+ private boolean delete = false;
+
+ String parameterName;
+ private String[] values = null;
+ private boolean multiple = false;
+
+ public SlingParameter(String parameterName) {
+ if (parameterName == null || parameterName.length() == 0) {
+ throw new IllegalArgumentException("parameterName must not be null or empty");
+ }
+ this.parameterName = parameterName;
+ }
+
+ public SlingParameter value(String value) {
+ if (value != null) {
+ this.values(new String[]{value});
+ } else {
+ this.values(new String[]{});
+ }
+ return this;
+ }
+
+ public SlingParameter values(String[] values) {
+ if (values == null) {
+ this.values = new String[]{};
+ } else {
+ this.values = values;
+ }
+ return this;
+ }
+
+ public SlingParameter typeHint(String typeHint) {
+ this.typeHint = typeHint;
+ return this;
+ }
+
+ public SlingParameter delete() {
+ this.delete = true;
+ return this;
+ }
+
+ public SlingParameter multiple() {
+ this.multiple = true;
+ return this;
+ }
+
+ public List<NameValuePair> toNameValuePairs() {
+ List<NameValuePair> parameters = new ArrayList<NameValuePair>();
+
+ if (multiple) {
+ for (String value : values) {
+ parameters.add(new BasicNameValuePair(parameterName, value));
+ }
+ } else if (values != null && values.length == 1) {
+ parameters.add(new BasicNameValuePair(parameterName, values[0]));
+ } else if (values != null && values.length > 1) {
+ // TODO not sure about the proper format of the values in this case?
+ // For now, only take the first one.
+ parameters.add(new BasicNameValuePair(parameterName, values[0]));
+ } else {
+ parameters.add(new BasicNameValuePair(parameterName, null));
+ }
+
+ // add @TypeHint suffix
+ if (typeHint != null) {
+ String parameter = parameterName + "@TypeHint";
+ parameters.add(new BasicNameValuePair(parameter, typeHint));
+ }
+
+ // add @Delete suffix
+ if (delete) {
+ String parameter = parameterName + "@Delete";
+ parameters.add(new BasicNameValuePair(parameter, "true"));
+ }
+
+ return parameters;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/TimeoutsProvider.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/TimeoutsProvider.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/TimeoutsProvider.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.sling.testing.clients.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Return timeout values that can be multiplied by a configurable
+ * factor. Useful to cope with slower integration testing systems:
+ * use timeout constants in your code that work for usual development
+ * systems, and set a multiplier when running on a slower system.
+ *
+ * @deprecated duplicate of {@link org.apache.sling.testing.timeouts.TimeoutsProvider}. This will be removed in the future, so switch to
+ * the other one instead
+ */
+@Deprecated
+public class TimeoutsProvider {
+ private static final Logger log = LoggerFactory.getLogger(TimeoutsProvider.class);
+ public static final String PROP_TIMEOUT_MULTIPLIER = "sling.testing.timeout.multiplier";
+ private static float timeoutFactor = -1;
+ private static TimeoutsProvider INSTANCE;
+
+ private TimeoutsProvider() {
+ if(timeoutFactor < 0) {
+ timeoutFactor = 1;
+ final String str = System.getProperty(PROP_TIMEOUT_MULTIPLIER);
+ if(str != null) {
+ try {
+ timeoutFactor = Float.valueOf(str.trim());
+ log.info("Timeout factor set to {} from system property {}",
+ timeoutFactor, PROP_TIMEOUT_MULTIPLIER);
+ } catch(NumberFormatException nfe) {
+ throw new IllegalStateException("Invalid timeout factor: " + PROP_TIMEOUT_MULTIPLIER + "=" + str);
+ }
+ }
+ }
+ }
+
+ public static TimeoutsProvider getInstance() {
+ if(INSTANCE == null) {
+ synchronized (TimeoutsProvider.class) {
+ INSTANCE = new TimeoutsProvider();
+ }
+ }
+ return INSTANCE;
+ }
+
+ public long getTimeout(long nomimalValue) {
+ final long result = (long)(nomimalValue * timeoutFactor);
+ return result;
+ }
+
+ public int getTimeout(int nomimalValue) {
+ final int result = (int)(nomimalValue * timeoutFactor);
+ return result;
+ }
+
+ /**
+ * Get timeout from a system property, with default value
+ * @param systemPropertyName Name of the system property that holds the timeout multiplier
+ * @param defaultNominalValue The default timeout multiplier
+ * @return the total timeout value
+ */
+ public int getTimeout(String systemPropertyName, int defaultNominalValue) {
+ int result = defaultNominalValue;
+ final String str = System.getProperty(systemPropertyName);
+ if(str != null) {
+ result = Integer.parseInt(str);
+ }
+ return getTimeout(result);
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/URLParameterBuilder.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/URLParameterBuilder.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/URLParameterBuilder.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.message.BasicNameValuePair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class URLParameterBuilder {
+
+ public final static String DEFAULT_ENCODING = "UTF-8";
+
+ private List<NameValuePair> params;
+ private String encoding;
+
+ public static URLParameterBuilder create() {
+ return new URLParameterBuilder();
+ }
+
+ URLParameterBuilder() {
+ params = new ArrayList<NameValuePair>();
+ encoding = DEFAULT_ENCODING;
+ }
+
+ public URLParameterBuilder add(String name, String value) {
+ params.add(new BasicNameValuePair(name, value));
+ return this;
+ }
+
+ public URLParameterBuilder add(NameValuePair pair) {
+ params.add(pair);
+ return this;
+ }
+
+ public URLParameterBuilder add(List<NameValuePair> list) {
+ params.addAll(list);
+ return this;
+ }
+
+ public URLParameterBuilder add(String name, String[] values) {
+ for (String value : values) this.add(name, value);
+ return this;
+ }
+
+ public URLParameterBuilder setEncoding(String encoding) {
+ this.encoding = encoding;
+ return this;
+ }
+
+ /**
+ * Build the URL parameters
+ *
+ * @return The URL parameters string without the leading question mark.
+ */
+ public String getURLParameters() {
+ return URLEncodedUtils.format(params, encoding);
+ }
+
+ public List<NameValuePair> getList() {
+ return params;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/UniquePaths.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/UniquePaths.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/UniquePaths.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/** Generate unique paths, for tests isolation */
+public class UniquePaths {
+
+ private static long startTime = System.currentTimeMillis();
+ private static AtomicLong counter = new AtomicLong();
+ public final static String SEP = "_";
+ public final static String U_PATTERN = "_UNIQ_";
+
+ /**
+ * Return a unique path based on basePath
+ * @param nameReference The simple class name of that object is used as part of the
+ * generated unique ID
+ * @param basePath All occurrences of {@link UniquePaths#U_PATTERN} in basePath are replaced by the generated
+ * unique ID. If $U$ is not found in basePath, unique ID is added at its end.
+ * @return path with a unique value for each call.
+ */
+ public static String get(Object nameReference, String basePath) {
+ if(basePath == null) {
+ basePath = "";
+ }
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append(nameReference.getClass().getSimpleName());
+ sb.append(SEP);
+ sb.append(startTime);
+ sb.append(SEP);
+ sb.append(counter.incrementAndGet());
+
+ if(basePath.contains(U_PATTERN)) {
+ return basePath.replaceAll(U_PATTERN, sb.toString());
+ } else {
+ return basePath + sb.toString();
+ }
+ }
+
+ /**
+ * Get a unique ID with no base path
+ *
+ * @param nameReference The simple class name of that object is used as part of the
+ * generated unique ID
+ * @return path with a unique value for each call
+ */
+ public static String get(Object nameReference) {
+ return get(nameReference, null);
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/XSSUtils.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/XSSUtils.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/XSSUtils.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.sling.xss.XSSAPI;
+import org.apache.sling.xss.impl.XSSAPIImpl;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+/**
+ * Basic class for XSS Testing
+ * The reliability of these methods are not critical
+ */
+public class XSSUtils {
+
+ /**
+ * Use to ensure that HTTP query strings are in proper form, by escaping
+ * special characters such as spaces.
+ *
+ * @param urlString the string to be encoded
+ * @return the encoded string
+ */
+ public static String encodeUrl(String urlString) {
+ try {
+ return URLEncoder.encode(urlString, "UTF-8");
+ } catch (UnsupportedEncodingException ex) {
+ throw new RuntimeException("UTF-8 not supported", ex);
+ }
+ }
+
+ /**
+ * Use to encapsulate old-style escaping of HTML (using StringEscapeUtils).
+ * NB: newer code uses XSSAPI (based on OWASP's ESAPI).
+ *
+ * @param htmlString the string to be escaped
+ * @return the escaped string
+ */
+ public static String escapeHtml(String htmlString) {
+ return StringEscapeUtils.escapeHtml4(htmlString);
+ }
+
+ /**
+ * Use to encapsulate old-style escaping of XML (with JSTL encoding rules).
+ * NB: newer code uses XSSAPI (based on OWASP's ESAPI).
+ *
+ * @param xmlString the string to be escaped
+ * @return the escaped string
+ */
+ public static String escapeXml(String xmlString) {
+ String xssString = xmlString;
+ if (xmlString != null) {
+ xssString = xssString.replace(";", ";");
+ xssString = xssString.replace(" ", " ");
+ xssString = xssString.replace("'", "'");
+ xssString = xssString.replace("\"", """);
+ xssString = xssString.replace(">", ">");
+ xssString = xssString.replace("<", "<");
+ xssString = xssString.replace("/", "/");
+ xssString = xssString.replace("(", "(");
+ xssString = xssString.replace(")", ")");
+ xssString = xssString.replace(":", ":");
+ }
+ return xssString;
+ }
+
+ /**
+ * Use to encapsulate new-style (XSSAPI-based) encoding for HTML element content.
+ *
+ * @param source the string to be encoded
+ * @return the encoded string
+ */
+ public static String encodeForHTML(String source) {
+ XSSAPI xssAPI = new XSSAPIImpl();
+ return xssAPI.encodeForHTML(source);
+ }
+
+ /**
+ * Use to encapsulate new-style (XSSAPI-based) encoding for HTML attribute values.
+ *
+ * @param source the string to be encoded
+ * @return the encoded string
+ */
+ public static String encodeForHTMLAttr(String source) {
+ XSSAPI xssAPI = new XSSAPIImpl();
+ return xssAPI.encodeForHTMLAttr(source);
+ }
+
+ /**
+ * Use to encapsulate new-style (XSSAPI-based) encoding for XML element content.
+ *
+ * @param source the string to be encoded
+ * @return the encoded string
+ */
+ public static String encodeForXML(String source) {
+ XSSAPI xssAPI = new XSSAPIImpl();
+ return xssAPI.encodeForXML(source);
+ }
+
+ /**
+ * Use to encapsulate new-style (XSSAPI-based) encoding for XML attribute values.
+ *
+ * @param source the string to be encoded
+ * @return the encoded string
+ */
+ public static String encodeForXMLAttr(String source) {
+ XSSAPI xssAPI = new XSSAPIImpl();
+ return xssAPI.encodeForXMLAttr(source);
+ }
+
+ /**
+ * Use to encapsulate new-style (XSSAPI-based) encoding for JavaScript strings.
+ *
+ * @param source the string to be encoded
+ * @return the encoded string
+ */
+ public static String encodeForJSString(String source) {
+ XSSAPI xssAPI = new XSSAPIImpl();
+ return xssAPI.encodeForJSString(source);
+ }
+
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfig.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfig.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfig.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.config;
+
+/**
+ * Allows saving and restoring an instance configuration.
+ * Implementations define the behaviour of save() and restore()
+ */
+public interface InstanceConfig {
+
+ /**
+ * Saves the current status of the configuration
+ *
+ * @return this
+ * @throws InstanceConfigException if saving the configuration fails
+ * @throws InterruptedException if interrupted
+ */
+ public InstanceConfig save() throws InstanceConfigException, InterruptedException;
+
+ /**
+ * Restores the saved status of the configuration
+ *
+ * @return this
+ * @throws InstanceConfigException if restoring the configuration fails
+ * @throws InterruptedException if interrupted
+ */
+ public InstanceConfig restore() throws InstanceConfigException, InterruptedException;
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfigCache.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfigCache.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfigCache.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.config;
+
+import java.util.Collection;
+
+/**
+ * A cache for different {@link InstanceConfig} objects
+ */
+public interface InstanceConfigCache extends InstanceConfig, Collection<InstanceConfig> {
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfigException.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfigException.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/InstanceConfigException.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.config;
+
+public class InstanceConfigException extends Exception {
+
+ public InstanceConfigException(Exception e) {
+ super(e);
+ }
+
+ public InstanceConfigException() {
+ }
+
+ public InstanceConfigException(String message) {
+ super(message);
+ }
+
+ public InstanceConfigException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InstanceConfigException(Throwable cause) {
+ super(cause);
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/EmptyInstanceConfig.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/EmptyInstanceConfig.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/EmptyInstanceConfig.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.config.impl;
+
+import org.apache.sling.testing.clients.util.config.InstanceConfig;
+import org.apache.sling.testing.clients.util.config.InstanceConfigException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EmptyInstanceConfig implements InstanceConfig {
+ private static final Logger LOG = LoggerFactory.getLogger(EmptyInstanceConfig.class);
+
+ public InstanceConfig save() throws InstanceConfigException {
+ LOG.debug("Saved nothing");
+ return this;
+ }
+
+ public InstanceConfig restore() throws InstanceConfigException {
+ LOG.debug("Restored nothing");
+ return this;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/InstanceConfigCacheImpl.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/InstanceConfigCacheImpl.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/InstanceConfigCacheImpl.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.config.impl;
+
+import org.apache.sling.testing.clients.util.config.InstanceConfig;
+import org.apache.sling.testing.clients.util.config.InstanceConfigCache;
+import org.apache.sling.testing.clients.util.config.InstanceConfigException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public class InstanceConfigCacheImpl implements InstanceConfigCache {
+ List<InstanceConfig> configs;
+
+ public InstanceConfigCacheImpl(List<InstanceConfig> configs) {
+ this.configs = configs;
+ }
+
+ public InstanceConfigCacheImpl() {
+ this.configs = new ArrayList<InstanceConfig>();
+ }
+
+ @Override
+ public int size() {
+ return configs.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return configs.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return configs.contains(o);
+ }
+
+ @Override
+ public Iterator<InstanceConfig> iterator() {
+ return configs.iterator();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return configs.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return configs.toArray(a);
+ }
+
+ @Override
+ public boolean add(InstanceConfig instanceConfig) {
+ return configs.add(instanceConfig);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return configs.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return configs.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends InstanceConfig> c) {
+ return configs.addAll(c);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ return configs.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ return configs.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ configs.clear();
+ }
+
+
+ @Override
+ public InstanceConfig save() throws InstanceConfigException, InterruptedException {
+ for (InstanceConfig ic : configs) {
+ ic.save();
+ }
+ return this;
+ }
+
+ @Override
+ public InstanceConfig restore() throws InstanceConfigException, InterruptedException {
+ for (InstanceConfig ic : configs) {
+ ic.restore();
+ }
+ return this;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/package-info.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/package-info.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/impl/package-info.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ */
+
+@Version("1.0.0")
+package org.apache.sling.testing.clients.util.config.impl;
+
+import org.osgi.annotation.versioning.Version;
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/config/package-info.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/config/package-info.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/config/package-info.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ */
+
+@Version("1.0.0")
+package org.apache.sling.testing.clients.util.config;
+
+import org.osgi.annotation.versioning.Version;
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/package-info.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/package-info.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/package-info.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ */
+
+@Version("2.0.0")
+package org.apache.sling.testing.clients.util;
+
+import org.osgi.annotation.versioning.Version;
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/AbstractPoller.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/AbstractPoller.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/AbstractPoller.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.poller;
+
+/**
+ * @deprecated use {@link Polling} instead.
+ * @see Polling for a better way to implement polling
+ */
+@Deprecated
+public abstract class AbstractPoller implements Poller {
+
+ private final long waitInterval;
+ private final long waitCount;
+
+ /**
+ * Convenience method to execute a generic call and do polling until a condition is met
+ * The user must implement the {@link Poller#call()} and {@link Poller#condition()} methods
+ * @param waitInterval Number of milliseconds to wait between polls
+ * @param waitCount Number of wait intervals
+ */
+ public AbstractPoller(long waitInterval, long waitCount) {
+ this.waitInterval = waitInterval;
+ this.waitCount = waitCount;
+ }
+
+ /**
+ * Calls the {@link Poller#call()} once and then calls {@link Poller#condition()} until it returns true
+ * The method waits AbstractPoller#waitInterval milliseconds between calls to {@link Poller#condition()}
+ * A maximum of AbstractPoller#waitCount intervals are checked
+ * @return true if the condition is met after waiting a maximum of AbstractPoller#waitCount intervals, false otherwise
+ * @throws InterruptedException to mark this operation as "waiting"
+ */
+ public boolean callAndWait() throws InterruptedException {
+ if (!call()) return false;
+ for (int i=0; i<waitCount; i++) {
+ if (condition()) return true;
+ Thread.sleep(waitInterval);
+ }
+ return false;
+ }
+
+ /**
+ * Calls the @see: Poller#call() and then calls {@link Poller#condition()} until it returns true
+ * The Poller#call() method is called in each wait interval, before the Poller#condition().
+ * The method waits AbstractPoller#waitInterval milliseconds between calls to {@link Poller#condition()}
+ * A maximum of AbstractPoller#waitCount intervals are checked
+ * @return true if the condition is met after waiting a maximum of AbstractPoller#waitCount intervals, false otherwise
+ * @throws InterruptedException to mark this operation as "waiting"
+ */
+ public boolean callUntilCondition() throws InterruptedException {
+ if (!call()) return false;
+ if (condition()) return true;
+ for (int i = 0; i < waitCount; i++) {
+ Thread.sleep(waitInterval);
+ if (!call()) return false;
+ if (condition()) return true;
+ }
+ return false;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.sling.testing.clients.util.poller;
+
+import org.apache.sling.testing.clients.AbstractSlingClient;
+import org.apache.sling.testing.clients.ClientException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Allows polling for a resource
+ */
+@Deprecated
+public class PathPoller extends AbstractPoller {
+ private static final Logger LOG = LoggerFactory.getLogger(PathPoller.class);
+ private final AbstractSlingClient client;
+ private final String path;
+ private final int[] expectedStatus;
+ private Exception exception;
+
+ public PathPoller(AbstractSlingClient client, String path, long waitInterval, long waitCount, int... expectedStatus) {
+ super(waitInterval, waitCount);
+ this.client = client;
+ this.path = path;
+ if (null == expectedStatus || expectedStatus.length == 0) {
+ this.expectedStatus = new int[]{200};
+ } else {
+ this.expectedStatus = expectedStatus;
+ }
+ }
+
+
+ @Override
+ public boolean call() {
+ return true;
+ }
+
+ @Override
+ public boolean condition() {
+ try {
+ client.doGet(path, expectedStatus);
+ } catch (ClientException e) {
+ LOG.warn("Get on {} failed: {}", path, e);
+ this.exception = e;
+ return false;
+ }
+ return true;
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/Poller.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/Poller.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/Poller.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.poller;
+
+/**
+ * Abstract Poller interface.
+ * Provides simple methods to implement custom pollers
+ *
+ * @deprecated use {@link Polling} instead.
+ * @see Polling for a better way to implement polling
+ */
+@Deprecated
+public interface Poller {
+ boolean call();
+ boolean condition();
+ boolean callAndWait() throws InterruptedException;
+ boolean callUntilCondition() throws InterruptedException;
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/Polling.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/Polling.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/Polling.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing.clients.util.poller;
+
+import org.apache.sling.testing.timeouts.TimeoutsProvider;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Helper for repeating a call until it returns true, with timeout capabilities.
+ * Subclasses should override the {@link #call()} method.
+ * Can be used with lambda expressions, using the constructor {@link #Polling(Callable c)}.
+ *
+ * @since 1.1.0
+ */
+public class Polling implements Callable<Boolean> {
+
+ /**
+ * Optional object to be used by the default implementation of call()
+ */
+ protected final Callable<Boolean> c;
+
+ /**
+ * Holder for the last exception thrown by call(), to be used for logging
+ */
+ protected Exception lastException;
+
+ /**
+ * Counter for total waiting time
+ */
+ protected long waited;
+
+ /**
+ * Default constructor to be used in subclasses that override the {@link #call()} method.
+ * Should not be used directly on {@code Polling} instances, but only on extended classes.
+ * If used directly to get a {@code Polling} instance, executing {@link #poll(long timeout, long delay)}
+ * will be equivalent to {@code Thread.sleep(timeout)}
+ */
+ public Polling() {
+ this.c = null;
+ this.lastException = null;
+ this.waited = 0;
+ }
+
+ /**
+ * Creates a new instance that uses the {@code Callable} parameter for polling
+ *
+ * @param c object whose {@code call()} method will be polled
+ */
+ public Polling(Callable<Boolean> c) {
+ this.c = c;
+ this.lastException = null;
+ this.waited = 0;
+ }
+
+ /**
+ * <p>Method to be called by {@link #poll(long timeout, long delay)}, potentially multiple times,
+ * until it returns true or timeout is reached.<br>
+ * Subclasses can override it to change the check accordingly. The method should return true
+ * only when the call was successful.<br>
+ * It can return false or throw any {@code Exception} to make the poller try again later.</p>
+ *
+ * <p>The default implementation delegates the call to the {@code Callable c} instance.</p>
+ *
+ * @return {@code true} to end polling
+ * @throws Exception if unable to compute a result
+ */
+ @Override
+ public Boolean call() throws Exception {
+ if (c != null) {
+ return c.call();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * <p>Tries to execute {@link #call()} until it returns true or until {@code timeout} is reached.
+ * Between retries, it waits using {@code Thread.sleep(delay)}. It means the retry is not at a fixed pace,
+ * but depends on the execution time of the call itself.</p>
+ * <p>The method guarantees that the call() will be executed at least once. If the timeout is 0 or less, then
+ * call() will be executed exactly once.</p>
+ * <p>The timeout is adjusted using {@link TimeoutsProvider} so the final value can be changed using the
+ * system property: {@value org.apache.sling.testing.timeouts.TimeoutsProvider#PROP_TIMEOUT_MULTIPLIER}</p>
+ *
+ * @param timeout max total execution time, in milliseconds
+ * @param delay time to wait between calls, in milliseconds
+ *
+ * @throws TimeoutException if {@code timeout} was reached
+ * @throws InterruptedException if the thread was interrupted while sleeping; caller should throw it further
+ */
+ public void poll(long timeout, long delay) throws TimeoutException, InterruptedException {
+ long start = System.currentTimeMillis();
+ long effectiveTimeout = TimeoutsProvider.getInstance().getTimeout(timeout);
+
+ do {
+ try {
+ boolean success = call();
+ if (success) {
+ waited = System.currentTimeMillis() - start;
+ return;
+ }
+ } catch (InterruptedException e) {
+ throw e; // Never inhibit InterruptedException
+ } catch (Exception e) {
+ lastException = e;
+ }
+ Thread.sleep(delay);
+ } while (System.currentTimeMillis() < start + effectiveTimeout);
+
+ waited = System.currentTimeMillis() - start;
+ throw new TimeoutException(String.format(message(), effectiveTimeout, delay) +
+ " Last exception was: " + lastException);
+ }
+
+ public long getWaited() {
+ return waited;
+ }
+
+ /**
+ * Returns the string to be used in the {@code TimeoutException}, if needed.
+ * The string is passed to {@code String.format(message(), timeout, delay)}, so it can be a format
+ * including {@code %1$d} and {@code %2$d}. The field {@code lastException} is also available for logging
+ *
+ * @return the format string
+ */
+ protected String message() {
+ return "Call failed to return true in %1$d ms.";
+ }
+
+ /**
+ * Return the last exception while polling or {null}
+ * @return
+ */
+ public Exception getLastException() {
+ return lastException;
+ }
+}
Added: release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/package-info.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/package-info.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/clients/util/poller/package-info.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ */
+
+@Version("1.3.0")
+package org.apache.sling.testing.clients.util.poller;
+
+import org.osgi.annotation.versioning.Version;
Added: release/sling/src/main/java/org/apache/sling/testing/timeouts/TimeoutsProvider.java
==============================================================================
--- release/sling/src/main/java/org/apache/sling/testing/timeouts/TimeoutsProvider.java (added)
+++ release/sling/src/main/java/org/apache/sling/testing/timeouts/TimeoutsProvider.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.sling.testing.timeouts;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Return timeout values that can be multiplied by a configurable
+ * factor. Useful to cope with slower integration testing systems:
+ * use timeout constants in your code that work for usual development
+ * systems, and set a multiplier when running on a slower system.
+ */
+public class TimeoutsProvider {
+ private static final Logger log = LoggerFactory.getLogger(TimeoutsProvider.class);
+ public static final String PROP_TIMEOUT_MULTIPLIER = "sling.testing.timeout.multiplier";
+ private static float timeoutFactor = -1;
+ private static TimeoutsProvider INSTANCE;
+
+ private TimeoutsProvider() {
+ if(timeoutFactor < 0) {
+ timeoutFactor = 1;
+ final String str = System.getProperty(PROP_TIMEOUT_MULTIPLIER);
+ if(str != null) {
+ try {
+ timeoutFactor = Float.valueOf(str.trim());
+ log.info("Timeout factor set to {} from system property {}",
+ timeoutFactor, PROP_TIMEOUT_MULTIPLIER);
+ } catch(NumberFormatException nfe) {
+ throw new IllegalStateException("Invalid timeout factor: " + PROP_TIMEOUT_MULTIPLIER + "=" + str);
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * @return the instance of the singleton
+ */
+ public static TimeoutsProvider getInstance() {
+ if(INSTANCE == null) {
+ synchronized (TimeoutsProvider.class) {
+ INSTANCE = new TimeoutsProvider();
+ }
+ }
+ return INSTANCE;
+ }
+
+ /**
+ *
+ * @param nomimalValue base number to be multiplied internally with the factor
+ * @return the new timeout
+ */
+ public long getTimeout(long nomimalValue) {
+ final long result = (long)(nomimalValue * timeoutFactor);
+ return result;
+ }
+
+ /**
+ *
+ * @param nomimalValue base number to be multiplied internally with the factor
+ * @return the new timeout
+ */
+ public int getTimeout(int nomimalValue) {
+ final int result = (int)(nomimalValue * timeoutFactor);
+ return result;
+ }
+
+ /**
+ * Get timeout from a system property, with default value
+ * @param systemPropertyName the name of the system prop from which to get the timeout
+ * @param defaultNominalValue default value in case the property does not exist
+ * @return the timeout
+ */
+ public int getTimeout(String systemPropertyName, int defaultNominalValue) {
+ int result = defaultNominalValue;
+ final String str = System.getProperty(systemPropertyName);
+ if(str != null) {
+ result = Integer.parseInt(str);
+ }
+ return getTimeout(result);
+ }
+}
Added: release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetPathTest.java
==============================================================================
--- release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetPathTest.java (added)
+++ release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetPathTest.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing;
+
+import org.apache.sling.testing.clients.ClientException;
+import org.apache.sling.testing.clients.SlingClient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class AbstractSlingClientGetPathTest {
+
+ @Parameterized.Parameters(name = "{index} - serverUrl: {0}, input: {1}, expected: {2}")
+ public static Collection<String[]> data() {
+ return Arrays.asList(new String[][] {
+ {"http://HOST", "http://HOST/page.html", "/page.html"},
+ {"http://HOST", "http://HOST/my/page.html", "/my/page.html"},
+ {"http://HOST", "http://HOST/my/", "/my/"},
+ {"http://HOST", "http://HOST/my", "/my"},
+ {"http://HOST", "http://HOST/", "/"},
+ {"http://HOST", "http://HOST", "/"},
+ {"http://HOST", "/page.html", "/page.html"},
+ {"http://HOST", "/my/page.html", "/my/page.html"},
+ {"http://HOST", "/my/", "/my/"},
+ {"http://HOST", "/", "/"},
+ {"http://HOST", "page.html", "/page.html"},
+ {"http://HOST", "my/page.html", "/my/page.html"},
+ {"http://HOST", "my", "/my"},
+ {"http://HOST", "", "/"},
+
+ {"http://HOST:4502", "http://HOST:4502/page.html", "/page.html"},
+ {"http://HOST:4502", "http://HOST:4502/my/page.html", "/my/page.html"},
+ {"http://HOST:4502", "http://HOST:4502/my/", "/my/"},
+ {"http://HOST:4502", "http://HOST:4502/my", "/my"},
+ {"http://HOST:4502", "http://HOST:4502/", "/"},
+ {"http://HOST:4502", "http://HOST:4502", "/"},
+ {"http://HOST:4502", "/page.html", "/page.html"},
+ {"http://HOST:4502", "/my/page.html", "/my/page.html"},
+ {"http://HOST:4502", "/my/", "/my/"},
+ {"http://HOST:4502", "/my", "/my"},
+ {"http://HOST:4502", "/", "/"},
+ {"http://HOST:4502", "page.html", "/page.html"},
+ {"http://HOST:4502", "my/page.html", "/my/page.html"},
+ {"http://HOST:4502", "my/", "/my/"},
+ {"http://HOST:4502", "my", "/my"},
+ {"http://HOST:4502", "", "/"},
+
+ {"http://HOST:4502/", "http://HOST:4502/page.html", "/page.html"},
+ {"http://HOST:4502/", "http://HOST:4502/my/page.html", "/my/page.html"},
+ {"http://HOST:4502/", "http://HOST:4502/my/", "/my/"},
+ {"http://HOST:4502/", "http://HOST:4502/my", "/my"},
+ {"http://HOST:4502/", "http://HOST:4502/", "/"},
+ {"http://HOST:4502/", "http://HOST:4502", "/"},
+ {"http://HOST:4502/", "/page.html", "/page.html"},
+ {"http://HOST:4502/", "/my/page.html", "/my/page.html"},
+ {"http://HOST:4502/", "/my/", "/my/"},
+ {"http://HOST:4502/", "/my", "/my"},
+ {"http://HOST:4502/", "/", "/"},
+ {"http://HOST:4502/", "page.html", "/page.html"},
+ {"http://HOST:4502/", "my/page.html", "/my/page.html"},
+ {"http://HOST:4502/", "my/", "/my/"},
+ {"http://HOST:4502/", "my", "/my"},
+ {"http://HOST:4502/", "", "/"},
+
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX/page.html", "/page.html"},
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX/my/page.html", "/my/page.html"},
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX/my/", "/my/"},
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX/my", "/my"},
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX/", "/"},
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX", "/"},
+ {"http://HOST:4502/CTX", "/CTX", "/"},
+ {"http://HOST:4502/CTX", "/CTX/", "/"},
+ {"http://HOST:4502/CTX", "/CTX/page.html", "/page.html"},
+ {"http://HOST:4502/CTX", "/page.html", "/page.html"},
+ {"http://HOST:4502/CTX", "/my/page.html", "/my/page.html"},
+ {"http://HOST:4502/CTX", "/my/", "/my/"},
+ {"http://HOST:4502/CTX", "/my", "/my"},
+ {"http://HOST:4502/CTX", "/", "/"},
+ {"http://HOST:4502/CTX", "CTX", "/"},
+ {"http://HOST:4502/CTX", "CTX/", "/"},
+ {"http://HOST:4502/CTX", "CTX/page.html", "/page.html"},
+ {"http://HOST:4502/CTX", "page.html", "/page.html"},
+ {"http://HOST:4502/CTX", "my/page.html", "/my/page.html"},
+ {"http://HOST:4502/CTX", "my/", "/my/"},
+ {"http://HOST:4502/CTX", "my", "/my"},
+ {"http://HOST:4502/CTX", "", "/"},
+
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/page.html", "/page.html"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/my/page.html", "/my/page.html"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/my/", "/my/"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/my", "/my"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/", "/"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX", "/"},
+
+ {"http://HOST:4502/CTX/", "/CTX", "/"},
+ {"http://HOST:4502/CTX/", "/CTX/", "/"},
+ {"http://HOST:4502/CTX/", "/CTX/page.html", "/page.html"},
+ {"http://HOST:4502/CTX/", "/page.html", "/page.html"},
+ {"http://HOST:4502/CTX/", "/my/page.html", "/my/page.html"},
+ {"http://HOST:4502/CTX/", "/my/", "/my/"},
+ {"http://HOST:4502/CTX/", "/my", "/my"},
+ {"http://HOST:4502/CTX/", "/", "/"},
+ {"http://HOST:4502/CTX/", "CTX", "/"},
+ {"http://HOST:4502/CTX/", "CTX/", "/"},
+ {"http://HOST:4502/CTX/", "CTX/page.html", "/page.html"},
+ {"http://HOST:4502/CTX/", "page.html", "/page.html"},
+ {"http://HOST:4502/CTX/", "my/page.html", "/my/page.html"},
+ {"http://HOST:4502/CTX/", "my/", "/my/"},
+ {"http://HOST:4502/CTX/", "my", "/my"},
+ {"http://HOST:4502/CTX/", "", "/"},
+
+ {"http://HOST:4502/CTX/", "/CTX/?param=value", "/?param=value"},
+ {"http://HOST:4502/CTX/", "/CTX/page.html?param=value", "/page.html?param=value"},
+ {"http://HOST:4502/CTX/", "/page.html?param=value", "/page.html?param=value"},
+ {"http://HOST:4502/CTX/", "/my/page.html?param=value", "/my/page.html?param=value"},
+ {"http://HOST:4502/CTX/", "/my/?param=value", "/my/?param=value"},
+ {"http://HOST:4502/CTX/", "/my?param=value", "/my?param=value"},
+ {"http://HOST:4502/CTX/", "CTX/?param=value", "/?param=value"},
+ {"http://HOST:4502/CTX/", "CTX/page.html?param=value", "/page.html?param=value"},
+ {"http://HOST:4502/CTX/", "page.html?param=value", "/page.html?param=value"},
+ {"http://HOST:4502/CTX/", "my/page.html?param=value", "/my/page.html?param=value"},
+ {"http://HOST:4502/CTX/", "my/?param=value", "/my/?param=value"},
+ {"http://HOST:4502/CTX/", "my?param=value", "/my?param=value"},
+
+ {"http://HOST:4502/CTX/", "http://www.google.com", "http://www.google.com"},
+ });
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public String serverUrl;
+
+ @Parameterized.Parameter(value = 1)
+ public String inputUri;
+
+ @Parameterized.Parameter(value = 2)
+ public String expectedPath;
+
+ @Test
+ public void testGetPath() throws ClientException, URISyntaxException {
+ SlingClient c = new SlingClient(URI.create(serverUrl), "USER", "PWD");
+ assertEquals(URI.create(expectedPath), c.getPath(inputUri));
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
Added: release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetServerUrlTest.java
==============================================================================
--- release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetServerUrlTest.java (added)
+++ release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetServerUrlTest.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing;
+
+import org.apache.sling.testing.clients.ClientException;
+import org.apache.sling.testing.clients.SlingClient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class AbstractSlingClientGetServerUrlTest {
+
+ @Parameterized.Parameters(name = "{index} - serverUrl: {0}, path: {1}, expected: {2}")
+ public static Collection<String[]> data() {
+ return Arrays.asList(new String[][] {
+ {"http://HOST", "http://HOST/"},
+ {"http://HOST:4502", "http://HOST:4502/"},
+ {"http://HOST:4502/", "http://HOST:4502/"},
+ {"http://HOST:4502/CTX", "http://HOST:4502/CTX/"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/"},
+ });
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public String serverUrl;
+
+ @Parameterized.Parameter(value = 1)
+ public String expectedUrl;
+
+ @Test
+ public void testGetUrl() throws ClientException {
+ SlingClient c = new SlingClient(URI.create(serverUrl), "USER", "PWD");
+ assertEquals("", URI.create(expectedUrl), c.getUrl());
+ }
+}
Added: release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetUrlTest.java
==============================================================================
--- release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetUrlTest.java (added)
+++ release/sling/src/test/java/org/apache/sling/testing/AbstractSlingClientGetUrlTest.java Thu Apr 9 13:50:42 2020
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * 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.apache.sling.testing;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.sling.testing.clients.ClientException;
+import org.apache.sling.testing.clients.SlingClient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class AbstractSlingClientGetUrlTest {
+
+ @Parameterized.Parameters(name = "{index} - serverUrl: {0}, path: {1}, expected: {2}")
+ public static Collection<String[]> data() {
+ return Arrays.asList(new String[][] {
+ // Server URL with no port
+ {"http://HOST", "/page.html", "http://HOST/page.html"},
+ {"http://HOST", "/my/page.html", "http://HOST/my/page.html"},
+ {"http://HOST", "/my/", "http://HOST/my/"},
+ {"http://HOST", "/my", "http://HOST/my"},
+ {"http://HOST", "/", "http://HOST/"},
+
+ {"http://HOST", "page.html", "http://HOST/page.html"},
+ {"http://HOST", "my/page.html", "http://HOST/my/page.html"},
+ {"http://HOST", "my/", "http://HOST/my/"},
+ {"http://HOST", "my", "http://HOST/my"},
+ {"http://HOST", "", "http://HOST/"},
+
+ // Server URL with with port
+ {"http://HOST:4502", "/page.html", "http://HOST:4502/page.html"},
+ {"http://HOST:4502", "/my/page.html", "http://HOST:4502/my/page.html"},
+ {"http://HOST:4502", "/my/", "http://HOST:4502/my/"},
+ {"http://HOST:4502", "/my", "http://HOST:4502/my"},
+ {"http://HOST:4502", "/", "http://HOST:4502/"},
+
+ {"http://HOST:4502", "page.html", "http://HOST:4502/page.html"},
+ {"http://HOST:4502", "my/page.html", "http://HOST:4502/my/page.html"},
+ {"http://HOST:4502", "my/", "http://HOST:4502/my/"},
+ {"http://HOST:4502", "my", "http://HOST:4502/my"},
+ {"http://HOST:4502", "", "http://HOST:4502/"},
+
+ // Server URL with with port and trailing slash
+ {"http://HOST:4502/", "/page.html", "http://HOST:4502/page.html"},
+ {"http://HOST:4502/", "/my/page.html", "http://HOST:4502/my/page.html"},
+ {"http://HOST:4502/", "/my/", "http://HOST:4502/my/"},
+ {"http://HOST:4502/", "/my", "http://HOST:4502/my"},
+ {"http://HOST:4502/", "/", "http://HOST:4502/"},
+
+ {"http://HOST:4502/", "page.html", "http://HOST:4502/page.html"},
+ {"http://HOST:4502/", "my/page.html", "http://HOST:4502/my/page.html"},
+ {"http://HOST:4502/", "my/", "http://HOST:4502/my/"},
+ {"http://HOST:4502/", "my", "http://HOST:4502/my"},
+ {"http://HOST:4502/", "", "http://HOST:4502/"},
+
+ // Server URL with with port and context path (no trailing slash)
+ {"http://HOST:4502/CTX", "/page.html", "http://HOST:4502/CTX/page.html"},
+ {"http://HOST:4502/CTX", "/my/page.html", "http://HOST:4502/CTX/my/page.html"},
+ {"http://HOST:4502/CTX", "/my/", "http://HOST:4502/CTX/my/"},
+ {"http://HOST:4502/CTX", "/my", "http://HOST:4502/CTX/my"},
+ {"http://HOST:4502/CTX", "/", "http://HOST:4502/CTX/"},
+
+ {"http://HOST:4502/CTX", "page.html", "http://HOST:4502/CTX/page.html"},
+ {"http://HOST:4502/CTX", "my/page.html", "http://HOST:4502/CTX/my/page.html"},
+ {"http://HOST:4502/CTX", "my/", "http://HOST:4502/CTX/my/"},
+ {"http://HOST:4502/CTX", "my", "http://HOST:4502/CTX/my"},
+ {"http://HOST:4502/CTX", "", "http://HOST:4502/CTX/"},
+
+ // Server URL with with port and context path and trailing slash
+ {"http://HOST:4502/CTX/", "/page.html", "http://HOST:4502/CTX/page.html"},
+ {"http://HOST:4502/CTX/", "/my/page.html", "http://HOST:4502/CTX/my/page.html"},
+ {"http://HOST:4502/CTX/", "/my/", "http://HOST:4502/CTX/my/"},
+ {"http://HOST:4502/CTX/", "/my", "http://HOST:4502/CTX/my"},
+ {"http://HOST:4502/CTX/", "/", "http://HOST:4502/CTX/"},
+
+ {"http://HOST:4502/CTX/", "page.html", "http://HOST:4502/CTX/page.html"},
+ {"http://HOST:4502/CTX/", "my/page.html", "http://HOST:4502/CTX/my/page.html"},
+ {"http://HOST:4502/CTX/", "my/", "http://HOST:4502/CTX/my/"},
+ {"http://HOST:4502/CTX/", "my", "http://HOST:4502/CTX/my"},
+ {"http://HOST:4502/CTX/", "", "http://HOST:4502/CTX/"},
+
+ // External URLs
+ {"http://HOST:4502/CTX/", "http://www.google.com", "http://www.google.com"},
+ {"http://HOST:4502/CTX/", "http://HOST:4502/CTX/my/page.html", "http://HOST:4502/CTX/my/page.html"},
+
+ // URL encoding of the path
+ {"http://HOST:4502/CTX/", "!@*()'~ #$%^&{}[]|\\<>?\"`", "http://host:4502/CTX/!@*()'~%20%23$%25%5E&%7B%7D%5B%5D%7C%5C%3C%3E%3F%22%60"},
+ });
+ }
+
+
+ private static final List<NameValuePair> TEST_PARAMETERS = Arrays.<NameValuePair>asList(new BasicNameValuePair("key", "value"));
+ private static final String STRING_TEST_PARAMETERS = "key=value";
+
+ @Parameterized.Parameter(value = 0)
+ public String serverUrl;
+
+ @Parameterized.Parameter(value = 1)
+ public String inputPath;
+
+ @Parameterized.Parameter(value = 2)
+ public String expectedUrl;
+
+ @Test
+ public void testGetUrlWithParam() throws ClientException {
+ SlingClient c = new SlingClient(URI.create(serverUrl), "USER", "PWD");
+ assertEquals("", URI.create(expectedUrl), c.getUrl(inputPath));
+ assertEquals(URI.create(expectedUrl), c.getUrl(inputPath, null));
+ assertEquals(URI.create(expectedUrl + "?"), c.getUrl(inputPath, new ArrayList<NameValuePair>()));
+ assertEquals(URI.create(expectedUrl + "?" + STRING_TEST_PARAMETERS), c.getUrl(inputPath, TEST_PARAMETERS));
+ }
+}