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

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


The following commit(s) were added to refs/heads/master by this push:
     new b312fea  releng: made testing setup more resilient
b312fea is described below

commit b312fea73db4dcd62ef3ddaa6b76427a6d37453e
Author: Radu Cotescu <[email protected]>
AuthorDate: Tue Jan 7 12:41:09 2020 +0100

    releng: made testing setup more resilient
---
 pom.xml                               |  25 +++++++
 src/test/java/LaunchpadReadyIT.java   | 134 ++++++++++++++++++++++++++++++++++
 src/test/java/LaunchpadReadyRule.java | 120 ++++++++++++++++++++++++++++++
 3 files changed, 279 insertions(+)

diff --git a/pom.xml b/pom.xml
index d9b7a6f..83fc913 100644
--- a/pom.xml
+++ b/pom.xml
@@ -192,6 +192,7 @@
                         
<io.sightly.tck.serverURL>http://${test.host}:${http.port}</io.sightly.tck.serverURL>
                         <io.sightly.tck.user>admin</io.sightly.tck.user>
                         <io.sightly.tck.pass>admin</io.sightly.tck.pass>
+                        <launchpad.http.port>${http.port}</launchpad.http.port>
                         
<launchpad.http.server.url>http://${test.host}:${http.port}</launchpad.http.server.url>
                         
<launchpad.servlet.context>${http.base.path}</launchpad.servlet.context>
                     </systemPropertyVariables>
@@ -229,6 +230,15 @@
                             <modelPattern>sightly.txt</modelPattern>
                         </configuration>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                
<IT.expected.bundles.count>184</IT.expected.bundles.count>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
@@ -246,6 +256,15 @@
                             
<modelDirectory>${project.basedir}/src/test/provisioning</modelDirectory>
                         </configuration>
                     </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                
<IT.expected.bundles.count>179</IT.expected.bundles.count>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
@@ -352,5 +371,11 @@
             <version>4.4</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <version>1.11.2</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/test/java/LaunchpadReadyIT.java 
b/src/test/java/LaunchpadReadyIT.java
index bcfc3e8..7762558 100644
--- a/src/test/java/LaunchpadReadyIT.java
+++ b/src/test/java/LaunchpadReadyIT.java
@@ -17,16 +17,131 @@
  * under the License.
  
