/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* 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.
* #L%
*/
package org.wisdom.resources;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.osgi.framework.Bundle;
import org.wisdom.api.configuration.ApplicationConfiguration;
import org.wisdom.api.crypto.Crypto;
import org.wisdom.api.crypto.Hash;
import org.wisdom.api.http.Context;
import org.wisdom.api.http.Result;
import org.wisdom.test.parents.Action;
import org.wisdom.test.parents.Invocation;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.wisdom.test.parents.Action.action;
/**
* Check the Web Jar Controller.
* <p/>
* IMPORTANT NOTE ABOUT Bundle urls:
* As it's not possible to use bundle:// (as the url handler is unknown, we use file://<bundle id>/path.
*/
public class WebJarControllerTest {
private File root = new File("target/wisdom-test");
private File webjars = new File(root, "assets/libs");
@Before
public void setUp() {
root.mkdirs();
}
@After
public void tearDown() {
FileUtils.deleteQuietly(root);
}
@Test
public void testOnMissingFolder() {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.indexSize()).isEqualTo(0);
assertThat(controller.libs().size()).isEqualTo(0);
}
@Test
public void testOnEmptyFolder() {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
webjars.mkdirs();
when(configuration.getBaseDir()).thenReturn(root);
WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.indexSize()).isEqualTo(0);
assertThat(controller.libs().size()).isEqualTo(0);
}
@Test
public void testOnFolderWithOneLibrary() throws IOException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
webjars.mkdirs();
// Copy autobahn
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs/0.8.2"), new File(webjars,
"autobahnjs/0.8.2"));
when(configuration.getBaseDir()).thenReturn(root);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.indexSize()).isEqualTo(1);
assertThat(controller.libs().size()).isEqualTo(1);
assertThat(controller.libs().get(0).name).isEqualTo("autobahnjs");
assertThat(controller.libs().get(0).version).isEqualTo("0.8.2");
assertThat(controller.libs().get(0).contains("autobahn.min.js")).isTrue();
assertThat(controller.libs().get(0).contains("autobahn.js")).isFalse();
assertThat(controller.libs().get(0).get("autobahn.min.js", mock(Context.class),
configuration, crypto).getStatusCode()).isEqualTo(200);
assertThat(controller.libs().get(0).get("autobahn.js", mock(Context.class),
configuration, crypto).getStatusCode()).isEqualTo(404);
// Try to serve.
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(404);
}
@Test
public void testAlternativeUrls() throws IOException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
webjars.mkdirs();
// Copy autobahn
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs/0.8.2"), new File(webjars,
"autobahnjs/0.8.2"));
when(configuration.getBaseDir()).thenReturn(root);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.indexSize()).isEqualTo(1);
assertThat(controller.libs().size()).isEqualTo(1);
// Just the file
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
// Just the library and file
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
// Just the library/version/file
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/0.8.2/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
// Missing version
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/0.8.x/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(404);
// Missing library
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autoba/0.8.2/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(404);
}
@Test
public void testAlternativeUrlsWhenTwoVersionOfTheSameLibAreThere() throws IOException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
webjars.mkdirs();
// Copy autobahn
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs/0.8.2"), new File(webjars,
"autobahnjs/0.8.2"));
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs/0.8.2-1"), new File(webjars,
"autobahnjs/0.8.2-1"));
when(configuration.getBaseDir()).thenReturn(root);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.indexSize()).isEqualTo(2);
assertThat(controller.libs().size()).isEqualTo(2);
// Just the file
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
// Just the library and file
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
// Just the library/version/file
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/0.8.2/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
assertThat(FileUtils.readFileToString((File) result.getResult().getRenderable().content())).contains("0.8.2")
.doesNotContain("0.8.2-1");
// Missing version
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/0.8.x/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(404);
// Second version
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahnjs/0.8.2-1/autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
assertThat(FileUtils.readFileToString((File) result.getResult().getRenderable().content())).contains("0.8.2-1");
}
@Test
public void testOnFolderWithTwoLibraries() throws Exception {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
webjars.mkdirs();
// Copy autobahn
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs/0.8.2"), new File(webjars,
"autobahnjs/0.8.2"));
FileUtils.copyDirectory(new File("target/test-classes/highcharts"), new File(webjars, "highcharts"));
when(configuration.getBaseDir()).thenReturn(root);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.libs().size()).isEqualTo(2);
// Try to serve.
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "highcharts.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
InputStream stream = result.getResult().getRenderable().render(null, null);
assertThat(IOUtils.toString(stream))
.contains("Highcharts JS v3.0.9 (2014-01-15)");
IOUtils.closeQuietly(stream);
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "adapters/mootools-adapter.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
stream = result.getResult().getRenderable().render(null, null);
assertThat(IOUtils.toString(stream))
.contains("MooTools adapter");
IOUtils.closeQuietly(stream);
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
stream = result.getResult().getRenderable().render(null, null);
assertThat(IOUtils.toString(stream))
.contains("var AUTOBAHNJS_VERSION=");
IOUtils.closeQuietly(stream);
}
@Test
public void testEtagAndCacheControl() throws IOException, InterruptedException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
when(crypto.hexSHA1(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
try {
String value = (String) invocation.getArguments()[0];
MessageDigest md;
md = MessageDigest.getInstance(Hash.SHA1.toString());
md.update(value.getBytes("utf-8"));
byte[] digest = md.digest();
return String.valueOf(Hex.encodeHex(digest));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
root = new File("target/wisdom-test");
webjars.mkdirs();
// Copy autobahn
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs"), new File(webjars, "autobahnjs"));
when(configuration.getBaseDir()).thenReturn(root);
when(configuration.getWithDefault(CacheUtils.HTTP_CACHE_CONTROL_MAX_AGE,
CacheUtils.HTTP_CACHE_CONTROL_DEFAULT)).thenReturn(CacheUtils
.HTTP_CACHE_CONTROL_DEFAULT);
when(configuration.getBooleanWithDefault(CacheUtils.HTTP_USE_ETAG,
CacheUtils.HTTP_USE_ETAG_DEFAULT)).thenReturn(CacheUtils.HTTP_USE_ETAG_DEFAULT);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
// First attempt
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
assertThat(result.getResult().getHeaders().get("Cache-Control")).isEqualTo("max-age=3600");
assertThat(result.getResult().getHeaders().get("Etag")).isNotNull();
String lastModified = result.getResult().getHeaders().get("Last-Modified");
String etag = result.getResult().getHeaders().get("Etag");
// If-None-Match (ETAG check)
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").header("If-None-Match", etag).invoke();
// Not modified.
assertThat(result.getResult().getStatusCode()).isEqualTo(304);
// If-Modified-Since (Date check)
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").header("If-Modified-Since", lastModified).invoke();
// Not modified.
assertThat(result.getResult().getStatusCode()).isEqualTo(304);
}
@Test
public void testOnBundleWithoutWebJars() {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
Bundle bundle = mock(Bundle.class);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(null);
WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
List<BundleWebJarLib> libs = controller.addingBundle(bundle, null);
assertThat(libs).isEmpty();
assertThat(controller.indexSize()).isEqualTo(0);
assertThat(controller.libs().size()).isEqualTo(0);
}
@Test
public void testOnBundleWithWebJarsDirButEmpty() throws MalformedURLException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
Bundle bundle = mock(Bundle.class);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(new URL("file://61/" + WebJarController.WEBJAR_LOCATION))
.iterator())
);
WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
List<BundleWebJarLib> libs = controller.addingBundle(bundle, null);
assertThat(libs).isEmpty();
assertThat(controller.indexSize()).isEqualTo(0);
assertThat(controller.libs().size()).isEqualTo(0);
// Same but with some junks.
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "foo/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "foo.txt")
).iterator())
);
controller = new WebJarController(crypto, configuration, "assets/libs");
libs = controller.addingBundle(bundle, null);
assertThat(libs).isEmpty();
assertThat(controller.indexSize()).isEqualTo(0);
assertThat(controller.libs().size()).isEqualTo(0);
}
@Test
public void testOnBundleWithWebJarsAndOneLib() throws MalformedURLException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
Bundle bundle = mock(Bundle.class);
when(bundle.getBundleId()).thenReturn(61l);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
List<BundleWebJarLib> libs = controller.addingBundle(bundle, null);
assertThat(libs).hasSize(1);
assertThat(controller.indexSize()).isEqualTo(1);
assertThat(controller.libs().size()).isEqualTo(1);
}
@Test
public void testOnBundleWithWebJarsAndTwoLibs() throws IOException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
Bundle bundle = mock(Bundle.class);
when(bundle.getBundleId()).thenReturn(61l);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "highcharts/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "highcharts/3.0.9/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "highcharts/3.0.9/highcharts.js"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "highcharts/3.0" +
".9/adapters/prototype-adapter.js")
).iterator())
);
when(bundle.findEntries("META-INF/resources/webjars/autobahnjs/0.8.2", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "highcharts/3.0.9", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "highcharts/3.0.9/highcharts.js"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "highcharts/3.0" +
".9/adapters/prototype-adapter.js")
).iterator())
);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
List<BundleWebJarLib> libs = controller.addingBundle(bundle, null);
assertThat(libs).hasSize(2);
assertThat(controller.libs().size()).isEqualTo(2);
Result result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).with().parameter("path", "autobahn.min.js").invoke().getResult();
assertThat(result.getStatusCode()).isEqualTo(200);
assertThat(((URL) result.getRenderable().content()).toExternalForm()).endsWith("autobahn.min.js");
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).with().parameter("path", "autobahnjs/autobahn.min.js").invoke().getResult();
assertThat(result.getStatusCode()).isEqualTo(200);
assertThat(((URL) result.getRenderable().content()).toExternalForm()).endsWith("autobahn.min.js");
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).with().parameter("path", "autobahnjs/0.8.2/autobahn.min.js").invoke().getResult();
assertThat(result.getStatusCode()).isEqualTo(200);
assertThat(((URL) result.getRenderable().content()).toExternalForm()).endsWith("autobahn.min.js");
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).with().parameter("path", "autobahnjs/autobahn.min.js2").invoke().getResult();
assertThat(result.getStatusCode()).isEqualTo(404);
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).with().parameter("path", "autobahnjs/0.8.3/autobahn.min.js").invoke().getResult();
assertThat(result.getStatusCode()).isEqualTo(404);
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).with().parameter("path", "autobahnjs2/autobahn.min.js").invoke().getResult();
assertThat(result.getStatusCode()).isEqualTo(404);
}
@Test
public void testBundleDynamics() throws MalformedURLException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
List<URL> entries = ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js"));
Bundle bundle = mock(Bundle.class);
when(bundle.getBundleId()).thenReturn(61l);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(entries.iterator()));
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
List<BundleWebJarLib> added = controller.addingBundle(bundle, null);
assertThat(added).hasSize(1);
assertThat(controller.libs().size()).isEqualTo(1);
assertThat(controller.indexSize()).isEqualTo(1);
// Uninstall.
controller.removedBundle(bundle, null, added);
assertThat(controller.indexSize()).isEqualTo(0);
assertThat(controller.libs().size()).isEqualTo(0);
// Re-install
// We need to restore the enumeration.
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(entries.iterator()));
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
added = controller.addingBundle(bundle, null);
assertThat(added).hasSize(1);
assertThat(controller.libs()).hasSize(1);
assertThat(controller.indexSize()).isEqualTo(1);
assertThat(controller.libs().get(0).version).isEqualTo("0.8.2");
// Update
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2-1/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2-1/autobahn.min.js")
).iterator())
);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2-1", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2-1/autobahn.min.js")
).iterator())
);
controller.modifiedBundle(bundle, null, added);
assertThat(controller.indexSize()).isEqualTo(1);
assertThat(controller.libs().size()).isEqualTo(1);
assertThat(controller.libs().get(0).version).isEqualTo("0.8.2-1");
}
@Test
public void testWithFileAndBundle() throws IOException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
when(configuration.getBaseDir()).thenReturn(root);
Bundle bundle = mock(Bundle.class);
when(bundle.getBundleId()).thenReturn(61l);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
webjars.mkdirs();
// Copy autobahn
FileUtils.copyDirectory(new File("target/test-classes/autobahnjs/0.8.2"), new File(webjars,
"autobahnjs/0.8.2"));
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
List<BundleWebJarLib> added = controller.addingBundle(bundle, null);
assertThat(added).hasSize(1);
assertThat(controller.libs().size()).isEqualTo(2);
assertThat(controller.libs().get(0)).isInstanceOf(FileWebJarLib.class);
assertThat(controller.libs().get(1)).isInstanceOf(BundleWebJarLib.class);
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
}
@Test
public void testEtagAndCacheControlForBundle() throws IOException, InterruptedException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
when(crypto.hexSHA1(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
try {
String value = (String) invocation.getArguments()[0];
MessageDigest md;
md = MessageDigest.getInstance(Hash.SHA1.toString());
md.update(value.getBytes("utf-8"));
byte[] digest = md.digest();
return String.valueOf(Hex.encodeHex(digest));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
});
root = new File("target/wisdom-test");
webjars.mkdirs();
when(configuration.getBaseDir()).thenReturn(root);
Bundle bundle = mock(Bundle.class);
when(bundle.getBundleId()).thenReturn(61l);
when(bundle.getLastModified()).thenReturn(60000l);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION, "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/"),
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
when(bundle.findEntries(WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2", "*", true)).thenReturn(
Iterators.asEnumeration(ImmutableList.of(
new URL("file://61/" + WebJarController.WEBJAR_LOCATION + "autobahnjs/0.8.2/autobahn.min.js")
).iterator())
);
when(configuration.getBaseDir()).thenReturn(root);
when(configuration.getWithDefault(CacheUtils.HTTP_CACHE_CONTROL_MAX_AGE,
CacheUtils.HTTP_CACHE_CONTROL_DEFAULT)).thenReturn(CacheUtils
.HTTP_CACHE_CONTROL_DEFAULT);
when(configuration.getBooleanWithDefault(CacheUtils.HTTP_USE_ETAG,
CacheUtils.HTTP_USE_ETAG_DEFAULT)).thenReturn(CacheUtils.HTTP_USE_ETAG_DEFAULT);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
controller.addingBundle(bundle, null);
// First attempt
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
assertThat(result.getResult().getHeaders().get("Cache-Control")).isEqualTo("max-age=3600");
assertThat(result.getResult().getHeaders().get("Etag")).isNotNull();
String lastModified = result.getResult().getHeaders().get("Last-Modified");
String etag = result.getResult().getHeaders().get("Etag");
// If-None-Match (ETAG check)
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").header("If-None-Match", etag).invoke();
// Not modified.
assertThat(result.getResult().getStatusCode()).isEqualTo(304);
// If-Modified-Since (Date check)
result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "autobahn.min.js").header("If-Modified-Since", lastModified).invoke();
// Not modified.
assertThat(result.getResult().getStatusCode()).isEqualTo(304);
}
@Test
public void testUrlsWhenRetrievingLastVersion() throws IOException {
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
Crypto crypto = mock(Crypto.class);
root = new File("target/wisdom-test");
webjars.mkdirs();
// Copy mock versioned lib
FileUtils.copyDirectory(new File("target/test-classes/mocklib/0.1.2"), new File(webjars,
"mocklib/0.1.2"));
FileUtils.copyDirectory(new File("target/test-classes/mocklib/0.2.5"), new File(webjars,
"mocklib/0.2.5"));
FileUtils.copyDirectory(new File("target/test-classes/mocklib/0.1.3"), new File(webjars,
"mocklib/0.1.3"));
when(configuration.getBaseDir()).thenReturn(root);
final WebJarController controller = new WebJarController(crypto, configuration, "assets/libs");
assertThat(root).isNotNull();
assertThat(controller.indexSize()).isEqualTo(3);
assertThat(controller.libs().size()).isEqualTo(3);
// Just the file
Action.ActionResult result = action(new Invocation() {
@Override
public Result invoke() throws Throwable {
return controller.serve();
}
}).parameter("path", "mocklib/mocklib.js").invoke();
assertThat(result.getResult().getStatusCode()).isEqualTo(200);
assertThat(FileUtils.readFileToString((File) result.getResult().getRenderable().content())).contains("0.2.5");
}
}