/*
* Copyright (c) 2008. All rights reserved.
*/
package ro.isdc.wro.model.resource.processor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.Random;
import java.util.concurrent.Callable;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.isdc.wro.config.Context;
import ro.isdc.wro.model.group.Inject;
import ro.isdc.wro.model.resource.Resource;
import ro.isdc.wro.model.resource.ResourceType;
import ro.isdc.wro.model.resource.processor.impl.css.CssUrlRewritingProcessor;
import ro.isdc.wro.model.resource.support.DefaultResourceAuthorizationManager;
import ro.isdc.wro.model.resource.support.ResourceAuthorizationManager;
import ro.isdc.wro.util.WroTestUtils;
/**
* Test for {@link CssUrlRewritingProcessor} class.
*
* @author Alex Objelean
* @created Created on Nov 3, 2008
*/
public class TestCssUrlRewritingProcessor {
private static final Logger LOG = LoggerFactory.getLogger(TestCssUrlRewritingProcessor.class);
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
@Mock
private FilterConfig filterConfig;
private CssUrlRewritingProcessor processor;
private static final String CSS_INPUT_NAME = "cssUrlRewriting.css";
@BeforeClass
public static void onBeforeClass() {
assertEquals(0, Context.countActive());
}
@AfterClass
public static void onAfterClass() {
assertEquals(0, Context.countActive());
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Context context = Context.webContext(request, response, filterConfig);
Context.set(context);
processor = new CssUrlRewritingProcessor() {
@Inject
private ResourceAuthorizationManager authorizationManager;
@Override
protected void onProcessCompleted() {
if (authorizationManager instanceof DefaultResourceAuthorizationManager) {
LOG.debug("allowed urls: {}", ((DefaultResourceAuthorizationManager) authorizationManager).list());
}
}
@Override
protected String getUrlPrefix() {
return "[WRO-PREFIX]?id=";
}
};
WroTestUtils.createInjector().inject(processor);
}
@After
public void tearDown() {
Context.unset();
}
@Test
public void testFromFolder()
throws Exception {
final URL url = getClass().getResource("cssUrlRewriting");
final File testFolder = new File(url.getFile(), "test");
final File expectedFolder = new File(url.getFile(), "expected");
WroTestUtils.compareFromDifferentFoldersByExtension(testFolder, expectedFolder, "css",
(ResourcePreProcessor) processor);
}
/**
* When background url contains a dataUri, the rewriting should have no effect.
*/
@Test
public void processResourceWithDataUriEncodedValue()
throws IOException {
final String resourceUri = "classpath:cssUrlRewriting-dataUri.css";
WroTestUtils.compareProcessedResourceContents(resourceUri, resourceUri, new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource(resourceUri), reader, writer);
}
});
}
/**
* Test a classpath css resource.
*/
@Test
public void processClasspathResourceType()
throws IOException {
final String resourceUri = "classpath:" + CSS_INPUT_NAME;
WroTestUtils.compareProcessedResourceContents(resourceUri, "classpath:cssUrlRewriting-classpath-outcome.css",
new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource(resourceUri), reader, writer);
}
});
}
/**
* @param resourceUri
* the resource should return.
* @return mocked {@link Resource} object.
*/
private Resource createMockResource(final String resourceUri) {
final Resource resource = Mockito.mock(Resource.class);
Mockito.when(resource.getUri()).thenReturn(resourceUri);
return resource;
}
/**
* Test a servletContext css resource.
*/
@Test
public void processServletContextResourceType()
throws IOException {
WroTestUtils.compareProcessedResourceContents("classpath:" + CSS_INPUT_NAME,
"classpath:cssUrlRewriting-servletContext-outcome.css", new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource("/static/img/" + CSS_INPUT_NAME), reader, writer);
}
});
}
/**
* Test a servletContext css resource.
*/
@Test
public void processServletContextResourceTypeWithAggregatedFolderSet()
throws IOException {
Context.get().setAggregatedFolderPath("wro/css");
WroTestUtils.compareProcessedResourceContents("classpath:" + CSS_INPUT_NAME,
"classpath:cssUrlRewriting-servletContext-aggregatedFolderSet-outcome.css", new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource("/static/img/" + CSS_INPUT_NAME), reader, writer);
}
});
}
/**
* Test a servletContext css resource.
*/
@Test
public void processServletContextResourceTypeWithNonRootContextPathSet()
throws IOException {
when(request.getContextPath()).thenReturn("/myapp");
WroTestUtils.compareProcessedResourceContents("classpath:" + CSS_INPUT_NAME,
"classpath:cssUrlRewriting-servletContext-nonRootContextPath-outcome.css", new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource("/static/img/" + CSS_INPUT_NAME), reader, writer);
}
});
}
/**
* Test a resource which is located inside WEB-INF protected folder.
*/
@Test
public void processWEBINFServletContextResourceType()
throws IOException {
WroTestUtils.compareProcessedResourceContents("classpath:" + CSS_INPUT_NAME,
"classpath:cssUrlRewriting-WEBINFservletContext-outcome.css", new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource("/WEB-INF/" + CSS_INPUT_NAME), reader, writer);
}
});
}
/**
* Test a url css resource.
*/
@Test
public void processUrlResourceType()
throws IOException {
WroTestUtils.compareProcessedResourceContents("classpath:" + CSS_INPUT_NAME,
"classpath:cssUrlRewriting-url-outcome.css", new ResourcePostProcessor() {
public void process(final Reader reader, final Writer writer)
throws IOException {
processor.process(createMockResource("http://www.site.com/static/css/" + CSS_INPUT_NAME), reader, writer);
}
});
}
@Test
public void checkUrlIsAllowed()
throws Exception {
processClasspathResourceType();
assertFalse(processor.isUriAllowed("/WEB-INF/web.xml"));
assertTrue(processor.isUriAllowed("classpath:folder/img.gif"));
}
@Test
public void shouldSupportOnlyCssResources() {
WroTestUtils.assertProcessorSupportResourceTypes(processor, ResourceType.CSS);
}
/**
* Tests that the Context injected into processor is thread safe and uses the values of set by the thread which runs
* the processor.
*/
@Test
public void shouldUseCorrectAggregatedFolderSetEvenWhenContextIsChangedInAnotherThread()
throws Exception {
WroTestUtils.createInjector().inject(processor);
WroTestUtils.runConcurrently(new Callable<Void>() {
public Void call()
throws Exception {
try {
Context.set(Context.standaloneContext());
if (new Random().nextBoolean()) {
processServletContextResourceTypeWithAggregatedFolderSet();
} else {
// ensure that a thread uses null aggregatedFolderPath which is injected into processor.
Context.get().setAggregatedFolderPath(null);
}
return null;
} finally {
Context.unset();
}
}
}, 20);
}
}