You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/10/20 14:44:43 UTC

[sling-org-apache-sling-testing-clients] 24/37: SLING-6853 Fixed incomplete patch.

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-clients.git

commit 8de4abdfdd9c433a13634a963060eaf616b053b2
Author: Andrei Dulvac <du...@apache.org>
AuthorDate: Tue May 16 15:03:12 2017 +0000

    SLING-6853 Fixed incomplete patch.
    
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1795326 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/testing/clients/util/poller/Polling.java | 131 +++++++++++++++
 .../sling/testing/clients/HttpServerRule.java      |  84 ++++++++++
 .../testing/clients/SlingClientDoGetJsonTest.java  |  71 ++++++++
 .../testing/clients/SlingClientWaitExistsTest.java |  93 +++++++++++
 .../testing/clients/util/poller/PollingTest.java   | 179 +++++++++++++++++++++
 5 files changed, 558 insertions(+)

diff --git a/src/main/java/org/apache/sling/testing/clients/util/poller/Polling.java b/src/main/java/org/apache/sling/testing/clients/util/poller/Polling.java
new file mode 100644
index 0000000..faef6b2
--- /dev/null
+++ b/src/main/java/org/apache/sling/testing/clients/util/poller/Polling.java
@@ -0,0 +1,131 @@
+/*
+ * 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;
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * <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) {
+                    return;
+                }
+                Thread.sleep(delay);
+            } catch (InterruptedException e) {
+                throw e;
+            } catch (Exception e) {
+                lastException = e;
+            }
+        } while (System.currentTimeMillis() < start + effectiveTimeout);
+
+        throw new TimeoutException(String.format(message(), effectiveTimeout, delay));
+    }
+
+    /**
+     * 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$} and {@code %2$}. 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. Last exception was: " + lastException;
+    }
+}
diff --git a/src/test/java/org/apache/sling/testing/clients/HttpServerRule.java b/src/test/java/org/apache/sling/testing/clients/HttpServerRule.java
new file mode 100644
index 0000000..926f79b
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/clients/HttpServerRule.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.HttpHost;
+import org.apache.http.client.utils.URIUtils;
+import org.apache.http.config.SocketConfig;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
+import org.apache.http.localserver.SSLTestContexts;
+import org.junit.rules.ExternalResource;
+
+/** JUnit Rule that starts an HTTP server */
+public class HttpServerRule extends ExternalResource {
+    public static final String ORIGIN = "TEST/1.1";
+    private HttpServer server;
+    private HttpHost host;
+    private URI uri;
+
+    protected ServerBootstrap serverBootstrap;
+
+    public static enum ProtocolScheme {
+        http,
+        https;
+        private ProtocolScheme() {
+        }
+    }
+
+    protected final ProtocolScheme protocolScheme;
+
+    public HttpServerRule() {
+        this(ProtocolScheme.http);
+    }
+
+    public HttpServerRule(ProtocolScheme protocolScheme) {
+        this.protocolScheme = protocolScheme;
+    }
+
+    @Override
+    protected void after() {
+        server.shutdown(-1, TimeUnit.SECONDS);
+    }
+
+    @Override
+    protected void before() throws Throwable {
+        final SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(5000).build();
+        serverBootstrap = ServerBootstrap.bootstrap().setSocketConfig(socketConfig).setServerInfo(ORIGIN);
+        if(ProtocolScheme.https.equals(protocolScheme)) {
+            serverBootstrap.setSslContext(SSLTestContexts.createServerSSLContext());
+        }
+        registerHandlers();
+        server = serverBootstrap.create();
+        server.start();
+        host = new HttpHost("127.0.0.1", server.getLocalPort(), protocolScheme.name());
+        uri = URIUtils.rewriteURI(new URI("/"), host);
+    }
+
+    protected void registerHandlers() throws IOException {
+    }
+
+    public URI getURI() {
+        return uri;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/testing/clients/SlingClientDoGetJsonTest.java b/src/test/java/org/apache/sling/testing/clients/SlingClientDoGetJsonTest.java
new file mode 100644
index 0000000..6eeba23
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/clients/SlingClientDoGetJsonTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.codehaus.jackson.JsonNode;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class SlingClientDoGetJsonTest {
+    private static final String GET_JSON_PATH = "/test/json/resource";
+    private static final String JSON_RESPONSE = "{\"jcr:primaryType\":\"cq:Page\",\"jcr:createdBy\":\"admin-json\"}";
+    private static final String JSON_INF_RESPONSE = "{\"jcr:primaryType\":\"cq:Page\",\"jcr:createdBy\":\"admin-infinity\"}";
+
+    @ClassRule
+    public static HttpServerRule httpServer = new HttpServerRule() {
+        @Override
+        protected void registerHandlers() throws IOException {
+            serverBootstrap.registerHandler(GET_JSON_PATH + ".1.json", new HttpRequestHandler() {
+                @Override
+                public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+                    response.setEntity(new StringEntity(JSON_RESPONSE));
+                }
+            });
+
+            serverBootstrap.registerHandler(GET_JSON_PATH + ".infinity.json", new HttpRequestHandler() {
+                @Override
+                public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+                    response.setEntity(new StringEntity(JSON_INF_RESPONSE));
+                }
+            });
+        }
+    };
+
+    @Test
+    public void testDoGetJson() throws Exception {
+        SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass");
+        JsonNode res = c.doGetJson(GET_JSON_PATH, 1, 200);
+        assertEquals("admin-json", res.get("jcr:createdBy").getTextValue());
+    }
+
+    @Test
+    public void testDoGetJsonInfinity() throws Exception {
+        SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass");
+        JsonNode res = c.doGetJson(GET_JSON_PATH, -1, 200);
+        assertEquals("admin-infinity", res.get("jcr:createdBy").getTextValue());
+    }
+}
diff --git a/src/test/java/org/apache/sling/testing/clients/SlingClientWaitExistsTest.java b/src/test/java/org/apache/sling/testing/clients/SlingClientWaitExistsTest.java
new file mode 100644
index 0000000..31b67bf
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/clients/SlingClientWaitExistsTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import static org.junit.Assert.*;
+
+public class SlingClientWaitExistsTest {
+    private static final String GET_WAIT_PATH = "/test/wait/resource";
+    private static final String OK_RESPONSE = "TEST_OK";
+    private static final String NOK_RESPONSE = "TEST_OK";
+
+    private static int waitCount = 4; // truly randomly chosen by typing with the eyes closed
+    private static int callCount = 0;
+
+    @ClassRule
+    public static HttpServerRule httpServer = new HttpServerRule() {
+        @Override
+        protected void registerHandlers() throws IOException {
+            serverBootstrap.registerHandler(GET_WAIT_PATH + ".json", new HttpRequestHandler() {
+                @Override
+                public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+                    callCount++;
+                    if (callCount == waitCount) {
+                        response.setEntity(new StringEntity(OK_RESPONSE));
+                    } else {
+                        response.setEntity(new StringEntity(NOK_RESPONSE));
+                        response.setStatusCode(404);
+                    }
+                }
+            });
+        }
+    };
+
+    @Test
+    public void testWaitExists() throws Exception {
+        callCount = 0;  // reset counter
+        waitCount = 3;  // less than timeout
+        SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass");
+        c.waitExists(GET_WAIT_PATH, 500, 10);
+        assertEquals(waitCount, callCount);
+    }
+
+    @Test
+    public void testWaitExistsTimeout() throws Exception {
+        callCount = 0;  // reset counter
+        waitCount = 40;  // to be sure we reach timeout
+        SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass");
+        try {
+            c.waitExists(GET_WAIT_PATH, 200, 10);
+        } catch (TimeoutException e ) {
+            assertTrue("call was executed only " + callCount + " times", callCount > 3);
+            return;
+        }
+
+        fail("waitExists did not timeout");
+    }
+
+    @Test
+    public void testWaitExistsOnce() throws Exception {
+        callCount = 0;  // reset counter
+        waitCount = 1;  // less than timeout
+        SlingClient c = new SlingClient(httpServer.getURI(), "user", "pass");
+        c.waitExists(GET_WAIT_PATH, -1, 10);
+        assertEquals(1, callCount);
+    }
+}
diff --git a/src/test/java/org/apache/sling/testing/clients/util/poller/PollingTest.java b/src/test/java/org/apache/sling/testing/clients/util/poller/PollingTest.java
new file mode 100644
index 0000000..15994ed
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/clients/util/poller/PollingTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.commons.lang3.mutable.MutableBoolean;
+import org.apache.commons.lang3.mutable.MutableInt;
+import org.junit.Test;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeoutException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class PollingTest {
+    @Test
+    public void testCallOnce() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        Polling p = new Polling() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                return true;
+            }
+        };
+        p.poll(500, 10);
+
+        assertEquals(1, callCount.intValue());
+    }
+
+    @Test
+    public void testCallTwice() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        final MutableBoolean called = new MutableBoolean(false);
+        Polling p = new Polling() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                boolean b = called.booleanValue();
+                called.setTrue();
+                return b;
+            }
+        };
+        p.poll(500, 10);
+
+        assertEquals(2, callCount.intValue());
+    }
+
+    @Test
+    public void testCallTimeout() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        Polling p = new Polling() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                return false;
+            }
+        };
+
+        try {
+            p.poll(100, 10);
+        } catch (TimeoutException e ) {
+            assertTrue("Expected to execute call() at least 4 times, got instead only " + callCount.intValue() + " calls",
+                    callCount.intValue() > 5);
+            return;
+        }
+
+        fail("Did not reach timeout");
+    }
+
+    @Test
+    public void testNegativeTimeout() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        Polling p = new Polling() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                return true;
+            }
+        };
+        p.poll(-1, 10);
+
+        assertEquals(1, callCount.intValue());
+    }
+
+    //
+    // Tests with Callable
+    //
+
+    @Test
+    public void testCallableOnce() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        final MutableBoolean called = new MutableBoolean(false);
+        Polling p = new Polling(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                return true;
+            }
+        });
+        p.poll(500, 10);
+
+        assertEquals(1, callCount.intValue());
+    }
+
+    @Test
+    public void testCallableTwice() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        final MutableBoolean called = new MutableBoolean(false);
+        Polling p = new Polling(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                boolean b = called.booleanValue();
+                called.setTrue();
+                return b;
+            }
+        });
+        p.poll(500, 10);
+
+        assertEquals(2, callCount.intValue());
+    }
+
+    @Test
+    public void testCallableTimeout() throws Exception {
+        final MutableInt callCount = new MutableInt(0);
+        Polling p = new Polling(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                callCount.increment();
+                return false;
+            }
+        });
+
+        try {
+            p.poll(100, 10);
+        } catch (TimeoutException e ) {
+            assertTrue("Expected to execute call() at least 4 times, got instead only " + callCount.intValue() + " calls",
+                    callCount.intValue() > 5);
+            return;
+        }
+
+        fail("Did not reach timeout");
+    }
+
+
+    @Test
+    public void testCallPriority() throws Exception {
+        Polling p = new Polling(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                return false;
+            }
+        }) {
+            @Override
+            public Boolean call() throws Exception {
+                return true;
+            }
+        };
+
+        // Should not reach timeout since overridden call() has priority over Callable param
+        p.poll(100, 10);
+    }
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.