Package org.auraframework.http

Source Code of org.auraframework.http.AppCacheManifestHttpTest

/*
* Copyright (C) 2013 salesforce.com, inc.
*
* Licensed 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.auraframework.http;

import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.protocol.HttpContext;
import org.auraframework.controller.java.ServletConfigController;
import org.auraframework.def.ApplicationDef;
import org.auraframework.def.DefDescriptor;
import org.auraframework.system.AuraContext.Mode;
import org.auraframework.test.AuraHttpTestCase;
import org.auraframework.test.annotation.ThreadHostileTest;
import org.auraframework.test.annotation.UnAdaptableTest;
import org.auraframework.test.client.UserAgent;

import com.google.common.collect.Lists;
import com.google.common.io.LineReader;

public class AppCacheManifestHttpTest extends AuraHttpTestCase {

    private static final String APPCACHE_SUPPORTED_USERAGENT = UserAgent.GOOGLE_CHROME.getUserAgentString();
    private static final String APPCACHE_UNSUPPORTED_USERAGENT = UserAgent.EMPTY.getUserAgentString();
    private static final Pattern HTML_MANIFEST_PATTERN = Pattern.compile("<html[^>]* manifest=\"(.*?)\"[^>]*>");

    public AppCacheManifestHttpTest(String name) {
        super(name);
    }

    private String getManifestURL(String appPath, Mode mode) throws Exception {
        HttpGet get = obtainGetMethod(appPath + String.format("?aura.mode=%s",mode.toString()));
        HttpResponse response = perform(get);
        String responseBody = getResponseBody(response);
        get.releaseConnection();
        Matcher m = HTML_MANIFEST_PATTERN.matcher(responseBody);
        String url = null;
        if (m.find()) {
            url = m.group(1);
        }
        return url;
    }

    private String getManifestURL(String appPath) throws Exception {
        return getManifestURL(appPath, Mode.PROD);
    }

    private String getManifestErrorUrl(String manifestURI) {
        return manifestURI + "?aura.error=true";
    }

    private List<String> getManifestLinks(String manifestContents) throws IOException {
        List<String> links = Lists.newArrayList();

        LineReader reader = new LineReader(new StringReader(manifestContents));
        for (String line = reader.readLine(); line != null; line = reader.readLine()) {
            if (line.startsWith("/")) {
                links.add(line);
            }
        }
        return links;
    }

    private List<String> getRequiredLinks() throws Exception {
        List<String> required = Lists.newArrayList();
        required.add(".*/aura_prod\\.js");
        return required;
    }

    private void assertManifest(String manifestContent, List<String> requiredLinks) throws Exception {
        assertManifestFormat(manifestContent);
        assertTrue("Could not find the LAST MOD: line in manifest", manifestContent.contains("\n# LAST MOD: app="));

        List<String> links = getManifestLinks(manifestContent);
        List<String> required = getRequiredLinks();
        required.addAll(requiredLinks);
        assertRequiredLinks(required, links);
        assertLinksReachable(links);
    }

    private void assertManifestFormat(String manifestContent) {
        if (!manifestContent.startsWith("CACHE MANIFEST\n")) {
            fail("Manifest should starts with: " + "CACHE MANIFEST");
        }
    }

    private void assertRequiredLinks(List<String> required, List<String> links) throws Exception {
        for (String requiredLink : required) {
            boolean foundFlag = false;
            for (String link : links) {
                if (link.matches(requiredLink)) {
                    foundFlag = true;
                }
            }
            if (!foundFlag) {
                fail("Missing required link: " + requiredLink + " but got instead: " + links);
            }
        }
    }

    private void assertLinksReachable(List<String> links) throws Exception {
        for (String link : links) {
            HttpGet get = obtainGetMethod(link);
            HttpResponse response = perform(get);
            int statusCode = getStatusCode(response);
            get.releaseConnection();
            assertEquals("Unexpected response code for link [" + link + "]", HttpStatus.SC_OK, statusCode);
        }
    }

    private void assertManifestHeaders(HttpResponse response) throws Exception {
      assertDefaultAntiClickjacking(response, true, false);
        String cacheControlHeader = String.format(",%s,", response.getFirstHeader(HttpHeaders.CACHE_CONTROL).getValue()
                .replaceAll("\\s", ""));
        if (!cacheControlHeader.contains(",no-cache,") || !cacheControlHeader.contains(",no-store,")) {
            fail("Missing cache control header values in: " + cacheControlHeader);
        }

        String expectedContentType = String.format("%s;charset=%s", AuraBaseServlet.MANIFEST_CONTENT_TYPE,
                AuraBaseServlet.UTF_ENCODING);
        Header[] contentTypeHeaders = response.getHeaders(HttpHeaders.CONTENT_TYPE);
        for (Header header : contentTypeHeaders) {
            if (expectedContentType.equals(header.getValue().replaceAll("\\s", ""))) {
                return;
            }
        }
        fail("Did not find expected content type header: " + Arrays.asList(contentTypeHeaders));
    }

    /**
     * GET app cache manifest without a supported user agent returns 404.
     */
    public void testGetManifestWithUnsupportedUserAgent() throws Exception {
        setHttpUserAgent(APPCACHE_UNSUPPORTED_USERAGENT);
        String manifest = getManifestURL("/appCache/withpreload.app");

        HttpGet get = obtainGetMethod(manifest);
        HttpResponse httpResponse = perform(get);
        String response = getResponseBody(httpResponse);
        get.releaseConnection();

        if (!response.isEmpty()) {
            fail("manifest should be empty: *" + manifest);
        }
    }

    /**
     * No manifest url is given when app cache is disabled via config.
     */
    @ThreadHostileTest("disables AppCache")
    public void testGetManifestWithAppCacheDisabled() throws Exception {
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        ServletConfigController.setAppCacheDisabled(true);
        String manifest = getManifestURL("/appCache/withpreload.app");
        if (manifest != null) {
            fail("no manifest url should be present, but got: " + manifest);
        }
    }

    /**
     * Manifest url is given even when app has no explicit preloads.
     */
    public void testGetManifestForAppWithoutPreloads() throws Exception {
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        String manifest = getManifestURL("/appCache/nopreload.app");
        if (manifest == null) {
            fail("manifest url should be present, but got: " + manifest);
        }
    }

    /**
     * GET app cache manifest for app with preloads returns a full manifest containing preloading resources.
     *
     * note that invalid and absolute css urls are not included
     */
    public void testGetManifestForAppWithPreloads() throws Exception {
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        String manifest = getManifestURL("/appCache/withpreload.app");

        HttpGet get = obtainGetMethod(manifest);
        HttpResponse httpResponse = perform(get);
        String response = getResponseBody(httpResponse);
        get.releaseConnection();

        assertManifest(response, Lists.newArrayList(".*/app\\.css", ".*/app\\.js"));
    }

    /**
     * GET app cache manifest with aura.error query param returns empty response and error-valued manifest cookie.
     */
    @UnAdaptableTest
    public void testGetManifestWithAuraErrorParam() throws Exception {
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        String manifest = getManifestURL("/appCache/withpreload.app");

        HttpGet get = obtainGetMethod(getManifestErrorUrl(manifest));

        HttpResponse httpResponse = perform(get);
        String response = getResponseBody(httpResponse);

        assertEquals(HttpStatus.SC_NO_CONTENT, getStatusCode(httpResponse));
        assertManifestHeaders(httpResponse);

        get.releaseConnection();

        if (response != null) {
            fail("Expected empty response, but got:\n" + response);
        }
    }

    /**
     * GET app cache manifest with manifest cookie with error value, returns 404 and deletes the manifest cookie.
     */
    public void testGetManifestWithErrorManifestCookie() throws Exception {
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        String manifest = getManifestURL("/appCache/withpreload.app");

        //
        // HttpClient Cookie Example
        // 1. Add cookie
        // 2. Create HttpContext which has default CookieStore
        // 3. Perform request method with context
        //
        addCookie(getHost(), "appCache_withpreload_lm", "error", "/");
        HttpContext httpContext = getHttpCookieContext();
        HttpGet get = obtainGetMethod(manifest);
        HttpResponse httpResponse = perform(get, httpContext);
        int statusCode = getStatusCode(httpResponse);
        String response = getResponseBody(httpResponse);
        get.releaseConnection();

        assertEquals(HttpStatus.SC_NOT_FOUND, statusCode);
        assertManifestHeaders(httpResponse);
        assertEquals("", response);
        assertNoCookie(getHost(), "appCache_withpreload_lm", "/");

        get = obtainGetMethod(manifest);
        HttpResponse clean = perform(get);
        String cleanResponse = getResponseBody(clean);
        get.releaseConnection();

        // Now, after one failed call a new manifest call should go thru.(Error
        // cookie cleared);
        assertManifest(cleanResponse, Lists.newArrayList(".*/app\\.css", ".*/app\\.js"));
    }

    /**
     * GET app cache manifest for app with additional URLs specified using a controller action returns a full manifest
     * containing the additional URLs returned by controller.
     */
    public void testGetManifestForAppWithAdditionalAppCacheURLs() throws Exception {
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        String manifest = getManifestURL("/appCache/additionalUrls.app");

        HttpGet get = obtainGetMethod(manifest);
        HttpResponse httpResponse = perform(get);
        String response = getResponseBody(httpResponse);
        get.releaseConnection();

        assertManifest(response, Lists.newArrayList(".*/app\\.css", ".*/app\\.js",
                "/auraFW/resources/aura/auraIdeLogo.png", "/auraFW/resources/aura/resetCSS.css"));
    }

    /**
     * Verify behavior when action which provides additional app cache urls returns bad results or throws exception.
     * TODO: W-1590903 - What should the expected behavior be? Currently, the behavior is not consistent across these
     * scenarios, it just continues and ignores the exception thrown by the action, in other cases it returns 404.
     * Should we do something to signal that something went wrong, you might not have resources that you asked for?
     */
    public void _testGetManifestWhenAdditionalAppCacheUrlsActionBarfs() throws Exception {
        String values[] = { "{!c.throwException}", // Action throws exception
                "{!c.getString}", // Action returns literal instead of List<String>
                "{!v.attr}", // A expression that refers to attribute instead of action
                "/auraFW/resources/aura/resetCSS.css" };

        String appMarkup = String.format(baseApplicationTag,
                "useAppcache=\"true\" render=\"client\" " +
                        " controller=\"java://org.auraframework.impl.java.controller.TestController\" " +
                        "additionalAppCacheURLs=\"%s\"", "");

        for (String value : values) {
            DefDescriptor<ApplicationDef> desc = addSourceAutoCleanup(ApplicationDef.class,
                    String.format(appMarkup, value));
            setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
            String manifest = getManifestURL(getUrl(desc));
            HttpGet get = obtainGetMethod(manifest);
            HttpResponse httpResponse = perform(get);
            String response = getResponseBody(httpResponse);
            int statusCode = getStatusCode(httpResponse);
            get.releaseConnection();

            assertEquals("Expected to fail manifest fetching. additionalAppCacheUrls:" + value,
                    HttpStatus.SC_NOT_FOUND, statusCode);

            assertManifest(response, Lists.newArrayList(".*/app\\.css", ".*/app\\.js"));
        }
    }
   
    /**
     *
     * UIPerf, UIPerfUi, UIPerfCSS, walltimelocale are uncombinable in PTEST mode.
     */
    public void testUncombinableResourceUrlsAreAddedToAppCacheManifest()throws Exception{
        setHttpUserAgent(APPCACHE_SUPPORTED_USERAGENT);
        String manifest = getManifestURL("/clientLibraryTest/clientLibraryTest.app", Mode.PTEST);
       
        HttpGet get  = obtainGetMethod(manifest);
        HttpResponse response = perform(get);
        assertEquals("Failed to fetch manifest", HttpStatus.SC_OK,getStatusCode(response));
        String responseString = getResponseBody(response);
        get.releaseConnection();
        assertNotNull(responseString);
       
        assertTrue("Manifest doesn't contain combinable CSS resource url", responseString.contains("/resources.css"));
        assertTrue("Manifest doesn't contain combinable JS resource url", responseString.contains("/resources.js"));
       
        //Verify the urls of uncombinable resources
        assertTrue("Missing UIPerf", responseString.contains("/UIPerf/UIPerf") || responseString.contains("perf/ormance.js"));
        assertTrue("Missing Moment", responseString.contains("/moment/moment.js"));
        assertTrue("Missing Walltime", responseString.contains("walltime-js/walltime.js"));
    }
}
TOP

Related Classes of org.auraframework.http.AppCacheManifestHttpTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.