org.auraframework.impl.adapter.ServletUtilAdapterImplUnitTest.java Source code

Java tutorial

Introduction

Here is the source code for org.auraframework.impl.adapter.ServletUtilAdapterImplUnitTest.java

Source

/*
 * 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.impl.adapter;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ConcurrentModificationException;
import java.util.EmptyStackException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.auraframework.adapter.ConfigAdapter;
import org.auraframework.adapter.ExceptionAdapter;
import org.auraframework.clientlibrary.ClientLibraryService;
import org.auraframework.def.ClientLibraryDef;
import org.auraframework.http.ManifestUtil;
import org.auraframework.instance.InstanceStack;
import org.auraframework.service.ContextService;
import org.auraframework.service.SerializationService;
import org.auraframework.system.AuraContext;
import org.auraframework.system.AuraContext.Format;
import org.auraframework.system.AuraContext.Mode;
import org.auraframework.util.test.util.UnitTestCase;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

public class ServletUtilAdapterImplUnitTest extends UnitTestCase {
    @Test
    public void testHandleServletExceptionSetsNoCacheForOKBeforeThrowing() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        Throwable t = new IOException();
        ContextService contextService = Mockito.mock(ContextService.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        sua.setContextService(contextService);

        Mockito.when(response.getStatus()).thenReturn(HttpStatus.SC_OK);

        sua = Mockito.spy(sua);

        Throwable expected = null;
        try {
            sua.handleServletException(t, false, context, request, response, false);
        } catch (Throwable x) {
            expected = x;
        }

        Mockito.verify(sua, Mockito.times(1)).setNoCache(response);
        Mockito.verify(contextService, Mockito.times(1)).endContext();
        assertEquals(expected, t);
    }

    @Test
    public void testHandleServletExceptionDoesNotSetNoCacheBeforeThrowingWhenNoCacheThrows() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        Throwable t = new IOException();
        ContextService contextService = Mockito.mock(ContextService.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        sua.setContextService(contextService);
        sua = Mockito.spy(sua);

        Mockito.when(response.getStatus()).thenReturn(HttpStatus.SC_OK);
        Mockito.doThrow(new Error()).when(response).setHeader(Mockito.any(), Mockito.any());

        Throwable expected = null;
        try {
            sua.handleServletException(t, false, context, request, response, true);
        } catch (Throwable x) {
            expected = x;
        }

        Mockito.verify(sua, Mockito.times(1)).setNoCache(response);

        ArgumentCaptor<Integer> statusCaptor = ArgumentCaptor.forClass(Integer.class);
        Mockito.verify(response, Mockito.atLeastOnce()).setStatus(statusCaptor.capture());
        List<Integer> statuses = statusCaptor.getAllValues();
        assertEquals("Must end up with 'SERVER_ERROR'", Integer.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR),
                statuses.get(statuses.size() - 1));

        Mockito.verify(contextService, Mockito.times(1)).endContext();
        assertEquals(t, expected);
    }

    @Test
    public void testHandleServletExceptionSetsInternalServerErrorForManifestEnabledForJS() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        Throwable t = Mockito.mock(Throwable.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        ContextService contextService = Mockito.mock(ContextService.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        ManifestUtil manifestUtil = Mockito.mock(ManifestUtil.class);
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        ExceptionAdapter exceptionAdapter = Mockito.mock(ExceptionAdapter.class);
        sua.setExceptionAdapter(exceptionAdapter);
        sua.setConfigAdapter(configAdapter);
        sua.setManifestUtil(manifestUtil);
        sua.setContextService(contextService);
        sua = Mockito.spy(sua);

        Mockito.when(context.getFormat()).thenReturn(Format.JS);
        Mockito.when(manifestUtil.isManifestEnabled()).thenReturn(true);
        Mockito.when(configAdapter.isProduction()).thenReturn(true);

        sua.handleServletException(t, false, context, request, response, true);

        ArgumentCaptor<Integer> statusCaptor = ArgumentCaptor.forClass(Integer.class);
        Mockito.verify(response, Mockito.times(1)).setStatus(statusCaptor.capture());
        List<Integer> statuses = statusCaptor.getAllValues();
        assertEquals("Must end up with 'SERVER_ERROR'", Integer.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR),
                statuses.get(0));
        Mockito.verify(contextService, Mockito.times(1)).endContext();
    }

    @Test
    public void testHandleServletExceptionSetsOKPlusNoCacheForManifestDisabledForJS() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        Throwable t = Mockito.mock(Throwable.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        ContextService contextService = Mockito.mock(ContextService.class);
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        ManifestUtil manifestUtil = Mockito.mock(ManifestUtil.class);
        InstanceStack instanceStack = Mockito.mock(InstanceStack.class);
        ExceptionAdapter exceptionAdapter = Mockito.mock(ExceptionAdapter.class);
        sua.setContextService(contextService);
        sua.setExceptionAdapter(exceptionAdapter);
        sua.setConfigAdapter(configAdapter);
        sua.setManifestUtil(manifestUtil);
        sua = Mockito.spy(sua);

        Mockito.when(context.getFormat()).thenReturn(Format.JS);
        Mockito.when(manifestUtil.isManifestEnabled()).thenReturn(false);
        Mockito.when(configAdapter.isProduction()).thenReturn(true);
        Mockito.when(context.getInstanceStack()).thenReturn(instanceStack);
        Mockito.when(instanceStack.getStackInfo()).thenReturn(Lists.newArrayList());

        sua.handleServletException(t, false, context, request, response, true);

        Mockito.verify(sua, Mockito.times(1)).setNoCache(response);

        //
        // Check the response status.
        //
        ArgumentCaptor<Integer> statusCaptor = ArgumentCaptor.forClass(Integer.class);
        Mockito.verify(response, Mockito.times(1)).setStatus(statusCaptor.capture());
        List<Integer> statuses = statusCaptor.getAllValues();
        assertEquals("Must end up with 'OK' ", Integer.valueOf(HttpStatus.SC_OK), statuses.get(0));
        Mockito.verify(contextService, Mockito.times(1)).endContext();
    }

    @Test
    public void testSend404() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        ContextService contextService = Mockito.mock(ContextService.class);
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);

        sua.setContextService(contextService);

        Mockito.when(response.getWriter()).thenReturn(pw);

        sua.send404(null, null, response);

        Mockito.verify(response, Mockito.times(1)).setStatus(HttpServletResponse.SC_NOT_FOUND);
        Mockito.verify(response, Mockito.times(1)).getWriter();
        Mockito.verify(contextService, Mockito.times(1)).endContext();
        Mockito.verifyNoMoreInteractions(response);
        Mockito.verifyNoMoreInteractions(contextService);

        String output = sw.getBuffer().toString();
        assertTrue("Output should start with '404 Not Found'", output.startsWith("404 Not Found"));
        assertTrue("Output should be longer than 256 bytes", output.length() > 256);
    }

    @Test
    public void testGetScriptsSafeNoIgnore() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        List<String> clientLibraries = Lists.newArrayList("cl1", "cl2");
        List<String> baseScripts = Lists.newArrayList("bs1", "bs2");
        List<String> frameworkScripts = Lists.newArrayList("fs1", "fs2");
        List<String> expected = Lists.newArrayList("cl1", "cl2", "bs1", "bs2", "fs1", "fs2");
        Map<String, Object> attributes = Maps.newHashMap();

        sua = Mockito.spy(sua);
        Mockito.doReturn(clientLibraries).when(sua).getJsClientLibraryUrls(context);
        Mockito.doReturn(baseScripts).when(sua).getBaseScripts(context, attributes);
        Mockito.doReturn(frameworkScripts).when(sua).getFrameworkScripts(context, true, false, attributes);

        List<String> result = sua.getScripts(context, true, false, attributes);

        assertEquals(expected, result);
    }

    @Test
    public void testGetScriptsNotSafeIgnore() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        List<String> clientLibraries = Lists.newArrayList("cl1", "cl2");
        List<String> baseScripts = Lists.newArrayList("bs1", "bs2");
        List<String> frameworkScripts = Lists.newArrayList("fs1", "fs2");
        List<String> expected = Lists.newArrayList("cl1", "cl2", "bs1", "bs2", "fs1", "fs2");
        ClientLibraryService clientLibraryService = Mockito.mock(ClientLibraryService.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua.setClientLibraryService(clientLibraryService);

        sua = Mockito.spy(sua);
        Mockito.doReturn(clientLibraries).when(sua).getJsClientLibraryUrls(context);
        Mockito.doReturn(baseScripts).when(sua).getBaseScripts(context, attributes);
        Mockito.doReturn(frameworkScripts).when(sua).getFrameworkScripts(context, false, true, attributes);

        List<String> result = sua.getScripts(context, false, true, attributes);

        assertEquals(expected, result);
    }

    @Test
    public void testGetStyles() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        List<String> clientLibraries = Lists.newArrayList("cl1", "cl2");
        List<String> expected = Lists.newArrayList("cl1", "cl2", "appcss");

        sua = Mockito.spy(sua);
        Mockito.doReturn(clientLibraries).when(sua).getCssClientLibraryUrls(context);
        Mockito.doReturn("appcss").when(sua).getAppCssUrl(context);

        List<String> result = sua.getStyles(context);

        assertEquals(expected, result);
    }

    @Test
    public void testGetClientLibraryUrls() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        ClientLibraryService clientLibraryService = Mockito.mock(ClientLibraryService.class);
        List<String> expected = Lists.newArrayList("cl1", "cl2");
        Set<String> returned = Sets.newLinkedHashSet(expected);
        List<String> actual;
        sua.setClientLibraryService(clientLibraryService);

        Mockito.doReturn(returned).when(clientLibraryService).getUrls(context, ClientLibraryDef.Type.CSS);

        actual = sua.getCssClientLibraryUrls(context);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetBaseScripts() throws Exception {
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        sua.setConfigAdapter(configAdapter);
        String expectedURL = "aurajs";
        List<String> expected = Lists.newArrayList(expectedURL);
        List<String> actual;

        Mockito.doReturn(expectedURL).when(configAdapter).getAuraJSURL();

        actual = sua.getBaseScripts(null, null);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkScriptsSafeNoCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua = Mockito.spy(sua);
        List<String> expected = Lists.newArrayList("appjs");
        List<String> actual;

        Mockito.doReturn("inline").when(sua).getInlineJsUrl(context, attributes);
        Mockito.doReturn("appjs").when(sua).getAppJsUrl(context, null);
        Mockito.doReturn("bootstrap").when(sua).getBootstrapUrl(context, attributes);

        actual = sua.getFrameworkScripts(context, true, true, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkScriptsUnSafeNoCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua = Mockito.spy(sua);
        List<String> expected = Lists.newArrayList("appjs");
        List<String> actual;

        Mockito.doReturn("inline").when(sua).getInlineJsUrl(context, attributes);
        Mockito.doReturn("appjs").when(sua).getAppJsUrl(context, null);
        Mockito.doReturn("bootstrap").when(sua).getBootstrapUrl(context, attributes);

        actual = sua.getFrameworkScripts(context, false, true, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkScriptsUnSafeCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua = Mockito.spy(sua);
        List<String> expected = Lists.newArrayList("appjs", "bootstrap");
        List<String> actual;

        Mockito.doReturn("inline").when(sua).getInlineJsUrl(context, attributes);
        Mockito.doReturn("appjs").when(sua).getAppJsUrl(context, null);
        Mockito.doReturn("bootstrap").when(sua).getBootstrapUrl(context, attributes);

        actual = sua.getFrameworkScripts(context, false, false, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkScriptsSafeCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua = Mockito.spy(sua);
        List<String> expected = Lists.newArrayList("inline", "appjs", "bootstrap");
        List<String> actual;

        Mockito.doReturn("inline").when(sua).getInlineJsUrl(context, attributes);
        Mockito.doReturn("appjs").when(sua).getAppJsUrl(context, null);
        Mockito.doReturn("bootstrap").when(sua).getBootstrapUrl(context, attributes);

        actual = sua.getFrameworkScripts(context, true, false, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkFallbackScriptsSafe() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua = Mockito.spy(sua);
        List<String> expected = Lists.newArrayList();
        List<String> actual;

        Mockito.doReturn("bootstrap").when(sua).getBootstrapUrl(context, attributes);

        actual = sua.getFrameworkFallbackScripts(context, true, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkFallbackScriptsUnSafe() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newHashMap();
        sua = Mockito.spy(sua);
        List<String> expected = Lists.newArrayList();
        List<String> actual;

        Mockito.doReturn("bootstrap").when(sua).getBootstrapUrl(context, attributes);

        actual = sua.getFrameworkFallbackScripts(context, false, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetJsClientLibraryUrls() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ClientLibraryService clientLibraryService = Mockito.mock(ClientLibraryService.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        sua.setClientLibraryService(clientLibraryService);
        List<String> expected = Lists.newArrayList("a", "b");
        Set<String> returned = Sets.newLinkedHashSet(expected);
        List<String> actual;

        Mockito.doReturn(returned).when(clientLibraryService).getUrls(context, ClientLibraryDef.Type.JS);

        actual = sua.getJsClientLibraryUrls(context);
        assertEquals(expected, actual);
    }

    @Test
    @Ignore("write me please")
    public void testWriteScriptUrls() throws Exception {
    }

    @Test
    public void testGetCssClientLibraryUrls() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ClientLibraryService clientLibraryService = Mockito.mock(ClientLibraryService.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        sua.setClientLibraryService(clientLibraryService);
        List<String> expected = Lists.newArrayList("a", "b");
        Set<String> returned = Sets.newLinkedHashSet(expected);
        List<String> actual;

        Mockito.doReturn(returned).when(clientLibraryService).getUrls(context, ClientLibraryDef.Type.CSS);

        actual = sua.getCssClientLibraryUrls(context);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetFrameworkUrl() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        String expected = "aurajs";
        String actual;
        sua.setConfigAdapter(configAdapter);

        Mockito.doReturn(expected).when(configAdapter).getAuraJSURL();

        actual = sua.getFrameworkUrl();
        assertEquals(expected, actual);
    }

    @Test
    public void testGetBootstrapUrl() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newLinkedHashMap();
        String expected = "contextPath/l/nonce/bootstrap.js?aura.attributes=%7B%22first%22%3A%22fv%22%2C%22second%22%3A%22sv%22%7D&jwt=thisjwt";
        String actual;
        sua.setConfigAdapter(configAdapter);

        attributes.put("first", "fv");
        attributes.put("second", "sv");

        Mockito.doReturn("contextPath").when(context).getContextPath();
        Mockito.doReturn("nonce").when(context).getEncodedURL(AuraContext.EncodingStyle.Normal);
        Mockito.doReturn("thisjwt").when(configAdapter).generateJwtToken();

        sua.createManifestUtil(); // Post-construct step
        actual = sua.getBootstrapUrl(context, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetBootstrapUrlEmptyAttributes() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newLinkedHashMap();
        String expected = "contextPath/l/nonce/bootstrap.js?jwt=thisjwt";
        String actual;
        sua.setConfigAdapter(configAdapter);

        Mockito.doReturn("contextPath").when(context).getContextPath();
        Mockito.doReturn("nonce").when(context).getEncodedURL(AuraContext.EncodingStyle.Normal);
        Mockito.doReturn("thisjwt").when(configAdapter).generateJwtToken();

        sua.createManifestUtil(); // Post-construct step
        actual = sua.getBootstrapUrl(context, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetInlineJsUrl() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newLinkedHashMap();
        String expected = "contextPath/l/nonce/inline.js?aura.attributes=%7B%22first%22%3A%22fv%22%2C%22second%22%3A%22sv%22%7D&jwt=thisjwt";
        String actual;
        sua.setConfigAdapter(configAdapter);

        attributes.put("first", "fv");
        attributes.put("second", "sv");

        Mockito.doReturn("contextPath").when(context).getContextPath();
        Mockito.doReturn("nonce").when(context).getEncodedURL(AuraContext.EncodingStyle.Normal);
        Mockito.doReturn("thisjwt").when(configAdapter).generateJwtToken();

        sua.createManifestUtil(); // Post-construct step
        actual = sua.getInlineJsUrl(context, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetInlineJsUrlNoAttributes() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newLinkedHashMap();
        String expected = "contextPath/l/nonce/inline.js?jwt=thisjwt";
        String actual;
        sua.setConfigAdapter(configAdapter);

        Mockito.doReturn("contextPath").when(context).getContextPath();
        Mockito.doReturn("nonce").when(context).getEncodedURL(AuraContext.EncodingStyle.Normal);
        Mockito.doReturn("thisjwt").when(configAdapter).generateJwtToken();

        sua.createManifestUtil(); // Post-construct step
        actual = sua.getInlineJsUrl(context, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetAppJsUrl() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newLinkedHashMap();
        String expected = "contextPath/l/nonce/app.js?aura.attributes=%7B%22first%22%3A%22fv%22%2C%22second%22%3A%22sv%22%7D";
        String actual;
        sua.setConfigAdapter(configAdapter);

        attributes.put("first", "fv");
        attributes.put("second", "sv");

        Mockito.doReturn("contextPath").when(context).getContextPath();
        Mockito.doReturn("nonce").when(context).getEncodedURL(AuraContext.EncodingStyle.Normal);

        actual = sua.getAppJsUrl(context, attributes);
        assertEquals(expected, actual);
    }

    @Test
    public void testGetAppCssUrl() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        AuraContext context = Mockito.mock(AuraContext.class);
        Map<String, Object> attributes = Maps.newLinkedHashMap();
        String expected = "contextPath/l/nonce/app.css";
        String actual;
        sua.setConfigAdapter(configAdapter);

        attributes.put("first", "fv");
        attributes.put("second", "sv");

        Mockito.doReturn("contextPath").when(context).getContextPath();
        Mockito.doReturn("nonce").when(context).getEncodedURL(AuraContext.EncodingStyle.Css);

        actual = sua.getAppCssUrl(context);
        assertEquals(expected, actual);
    }

    @Test
    public void testSetNoCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        long now = System.currentTimeMillis();

        sua.setNoCache(response);

        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store");
        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.PRAGMA, "no-cache");

        ArgumentCaptor<String> nameCaptors = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<Long> dateCaptors = ArgumentCaptor.forClass(Long.class);

        Mockito.verify(response, Mockito.times(2)).setDateHeader(nameCaptors.capture(), dateCaptors.capture());

        List<String> names = nameCaptors.getAllValues();
        List<Long> dates = dateCaptors.getAllValues();

        // allow arbitrary ordering.
        int expires = 0;
        int lastModified = 1;
        if (HttpHeaders.EXPIRES.equals(names.get(1))) {
            expires = 1;
            lastModified = 0;
        }
        assertEquals("Expires header should be 'EXPIRES'", HttpHeaders.EXPIRES, names.get(expires));
        assertTrue("Expires should be in the future at least the timeout",
                dates.get(expires).longValue() < now - 60 * 1000);
        assertEquals("Expires header should be 'LAST_MODIFIED'", HttpHeaders.LAST_MODIFIED,
                names.get(lastModified));
        assertTrue("LastModified should be in the past", dates.get(lastModified).longValue() < now);

        Mockito.verifyNoMoreInteractions(response);
    }

    @Test
    public void testIsProductionModeModeProd() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();

        assertTrue(sua.isProductionMode(Mode.PROD));
    }

    @Test
    public void testIsProductionModeByConfig() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        Mockito.doReturn(true).when(configAdapter).isProduction();
        sua.setConfigAdapter(configAdapter);

        assertTrue(sua.isProductionMode(Mode.DEV));
    }

    @Test
    public void testIsProductionModeIsFalse() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        ConfigAdapter configAdapter = Mockito.mock(ConfigAdapter.class);
        Mockito.doReturn(false).when(configAdapter).isProduction();
        sua.setConfigAdapter(configAdapter);

        assertFalse(sua.isProductionMode(Mode.DEV));
    }

    @Test
    @Ignore("write me please")
    public void testSetCSPHeaders() throws Exception {
    }

    @Test
    public void testSetLongCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        long now = System.currentTimeMillis();
        long timeoutmSecs = 45 * 24L * 60 * 60 * 1000;

        sua.setCacheTimeout(response, timeoutmSecs);

        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.VARY, "Accept-Encoding");
        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.CACHE_CONTROL, "max-age=3888000, public");

        checkCacheDateHeaders(response, now, timeoutmSecs);

        Mockito.verifyNoMoreInteractions(response);
    }

    @Test
    public void testSetShortCache() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        long now = System.currentTimeMillis();
        long timeoutmSecs = 24L * 60 * 60 * 1000;

        sua.setCacheTimeout(response, timeoutmSecs);

        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.VARY, "Accept-Encoding");
        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.CACHE_CONTROL, "max-age=86400, public");

        checkCacheDateHeaders(response, now, timeoutmSecs);

        Mockito.verifyNoMoreInteractions(response);
    }

    @Test
    public void testSetCacheTimeout() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        long now = System.currentTimeMillis();
        long timeoutmSecs = 100000;

        sua.setCacheTimeout(response, timeoutmSecs);

        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.VARY, "Accept-Encoding");
        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.CACHE_CONTROL, "max-age=100, public");

        checkCacheDateHeaders(response, now, timeoutmSecs);

        Mockito.verifyNoMoreInteractions(response);
    }

    @Test
    public void testSetCacheTimeoutVeryLong() throws Exception {
        ServletUtilAdapterImpl sua = new ServletUtilAdapterImpl();
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
        long now = System.currentTimeMillis();
        long timeoutmSecs = 10000000000L;

        sua.setCacheTimeout(response, timeoutmSecs);

        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.VARY, "Accept-Encoding");
        Mockito.verify(response, Mockito.times(1)).setHeader(HttpHeaders.CACHE_CONTROL, "max-age=10000000, public");

        checkCacheDateHeaders(response, now, timeoutmSecs);

        Mockito.verifyNoMoreInteractions(response);
    }

    /**
     * check to make sure that the two date headers for caching are set correctly.
     */
    private void checkCacheDateHeaders(HttpServletResponse response, long now, long timeoutmSecs) {
        ArgumentCaptor<String> nameCaptors = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<Long> dateCaptors = ArgumentCaptor.forClass(Long.class);

        Mockito.verify(response, Mockito.times(2)).setDateHeader(nameCaptors.capture(), dateCaptors.capture());

        List<String> names = nameCaptors.getAllValues();
        List<Long> dates = dateCaptors.getAllValues();

        // allow arbitrary ordering.
        int expires = 0;
        int lastModified = 1;
        if (HttpHeaders.EXPIRES.equals(names.get(1))) {
            expires = 1;
            lastModified = 0;
        }
        assertEquals("Expires header should be 'EXPIRES'", HttpHeaders.EXPIRES, names.get(expires));
        assertTrue("Expires should be in the future at least the timeout",
                dates.get(expires).longValue() >= now + timeoutmSecs);
        assertEquals("Expires header should be 'LAST_MODIFIED'", HttpHeaders.LAST_MODIFIED,
                names.get(lastModified));
        assertTrue("LastModified should be in the past", dates.get(lastModified).longValue() < now);
    }

    /**
     * Unhandled exceptions such has InterruptedException should set response status to 500 for JS (and CSS)
     * so it doesn't cache in browser, appcache, etc
     */
    @Test
    public void testHandleJSExceptionManifestEnabled() throws Exception {
        PrintWriter writer = Mockito.mock(PrintWriter.class);
        HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
        ContextService mockContextService = Mockito.mock(ContextService.class);
        AuraContext mockContext = Mockito.mock(AuraContext.class);
        ConfigAdapter mockConfigAdapter = Mockito.mock(ConfigAdapter.class);
        InstanceStack mockInstanceStack = Mockito.mock(InstanceStack.class);
        List<String> stack = Lists.newArrayList();
        SerializationService mockSerializationService = Mockito.mock(SerializationService.class);
        ManifestUtil mockManifestUtil = Mockito.mock(ManifestUtil.class);

        Mockito.when(mockResponse.getWriter()).thenReturn(writer);
        Mockito.when(mockContext.getFormat()).thenReturn(AuraContext.Format.JS);
        Mockito.when(mockContext.getMode()).thenReturn(Mode.PROD);
        Mockito.when(mockContext.getInstanceStack()).thenReturn(mockInstanceStack);
        Mockito.when(mockConfigAdapter.isProduction()).thenReturn(true);
        Mockito.when(mockInstanceStack.getStackInfo()).thenReturn(stack);
        Mockito.when(mockContextService.getCurrentContext()).thenReturn(mockContext);
        Mockito.when(mockManifestUtil.isManifestEnabled()).thenReturn(true);
        Throwable exception = new InterruptedException("opps");

        ServletUtilAdapterImpl adapter = new ServletUtilAdapterImpl();
        adapter.setContextService(mockContextService);
        adapter.setConfigAdapter(mockConfigAdapter);
        adapter.setSerializationService(mockSerializationService);
        adapter.setManifestUtil(mockManifestUtil);
        adapter.handleServletException(exception, true, mockContext, mockRequest, mockResponse, true);

        // for JS with appCache enabled, SC_INTERNAL_SERVER_ERROR
        Mockito.verify(mockResponse).setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
        Mockito.verify(mockContextService, Mockito.atLeastOnce()).endContext();
    }

    @Test
    public void testHandleJSExceptionManifestDisabled() throws Exception {
        PrintWriter writer = Mockito.mock(PrintWriter.class);
        HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
        ContextService mockContextService = Mockito.mock(ContextService.class);
        AuraContext mockContext = Mockito.mock(AuraContext.class);
        ConfigAdapter mockConfigAdapter = Mockito.mock(ConfigAdapter.class);
        InstanceStack mockInstanceStack = Mockito.mock(InstanceStack.class);
        List<String> stack = Lists.newArrayList();
        SerializationService mockSerializationService = Mockito.mock(SerializationService.class);
        ManifestUtil mockManifestUtil = Mockito.mock(ManifestUtil.class);

        Mockito.when(mockResponse.getWriter()).thenReturn(writer);
        Mockito.when(mockContext.getFormat()).thenReturn(AuraContext.Format.JS);
        Mockito.when(mockContext.getMode()).thenReturn(Mode.PROD);
        Mockito.when(mockContext.getInstanceStack()).thenReturn(mockInstanceStack);
        Mockito.when(mockConfigAdapter.isProduction()).thenReturn(true);
        Mockito.when(mockInstanceStack.getStackInfo()).thenReturn(stack);
        Mockito.when(mockContextService.getCurrentContext()).thenReturn(mockContext);
        Mockito.when(mockManifestUtil.isManifestEnabled()).thenReturn(false);
        Throwable exception = new InterruptedException("opps");

        ServletUtilAdapterImpl adapter = new ServletUtilAdapterImpl();
        adapter.setContextService(mockContextService);
        adapter.setConfigAdapter(mockConfigAdapter);
        adapter.setSerializationService(mockSerializationService);
        adapter.setManifestUtil(mockManifestUtil);
        adapter.handleServletException(exception, true, mockContext, mockRequest, mockResponse, true);

        // for JS with appCache disabled, SC_OK
        Mockito.verify(mockResponse).setStatus(HttpStatus.SC_OK);
        Mockito.verify(mockResponse).setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store");
        Mockito.verify(mockContextService, Mockito.atLeastOnce()).endContext();
    }

    /**
     * Verifies first exception within handleServletException is caught and processed
     * we throw 'EmptyStackException' when getting InstanceStack, then verify
     * exceptionAdapter.handleException(death) is called with it
     */
    @Test
    public void testHandleExceptionDeathCaught() throws Exception {
        PrintWriter writer = Mockito.mock(PrintWriter.class);
        HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
        ContextService mockContextService = Mockito.mock(ContextService.class);
        AuraContext mockContext = Mockito.mock(AuraContext.class);
        ConfigAdapter mockConfigAdapter = Mockito.mock(ConfigAdapter.class);
        ExceptionAdapter mockExceptionAdapter = Mockito.mock(ExceptionAdapter.class);

        Throwable firstException = new EmptyStackException();

        Mockito.when(mockResponse.getWriter()).thenReturn(writer);
        Mockito.when(mockResponse.getStatus()).thenReturn(HttpStatus.SC_OK);
        Mockito.when(mockContext.getFormat()).thenReturn(AuraContext.Format.JSON);
        Mockito.when(mockContext.getMode()).thenReturn(Mode.PROD);
        Mockito.when(mockConfigAdapter.isProduction()).thenReturn(true);
        Mockito.when(mockContextService.getCurrentContext()).thenReturn(mockContext);
        Mockito.when(mockContext.getInstanceStack()).thenThrow(firstException);

        Throwable exception = new InterruptedException("opps");

        ServletUtilAdapterImpl adapter = Mockito.spy(new ServletUtilAdapterImpl());
        adapter.setContextService(mockContextService);
        adapter.setConfigAdapter(mockConfigAdapter);
        adapter.setExceptionAdapter(mockExceptionAdapter);
        adapter.handleServletException(exception, true, mockContext, mockRequest, mockResponse, true);

        ArgumentCaptor<Throwable> handledException = ArgumentCaptor.forClass(Throwable.class);
        Mockito.verify(mockExceptionAdapter, Mockito.times(2)).handleException(handledException.capture());

        assertTrue("Should handle EmptyStackException",
                handledException.getAllValues().get(1) instanceof EmptyStackException);

        Mockito.verify(mockResponse, Mockito.atLeastOnce()).setStatus(HttpStatus.SC_OK);
        Mockito.verify(mockContextService, Mockito.atLeastOnce()).endContext();
        Mockito.verify(adapter, Mockito.times(1)).setNoCache(mockResponse);
    }

    /**
     * Verifies second exception within handleServletException is caught and processed
     * we throw 'EmptyStackException' when getting InstanceStack, when
     * exceptionAdapter.handleException(death) handle the exception,
     * we throw second exception, then verify we printout the error message to response's writer
     */
    @Test
    public void testHandleExceptionDoubleDeathCaught() throws Exception {
        PrintWriter writer = Mockito.mock(PrintWriter.class);
        HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
        HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
        ContextService mockContextService = Mockito.mock(ContextService.class);
        AuraContext mockContext = Mockito.mock(AuraContext.class);
        ConfigAdapter mockConfigAdapter = Mockito.mock(ConfigAdapter.class);
        ExceptionAdapter mockExceptionAdapter = Mockito.mock(ExceptionAdapter.class);

        Throwable firstException = new EmptyStackException();
        String ccmeMsg = "double dead";
        Throwable secondException = new ConcurrentModificationException("double dead");

        Mockito.when(mockResponse.getWriter()).thenReturn(writer);
        Mockito.when(mockResponse.getStatus()).thenReturn(HttpStatus.SC_OK);
        Mockito.when(mockContext.getFormat()).thenReturn(AuraContext.Format.HTML);
        Mockito.when(mockContext.getMode()).thenReturn(Mode.DEV);
        Mockito.when(mockConfigAdapter.isProduction()).thenReturn(false);
        Mockito.when(mockContextService.getCurrentContext()).thenReturn(mockContext);
        Mockito.when(mockContext.getInstanceStack()).thenThrow(firstException);
        Mockito.when(mockExceptionAdapter.handleException(firstException)).thenThrow(secondException);

        Throwable exception = new InterruptedException("opps");

        ServletUtilAdapterImpl adapter = Mockito.spy(new ServletUtilAdapterImpl());
        adapter.setContextService(mockContextService);
        adapter.setConfigAdapter(mockConfigAdapter);
        adapter.setExceptionAdapter(mockExceptionAdapter);
        adapter.handleServletException(exception, true, mockContext, mockRequest, mockResponse, true);

        ArgumentCaptor<String> exceptionMessage = ArgumentCaptor.forClass(String.class);
        Mockito.verify(writer, Mockito.times(1)).println(exceptionMessage.capture());

        assertEquals(ccmeMsg, exceptionMessage.getValue());
        // in this case we return SC_OK, and we set non-cacheable.
        Mockito.verify(mockResponse, Mockito.atLeastOnce()).setStatus(HttpStatus.SC_OK);
        Mockito.verify(mockContextService, Mockito.atLeastOnce()).endContext();
        Mockito.verify(adapter, Mockito.atLeastOnce()).setNoCache(mockResponse);
    }
}