Extract base interface for VersionStrategy

This change splits out a base VersionPathStrategy interface that
focuses on where in the URL path the version is embedded.
This commit is contained in:
Rossen Stoyanchev
2014-07-28 15:48:21 -04:00
committed by Brian Clozel
parent 9f3c1cf762
commit d917b8a923
15 changed files with 307 additions and 346 deletions

View File

@@ -78,7 +78,7 @@ public class AppCacheManifestTransformerTests {
VersionResourceResolver versionResourceResolver = new VersionResourceResolver();
versionResourceResolver
.setVersionStrategyMap(Collections.singletonMap("/**", new ContentBasedVersionStrategy()));
.setStrategyMap(Collections.singletonMap("/**", new ContentVersionStrategy()));
List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>();
resolvers.add(versionResourceResolver);

View File

@@ -15,10 +15,7 @@
*/
package org.springframework.web.servlet.resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
@@ -31,65 +28,50 @@ import org.springframework.util.FileCopyUtils;
import static org.junit.Assert.*;
/**
* Unit tests for {@link org.springframework.web.servlet.resource.ContentBasedVersionStrategy}
* Unit tests for {@link ContentVersionStrategy}
* @author Brian Clozel
*/
public class ContentBasedVersionStrategyTests {
private List<Resource> locations;
private ContentVersionStrategy versionStrategy = new ContentVersionStrategy();
private ContentBasedVersionStrategy versionStrategy = new ContentBasedVersionStrategy();
private ResourceResolverChain chain;
@Before
public void setup() {
this.locations = new ArrayList<Resource>();
this.locations.add(new ClassPathResource("test/", getClass()));
this.locations.add(new ClassPathResource("testalternatepath/", getClass()));
VersionResourceResolver versionResourceResolver = new VersionResourceResolver();
versionResourceResolver.setVersionStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
this.chain = new DefaultResourceResolverChain(Arrays.asList(versionResourceResolver, new PathResourceResolver()));
versionResourceResolver.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
}
@Test
public void extractVersionFromPath() throws Exception {
public void extractVersion() throws Exception {
String hash = "7fbe76cdac6093784895bb4989203e5a";
String path = "font-awesome/css/font-awesome.min-" + hash + ".css";
assertEquals(hash, this.versionStrategy.extractVersionFromPath(path));
assertEquals("", this.versionStrategy.extractVersionFromPath("foo/bar.css"));
assertEquals(hash, this.versionStrategy.extractVersion(path));
assertNull(this.versionStrategy.extractVersion("foo/bar.css"));
}
@Test
public void deleteVersionFromPath() throws Exception {
public void removeVersion() throws Exception {
String file = "font-awesome/css/font-awesome.min%s%s.css";
String hash = "7fbe76cdac6093784895bb4989203e5a";
assertEquals(String.format(file, "", ""), this.versionStrategy.deleteVersionFromPath(String.format(file, "-", hash), hash));
assertEquals("", this.versionStrategy.extractVersionFromPath("foo/bar.css"));
assertEquals(String.format(file, "", ""), this.versionStrategy.removeVersion(String.format(file, "-", hash), hash));
assertNull(this.versionStrategy.extractVersion("foo/bar.css"));
}
@Test
public void resourceVersionMatches() throws Exception {
public void getResourceVersion() throws Exception {
Resource expected = new ClassPathResource("test/bar.css", getClass());
String hash = DigestUtils.md5DigestAsHex(FileCopyUtils.copyToByteArray(expected.getInputStream()));
String wrongHash = "wronghash";
assertTrue(this.versionStrategy.resourceVersionMatches(expected, hash));
assertFalse(this.versionStrategy.resourceVersionMatches(expected, wrongHash));
assertEquals(hash, this.versionStrategy.getResourceVersion(expected));
}
@Test
public void addVersionToUrl() throws Exception {
String file = "bar.css";
Resource expected = new ClassPathResource("test/" + file, getClass());
String hash = DigestUtils.md5DigestAsHex(FileCopyUtils.copyToByteArray(expected.getInputStream()));
String path = "bar-" + hash + ".css";
String resultUrl = this.versionStrategy.addVersionToUrl(file, this.locations, this.chain);
assertEquals(path, resultUrl);
String requestPath = "test/bar.css";
String version = "123";
assertEquals("test/bar-123.css", this.versionStrategy.addVersion(requestPath, version));
}
}

View File

@@ -50,9 +50,9 @@ public class CssLinkResourceTransformerTests {
@Before
public void setUp() {
Map<String, VersionStrategy> versionStrategyMap = new HashMap<>();
versionStrategyMap.put("/**", new ContentBasedVersionStrategy());
versionStrategyMap.put("/**", new ContentVersionStrategy());
VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.setVersionStrategyMap(versionStrategyMap);
versionResolver.setStrategyMap(versionStrategyMap);
List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>();
resolvers.add(versionResolver);

View File

@@ -15,16 +15,11 @@
*/
package org.springframework.web.servlet.resource;
import java.util.Collections;
import java.util.concurrent.Callable;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.springframework.core.io.Resource;
/**
* Unit tests for {@link org.springframework.web.servlet.resource.FixedVersionStrategy}
* @author Brian Clozel
@@ -33,49 +28,36 @@ public class FixedVersionStrategyTests {
private final String version = "1df341f";
private final String resourceId = "js/foo.js";
private final String path = "js/foo.js";
private FixedVersionStrategy strategy;
private FixedVersionStrategy versionStrategy;
@Before
public void setup() {
this.versionStrategy = new FixedVersionStrategy(this.version);
this.strategy = new FixedVersionStrategy(this.version);
}
@Test(expected = IllegalArgumentException.class)
public void constructWithEmptyPrefixVersion() throws Exception {
FixedVersionStrategy versionStrategy = new FixedVersionStrategy(" ");
}
@Test(expected = IllegalArgumentException.class)
public void constructWithEmptyCallableVersion() throws Exception {
FixedVersionStrategy versionStrategy = new FixedVersionStrategy(
new Callable<String>() {
@Override
public String call() throws Exception {
return " ";
}
});
public void emptyPrefixVersion() throws Exception {
new FixedVersionStrategy(" ");
}
@Test
public void extractVersionFromPath() throws Exception {
assertEquals(this.version + "/", this.versionStrategy.extractVersionFromPath(this.version + "/" + this.resourceId));
assertEquals("", this.versionStrategy.extractVersionFromPath(this.resourceId));
public void extractVersion() throws Exception {
assertEquals(this.version, this.strategy.extractVersion(this.version + "/" + this.path));
assertNull(this.strategy.extractVersion(this.path));
}
@Test
public void deleteVersionFromPath() throws Exception {
assertEquals(this.resourceId,
this.versionStrategy.deleteVersionFromPath(this.version + "/" + this.resourceId, this.version + "/"));
public void removeVersion() throws Exception {
assertEquals("/" + this.path, this.strategy.removeVersion(this.version + "/" + this.path, this.version));
}
@Test
public void addVersionToUrl() throws Exception {
assertEquals(this.version + "/" + this.resourceId,
this.versionStrategy.addVersionToUrl(this.resourceId, Collections.<Resource>emptyList(), null));
public void addVersion() throws Exception {
assertEquals(this.version + "/" + this.path, this.strategy.addVersion(this.path, this.version));
}
}

View File

@@ -71,9 +71,9 @@ public class GzipResourceResolverTests {
@Before
public void setUp() {
Map<String, VersionStrategy> versionStrategyMap = new HashMap<>();
versionStrategyMap.put("/**", new ContentBasedVersionStrategy());
versionStrategyMap.put("/**", new ContentVersionStrategy());
VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.setVersionStrategyMap(versionStrategyMap);
versionResolver.setStrategyMap(versionStrategyMap);
List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>();
resolvers.add(new GzipResourceResolver());

View File

@@ -115,9 +115,9 @@ public class ResourceUrlProviderJavaConfigTests {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
Map<String, VersionStrategy> versionStrategyMap = new HashMap<>();
versionStrategyMap.put("/**", new ContentBasedVersionStrategy());
versionStrategyMap.put("/**", new ContentVersionStrategy());
VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.setVersionStrategyMap(versionStrategyMap);
versionResolver.setStrategyMap(versionStrategyMap);
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:org/springframework/web/servlet/resource/test/")

View File

@@ -68,9 +68,9 @@ public class ResourceUrlProviderTests {
@Test
public void getFingerprintedResourceUrl() {
Map<String, VersionStrategy> versionStrategyMap = new HashMap<>();
versionStrategyMap.put("/**", new ContentBasedVersionStrategy());
versionStrategyMap.put("/**", new ContentVersionStrategy());
VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.setVersionStrategyMap(versionStrategyMap);
versionResolver.setStrategyMap(versionStrategyMap);
List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>();
resolvers.add(versionResolver);

View File

@@ -40,7 +40,7 @@ public class VersionResourceResolverTests {
private List<Resource> locations;
private VersionResourceResolver versionResourceResolver;
private VersionResourceResolver resolver;
private ResourceResolverChain chain;
@@ -49,126 +49,118 @@ public class VersionResourceResolverTests {
@Before
public void setup() {
this.locations = new ArrayList<Resource>();
this.locations = new ArrayList<>();
this.locations.add(new ClassPathResource("test/", getClass()));
this.locations.add(new ClassPathResource("testalternatepath/", getClass()));
this.versionResourceResolver = new VersionResourceResolver();
this.resolver = new VersionResourceResolver();
this.chain = mock(ResourceResolverChain.class);
this.versionStrategy = mock(VersionStrategy.class);
}
@Test
public void resolveResourceInternalExisting() throws Exception {
public void resolveResourceExisting() throws Exception {
String file = "bar.css";
Resource expected = new ClassPathResource("test/" + file, getClass());
when(this.chain.resolveResource(null, file, this.locations)).thenReturn(expected);
this.versionResourceResolver
.setVersionStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.versionResourceResolver.resolveResourceInternal(null, file, this.locations, this.chain);
this.resolver.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.resolver.resolveResourceInternal(null, file, this.locations, this.chain);
assertEquals(expected, actual);
verify(this.chain, times(1)).resolveResource(null, file, this.locations);
verify(this.versionStrategy, never()).extractVersionFromPath(file);
verify(this.versionStrategy, never()).extractVersion(file);
}
@Test
public void resolveResourceInternalNoStrategy() throws Exception {
public void resolveResourceNoVersionStrategy() throws Exception {
String file = "missing.css";
when(this.chain.resolveResource(null, file, this.locations)).thenReturn(null);
this.versionResourceResolver.setVersionStrategyMap(Collections.emptyMap());
Resource actual = this.versionResourceResolver.resolveResourceInternal(null, file, this.locations, this.chain);
this.resolver.setStrategyMap(Collections.emptyMap());
Resource actual = this.resolver.resolveResourceInternal(null, file, this.locations, this.chain);
assertNull(actual);
verify(this.chain, times(1)).resolveResource(null, file, this.locations);
}
@Test
public void resolveResourceInternalNoCandidateVersion() throws Exception {
public void resolveResourceNoVersionInPath() throws Exception {
String file = "bar.css";
when(this.chain.resolveResource(null, file, this.locations)).thenReturn(null);
when(this.versionStrategy.extractVersionFromPath(file)).thenReturn("");
when(this.versionStrategy.extractVersion(file)).thenReturn("");
this.versionResourceResolver
.setVersionStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.versionResourceResolver.resolveResourceInternal(null, file, this.locations, this.chain);
this.resolver.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.resolver.resolveResourceInternal(null, file, this.locations, this.chain);
assertNull(actual);
verify(this.chain, times(1)).resolveResource(null, file, this.locations);
verify(this.versionStrategy, times(1)).extractVersionFromPath(file);
verify(this.versionStrategy, times(1)).extractVersion(file);
}
@Test
public void resolveResourceInternalNoBaseResource() throws Exception {
public void resolveResourceNoResourceAfterVersionRemoved() throws Exception {
String versionFile = "bar-version.css";
String version = "version";
String file = "bar.css";
when(this.chain.resolveResource(null, versionFile, this.locations)).thenReturn(null);
when(this.chain.resolveResource(null, file, this.locations)).thenReturn(null);
when(this.versionStrategy.extractVersionFromPath(versionFile)).thenReturn(version);
when(this.versionStrategy.deleteVersionFromPath(versionFile, version)).thenReturn(file);
when(this.versionStrategy.extractVersion(versionFile)).thenReturn(version);
when(this.versionStrategy.removeVersion(versionFile, version)).thenReturn(file);
this.versionResourceResolver
.setVersionStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.versionResourceResolver.resolveResourceInternal(null, versionFile, this.locations, this.chain);
this.resolver.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.resolver.resolveResourceInternal(null, versionFile, this.locations, this.chain);
assertNull(actual);
verify(this.versionStrategy, times(1)).deleteVersionFromPath(versionFile, version);
verify(this.versionStrategy, times(1)).removeVersion(versionFile, version);
}
@Test
public void resolveResourceInternalNoMatch() throws Exception {
public void resolveResourceVersionDoesNotMatch() throws Exception {
String versionFile = "bar-version.css";
String version = "version";
String file = "bar.css";
Resource expected = new ClassPathResource("test/" + file, getClass());
when(this.chain.resolveResource(null, versionFile, this.locations)).thenReturn(null);
when(this.chain.resolveResource(null, file, this.locations)).thenReturn(expected);
when(this.versionStrategy.extractVersionFromPath(versionFile)).thenReturn(version);
when(this.versionStrategy.deleteVersionFromPath(versionFile, version)).thenReturn(file);
when(this.versionStrategy.resourceVersionMatches(expected, version)).thenReturn(false);
when(this.versionStrategy.extractVersion(versionFile)).thenReturn(version);
when(this.versionStrategy.removeVersion(versionFile, version)).thenReturn(file);
when(this.versionStrategy.getResourceVersion(expected)).thenReturn("newer-version");
this.versionResourceResolver
.setVersionStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.versionResourceResolver.resolveResourceInternal(null, versionFile, this.locations, this.chain);
this.resolver.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.resolver.resolveResourceInternal(null, versionFile, this.locations, this.chain);
assertNull(actual);
verify(this.versionStrategy, times(1)).resourceVersionMatches(expected, version);
verify(this.versionStrategy, times(1)).getResourceVersion(expected);
}
@Test
public void resolveResourceInternalMatch() throws Exception {
public void resolveResourceSuccess() throws Exception {
String versionFile = "bar-version.css";
String version = "version";
String file = "bar.css";
Resource expected = new ClassPathResource("test/" + file, getClass());
when(this.chain.resolveResource(null, versionFile, this.locations)).thenReturn(null);
when(this.chain.resolveResource(null, file, this.locations)).thenReturn(expected);
when(this.versionStrategy.extractVersionFromPath(versionFile)).thenReturn(version);
when(this.versionStrategy.deleteVersionFromPath(versionFile, version)).thenReturn(file);
when(this.versionStrategy.resourceVersionMatches(expected, version)).thenReturn(true);
when(this.versionStrategy.extractVersion(versionFile)).thenReturn(version);
when(this.versionStrategy.removeVersion(versionFile, version)).thenReturn(file);
when(this.versionStrategy.getResourceVersion(expected)).thenReturn(version);
this.versionResourceResolver
.setVersionStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.versionResourceResolver.resolveResourceInternal(null, versionFile, this.locations, this.chain);
this.resolver
.setStrategyMap(Collections.singletonMap("/**", this.versionStrategy));
Resource actual = this.resolver.resolveResourceInternal(null, versionFile, this.locations, this.chain);
assertEquals(expected, actual);
verify(this.versionStrategy, times(1)).resourceVersionMatches(expected, version);
verify(this.versionStrategy, times(1)).getResourceVersion(expected);
}
@Test
public void findStrategy() throws Exception {
public void getStrategyForPath() throws Exception {
Map<String, VersionStrategy> strategies = new HashMap<>();
VersionStrategy jsStrategy = mock(VersionStrategy.class);
VersionStrategy catchAllStrategy = mock(VersionStrategy.class);
strategies.put("/**", catchAllStrategy);
strategies.put("/**/*.js", jsStrategy);
this.versionResourceResolver.setVersionStrategyMap(strategies);
this.resolver.setStrategyMap(strategies);
assertEquals(catchAllStrategy, this.versionResourceResolver.findStrategy("foo.css"));
assertEquals(catchAllStrategy, this.versionResourceResolver.findStrategy("foo-js.css"));
assertEquals(jsStrategy, this.versionResourceResolver.findStrategy("foo.js"));
assertEquals(jsStrategy, this.versionResourceResolver.findStrategy("bar/foo.js"));
assertEquals(catchAllStrategy, this.resolver.getStrategyForPath("foo.css"));
assertEquals(catchAllStrategy, this.resolver.getStrategyForPath("foo-js.css"));
assertEquals(jsStrategy, this.resolver.getStrategyForPath("foo.js"));
assertEquals(jsStrategy, this.resolver.getStrategyForPath("bar/foo.js"));
}
}