/*
 * 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.launchpad.webapp.integrationtest;

import org.apache.sling.servlets.post.SlingPostConstants;

/** Test JSP scripting
 *  TODO this class can be generalized to be used for any scripting language,
 *  that would help in testing all scripting engines.
 */
public class JspScriptingTest extends JspTestBase {

    private String testRootUrl;
    private TestNode rtNode;
    private TestNode unstructuredNode;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        final String testRootPath = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis();
        testRootUrl = testClient.createNode(testRootPath + SlingPostConstants.DEFAULT_CREATE_SUFFIX, null);
        rtNode = new TestNode(testRootPath + "/rt", null);
        unstructuredNode = new TestNode(testRootPath + "/unstructured", null);
    }

    @Override
    protected void tearDown() throws Exception {
        testClient.delete(testRootUrl);
        super.tearDown();
    }

    public void testRtNoScript() throws Exception {
        final String content = getContent(rtNode.nodeUrl + ".txt", CONTENT_TYPE_PLAIN);
        assertTrue(content.contains("PlainTextRendererServlet"));
        assertTrue("Content contains " + rtNode.testText + " (" + content + ")", content.contains(rtNode.testText));
    }

    public void testUnstructuredNoScript() throws Exception {
        final String content = getContent(unstructuredNode.nodeUrl + ".txt", CONTENT_TYPE_PLAIN);
        assertTrue(content.contains("PlainTextRendererServlet"));
        assertTrue("Content contains " + unstructuredNode.testText + " (" + content + ")", content.contains(unstructuredNode.testText));
    }

    public void testRtJsp() throws Exception {
        final String toDelete = uploadTestScript(rtNode.scriptPath, "rendering-test.jsp", "html.jsp");
        try {
            checkContent(rtNode);
        } finally {
            if(toDelete != null) {
                testClient.delete(toDelete);
            }
        }
    }

    public void testUnstructuredJsp() throws Exception {
        final String toDelete = uploadTestScript(unstructuredNode.scriptPath, "rendering-test.jsp", "html.jsp");
        try {
            checkContent(unstructuredNode);
        } finally {
            if(toDelete != null) {
                testClient.delete(toDelete);
            }
        }
    }

    /* Verify that overwriting a JSP script changes the output immediately */
    public void testChangingJsp() throws Exception {
        String toDelete = null;

        try {
            final String [] scripts = { "jsp1.jsp", "jsp2.jsp" };
            for(String script : scripts) {
                toDelete = uploadTestScript(unstructuredNode.scriptPath, script, "html.jsp");
                final String content = getContent(unstructuredNode.nodeUrl + ".html", CONTENT_TYPE_HTML);
                final String expected = "text from " + script + ":" + unstructuredNode.testText;
                assertTrue("Content contains '" + expected + "'(" + content + ")", content.contains(expected));
            }
        } finally {
            if(toDelete != null) {
                testClient.delete(toDelete);
            }
        }
    }
    
    public void testEnum() throws Exception {
        String toDelete = null;
        try {
            toDelete = uploadTestScript(unstructuredNode.scriptPath, "enum-test.jsp", "txt.jsp");
            final String content = getContent(unstructuredNode.nodeUrl + ".txt", CONTENT_TYPE_PLAIN);
            for(String expected : new String[] { "FOO=FOO", "BAR=BAR"}) {
                assertTrue("Content contains '" + expected + "'(" + content + ")", content.contains(expected));
            }
        } finally {
            if(toDelete != null) {
                testClient.delete(toDelete);
            }
        }
    }

    private void checkContent(TestNode tn) throws Exception {
        final String content = getContent(tn.nodeUrl + ".html", CONTENT_TYPE_HTML);
        assertTrue("JSP script executed as expected (" + content + ")", content.contains("<h1>JSP rendering result</h1>"));

        final String [] expected = {
                "using resource.adaptTo:" + tn.testText,
                "using currentNode:" + tn.testText,
        };
        for(String exp : expected) {
            assertTrue("Content contains " + exp + "(" + content + ")", content.contains(exp));
        }
    }
}

@@ -3277,19 +3277,114 @@
 put 
-immediately
+within a reasonable time %0A     * (might not be immediate as there's some observation and caching involved)
  */%0A
@@ -3706,194 +3706,523 @@
     
-final String content = getContent(unstructuredNode.nodeUrl + %22.html%22, CONTENT_TYPE_HTML);%0A                final String expected = %22text from %22 + script + %22:%22 + unstructuredNode.testText;
+String content = null;%0A                final String expected = %22text from %22 + script + %22:%22 + unstructuredNode.testText;%0A                final long timeout = System.currentTimeMillis() + 2000L;%0A                while(System.currentTimeMillis() %3C timeout) %7B%0A                    content = getContent(unstructuredNode.nodeUrl + %22.html%22, CONTENT_TYPE_HTML);%0A                    if(content.contains(expected)) %7B%0A                        break;%0A                    %7D%0A                    Thread.sleep(100L);%0A                %7D
 %0A   

Make test more robust w.r.t. timing