******************************************************************************/
 
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.utils.json.JSONParser;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.sling.testing.clients.SlingClient;
 import org.apache.sling.testing.junit.rules.SlingInstanceRule;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
 public class LaunchpadReadyIT {
 
+    private static final int LAUNCHPAD_PORT = 
Integer.getInteger("launchpad.http.port", 8080);
+    private static final int EXPECTED_BUNDLES_COUNT = 
Integer.getInteger("IT.expected.bundles.count", Integer.MAX_VALUE);
+    private HttpClientContext httpClientContext;
+
     @ClassRule
     public static final SlingInstanceRule SLING_INSTANCE_RULE = new 
SlingInstanceRule();
 
+    @ClassRule
+    public static LaunchpadReadyRule LAUNCHPAD = new 
LaunchpadReadyRule(LAUNCHPAD_PORT);
+
+    @Before
+    public void prepareHttpContext() {
+
+        CredentialsProvider credsProvider = new BasicCredentialsProvider();
+        UsernamePasswordCredentials creds = new 
UsernamePasswordCredentials("admin", "admin");
+        credsProvider.setCredentials(new AuthScope("localhost", 
LAUNCHPAD_PORT), creds);
+
+        BasicAuthCache authCache = new BasicAuthCache();
+        BasicScheme basicAuth = new BasicScheme();
+        authCache.put(new HttpHost("localhost", LAUNCHPAD_PORT, "http"), 
basicAuth);
+
+        httpClientContext = HttpClientContext.create();
+        httpClientContext.setCredentialsProvider(credsProvider);
+        httpClientContext.setAuthCache(authCache);
+    }
+
+    private CloseableHttpClient newClient() {
+
+        return HttpClientBuilder.create()
+                
.setDefaultCredentialsProvider(httpClientContext.getCredentialsProvider())
+                .build();
+    }
+
+    @Test
+    public void verifyAllBundlesStarted() throws Exception {
+
+        try (CloseableHttpClient client = newClient()) {
+
+            HttpGet get = new HttpGet("http://localhost:"; + LAUNCHPAD_PORT + 
"/system/console/bundles.json");
+
+            // pass the context to ensure preemptive basic auth is used
+            // 
https://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html
+            try (CloseableHttpResponse response = client.execute(get, 
httpClientContext)) {
+
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    fail("Unexpected status line " + response.getStatusLine());
+                }
+
+                Header contentType = response.getFirstHeader("Content-Type");
+                assertThat("Content-Type header", contentType.getValue(), 
CoreMatchers.startsWith("application/json"));
+
+                Map<String, Object> obj = new 
JSONParser(response.getEntity().getContent()).getParsed();
+
+                @SuppressWarnings("unchecked")
+                List<Object> status = (List<Object>) obj.get("s");
+
+                @SuppressWarnings("unchecked")
+                List<Object> bundles = (List<Object>) obj.get("data");
+                if (bundles.size() < EXPECTED_BUNDLES_COUNT) {
+                    fail("Expected at least " + EXPECTED_BUNDLES_COUNT + " 
bundles, got " + bundles.size());
+                }
+
+                BundleStatus bs = new BundleStatus(status);
+
+                if (bs.resolvedBundles != 0 || bs.installedBundles != 0) {
+
+                    StringBuilder out = new StringBuilder();
+                    out.append("Expected all bundles to be active, but instead 
got ")
+                            .append(bs.resolvedBundles).append(" resolved 
bundles, ")
+                            .append(bs.installedBundles).append(" installed 
bundlles: ");
+
+                    for (Object o : bundles) {
+                        @SuppressWarnings("unchecked")
+                        Map<String, Object> bundle = (Map<String, Object>) o;
+
+                        String bundleState = (String) bundle.get("state");
+                        String bundleSymbolicName = (String) 
bundle.get("symbolicName");
+                        String bundleVersion = (String) bundle.get("version");
+
+                        switch (bundleState) {
+                            case "Active":
+                            case "Fragment":
+                                continue;
+
+                            default:
+                                out.append("\n- 
").append(bundleSymbolicName).append(" ").append(bundleVersion).append(" is in 
state ")
+                                        .append(bundleState);
+                        }
+                    }
+
+                    fail(out.toString());
+                }
+            }
+        }
+    }
+
     @Test
     public void testLaunchpadReady() throws Exception {
         SlingClient client = SLING_INSTANCE_RULE.getAdminClient();
@@ -34,4 +149,23 @@ public class LaunchpadReadyIT {
         client.waitUntilExists("/sightlytck", 1000, 60);
     }
 
+    private static class BundleStatus {
+
+        long totalBundles;
+        long activeBundles;
+        long activeFragments;
+        long resolvedBundles;
+        long installedBundles;
+
+        public BundleStatus(List<Object> array) {
+
+            totalBundles = (Long) array.get(0);
+            activeBundles = (Long) array.get(1);
+            activeFragments = (Long) array.get(2);
+            resolvedBundles = (Long) array.get(3);
+            installedBundles = (Long) array.get(4);
+
+        }
+    }
+
 }
diff --git a/src/test/java/LaunchpadReadyRule.java 
b/src/test/java/LaunchpadReadyRule.java
new file mode 100644
index 0000000..0e9325d
--- /dev/null
+++ b/src/test/java/LaunchpadReadyRule.java
@@ -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.
+ */
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.junit.rules.ExternalResource;
+
+public class LaunchpadReadyRule extends ExternalResource {
+
+    private static final int TRIES = 60;
+    private static final int WAIT_BETWEEN_TRIES_MILLIS = 1000;
+
+    private final List<Check> checks = new ArrayList<>();
+
+    public LaunchpadReadyRule(int launchpadPort) {
+
+        checks.add(new Check("http://localhost:"; + launchpadPort + 
"/server/default/jcr:root/content"));
+        checks.add(new Check("http://localhost:"; + launchpadPort + 
"/content/starter.html") {
+            @Override
+            public String runCheck(HttpResponse response) throws Exception {
+                try (InputStreamReader isr = new 
InputStreamReader(response.getEntity().getContent());
+                     BufferedReader reader = new BufferedReader(isr)) {
+
+                    String line;
+                    while ((line = reader.readLine()) != null) {
+                        if (line.contains("Do not remove this comment, used 
for Starter integration tests")) {
+                            return null;
+                        }
+                    }
+                }
+
+                return "Did not find 'ready' marker in the response body";
+            }
+        });
+    }
+
+    @Override
+    protected void before() throws Throwable {
+
+        try (CloseableHttpClient client = HttpClients.createDefault()) {
+            for (Check check : checks) {
+                runCheck(client, check);
+            }
+        }
+    }
+
+    private void runCheck(CloseableHttpClient client, Check check) throws 
Exception {
+
+        String lastFailure = null;
+        HttpGet get = new HttpGet(check.getUrl());
+
+        for (int i = 0; i < TRIES; i++) {
+            try (CloseableHttpResponse response = client.execute(get)) {
+
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    lastFailure = "Status code is " + response.getStatusLine();
+                    Thread.sleep(WAIT_BETWEEN_TRIES_MILLIS);
+                    continue;
+                }
+
+                lastFailure = check.runCheck(response);
+                if (lastFailure == null) {
+                    return;
+                }
+            } catch (ConnectException e) {
+                lastFailure = e.getClass().getName() + " : " + e.getMessage();
+            }
+
+            Thread.sleep(WAIT_BETWEEN_TRIES_MILLIS);
+        }
+
+        throw new RuntimeException(String.format("Launchpad not ready. Failed 
check for URL %s with message '%s'",
+                check.getUrl(), lastFailure));
+    }
+
+    static class Check {
+        private String url;
+
+        public Check(String url) {
+            this.url = url;
+        }
+
+        public String getUrl() {
+            return url;
+        }
+
+        /**
+         * @param response the HttpResponse
+         * @return null if check check was successful, an error description 
otherwise
+         * @throws Exception
+         */
+        public String runCheck(HttpResponse response) throws Exception {
+            return null;
+        }
+    }
+
+}

Reply via email to