Merge "Do not wrap nav links in unified diff view" into stable-2.12
diff --git a/gerrit-httpd/BUCK b/gerrit-httpd/BUCK
index da224d5..3085054 100644
--- a/gerrit-httpd/BUCK
+++ b/gerrit-httpd/BUCK
@@ -58,6 +58,8 @@
'//gerrit-reviewdb:server',
'//gerrit-server:server',
'//gerrit-util-http:http',
+ '//gerrit-util-http:testutil',
+ '//lib:jimfs',
'//lib:junit',
'//lib:gson',
'//lib:gwtorm',
@@ -69,6 +71,7 @@
'//lib/guice:guice-servlet',
'//lib/jgit:jgit',
'//lib/jgit:junit',
+ '//lib/joda:joda-time',
],
source_under_test = [':httpd'],
# TODO(sop) Remove after Buck supports Eclipse
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java
index 507bc59..6f7ad51 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ResourceServlet.java
@@ -26,6 +26,7 @@
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableMap;
@@ -96,10 +97,18 @@
private final Cache<Path, Resource> cache;
private final boolean refresh;
+ private final int cacheFileSizeLimitBytes;
protected ResourceServlet(Cache<Path, Resource> cache, boolean refresh) {
+ this(cache, refresh, CACHE_FILE_SIZE_LIMIT_BYTES);
+ }
+
+ @VisibleForTesting
+ ResourceServlet(Cache<Path, Resource> cache, boolean refresh,
+ int cacheFileSizeLimitBytes) {
this.cache = checkNotNull(cache, "cache");
this.refresh = refresh;
+ this.cacheFileSizeLimitBytes = cacheFileSizeLimitBytes;
}
/**
@@ -214,7 +223,7 @@
private boolean maybeStream(Path p, HttpServletRequest req,
HttpServletResponse rsp) throws IOException {
try {
- if (Files.size(p) < CACHE_FILE_SIZE_LIMIT_BYTES) {
+ if (Files.size(p) < cacheFileSizeLimitBytes) {
return false;
}
} catch (NoSuchFileException e) {
@@ -294,7 +303,12 @@
}
boolean isStale(Path p, ResourceServlet rs) throws IOException {
- FileTime t = rs.getLastModifiedTime(p);
+ FileTime t;
+ try {
+ t = rs.getLastModifiedTime(p);
+ } catch (NoSuchFileException e) {
+ return this != NOT_FOUND;
+ }
return t.toMillis() == 0
|| lastModified.toMillis() == 0
|| !lastModified.equals(t);
diff --git a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
index 10a35a8..94f3768 100644
--- a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
+++ b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/AllRequestFilterFilterProxyTest.java
@@ -22,6 +22,8 @@
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
import com.google.gerrit.server.plugins.Plugin;
+import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
+import com.google.gerrit.util.http.testutil.FakeHttpServletResponse;
import com.google.inject.Key;
import com.google.inject.util.Providers;
@@ -88,8 +90,8 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock(FilterConfig.class);
- HttpServletRequest req = ems.createMock(HttpServletRequest.class);
- HttpServletResponse res = ems.createMock(HttpServletResponse.class);
+ HttpServletRequest req = new FakeHttpServletRequest();
+ HttpServletResponse res = new FakeHttpServletResponse();
FilterChain chain = ems.createMock(FilterChain.class);
chain.doFilter(req, res);
@@ -110,8 +112,8 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock("config", FilterConfig.class);
- HttpServletRequest req = ems.createMock("req", HttpServletRequest.class);
- HttpServletResponse res = ems.createMock("res", HttpServletResponse.class);
+ HttpServletRequest req = new FakeHttpServletRequest();
+ HttpServletResponse res = new FakeHttpServletResponse();
FilterChain chain = ems.createMock("chain", FilterChain.class);
@@ -137,8 +139,8 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock(FilterConfig.class);
- HttpServletRequest req = ems.createMock(HttpServletRequest.class);
- HttpServletResponse res = ems.createMock(HttpServletResponse.class);
+ HttpServletRequest req = new FakeHttpServletRequest();
+ HttpServletResponse res = new FakeHttpServletResponse();
IMocksControl mockControl = ems.createStrictControl();
FilterChain chain = mockControl.createMock(FilterChain.class);
@@ -169,8 +171,8 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock(FilterConfig.class);
- HttpServletRequest req = ems.createMock(HttpServletRequest.class);
- HttpServletResponse res = ems.createMock(HttpServletResponse.class);
+ HttpServletRequest req = new FakeHttpServletRequest();
+ HttpServletResponse res = new FakeHttpServletResponse();
IMocksControl mockControl = ems.createStrictControl();
FilterChain chain = mockControl.createMock(FilterChain.class);
@@ -202,8 +204,8 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock(FilterConfig.class);
- HttpServletRequest req = ems.createMock(HttpServletRequest.class);
- HttpServletResponse res = ems.createMock(HttpServletResponse.class);
+ HttpServletRequest req = new FakeHttpServletRequest();
+ HttpServletResponse res = new FakeHttpServletResponse();
IMocksControl mockControl = ems.createStrictControl();
FilterChain chain = mockControl.createMock(FilterChain.class);
@@ -242,10 +244,10 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock(FilterConfig.class);
- HttpServletRequest req1 = ems.createMock("req1", HttpServletRequest.class);
- HttpServletRequest req2 = ems.createMock("req2", HttpServletRequest.class);
- HttpServletResponse res1 = ems.createMock("res1", HttpServletResponse.class);
- HttpServletResponse res2 = ems.createMock("res2", HttpServletResponse.class);
+ HttpServletRequest req1 = new FakeHttpServletRequest();
+ HttpServletRequest req2 = new FakeHttpServletRequest();
+ HttpServletResponse res1 = new FakeHttpServletResponse();
+ HttpServletResponse res2 = new FakeHttpServletResponse();
IMocksControl mockControl = ems.createStrictControl();
FilterChain chain = mockControl.createMock("chain", FilterChain.class);
@@ -294,12 +296,12 @@
EasyMockSupport ems = new EasyMockSupport();
FilterConfig config = ems.createMock(FilterConfig.class);
- HttpServletRequest req1 = ems.createMock("req1", HttpServletRequest.class);
- HttpServletRequest req2 = ems.createMock("req2", HttpServletRequest.class);
- HttpServletRequest req3 = ems.createMock("req3", HttpServletRequest.class);
- HttpServletResponse res1 = ems.createMock("res1", HttpServletResponse.class);
- HttpServletResponse res2 = ems.createMock("res2", HttpServletResponse.class);
- HttpServletResponse res3 = ems.createMock("res3", HttpServletResponse.class);
+ HttpServletRequest req1 = new FakeHttpServletRequest();
+ HttpServletRequest req2 = new FakeHttpServletRequest();
+ HttpServletRequest req3 = new FakeHttpServletRequest();
+ HttpServletResponse res1 = new FakeHttpServletResponse();
+ HttpServletResponse res2 = new FakeHttpServletResponse();
+ HttpServletResponse res3 = new FakeHttpServletResponse();
Plugin plugin = ems.createMock(Plugin.class);
diff --git a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/plugins/ContextMapperTest.java b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/plugins/ContextMapperTest.java
index e032823..9559e13 100644
--- a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/plugins/ContextMapperTest.java
+++ b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/plugins/ContextMapperTest.java
@@ -14,10 +14,9 @@
package com.google.gerrit.httpd.plugins;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
import org.junit.Test;
@@ -34,16 +33,17 @@
ContextMapper classUnderTest = new ContextMapper(CONTEXT);
HttpServletRequest originalRequest =
- createMockRequest("/plugins/", PLUGIN_NAME + "/" + RESOURCE);
+ createFakeRequest("/plugins/", PLUGIN_NAME + "/" + RESOURCE);
HttpServletRequest result =
classUnderTest.create(originalRequest, PLUGIN_NAME);
- assertEquals(CONTEXT + "/plugins/" + PLUGIN_NAME, result.getContextPath());
- assertEquals("", result.getServletPath());
- assertEquals("/" + RESOURCE, result.getPathInfo());
- assertEquals(CONTEXT + "/plugins/" + PLUGIN_NAME + "/" + RESOURCE,
- result.getRequestURI());
+ assertThat(result.getContextPath())
+ .isEqualTo(CONTEXT + "/plugins/" + PLUGIN_NAME);
+ assertThat(result.getServletPath()).isEqualTo("");
+ assertThat(result.getPathInfo()).isEqualTo("/" + RESOURCE);
+ assertThat(result.getRequestURI())
+ .isEqualTo(CONTEXT + "/plugins/" + PLUGIN_NAME + "/" + RESOURCE);
}
@Test
@@ -51,29 +51,22 @@
ContextMapper classUnderTest = new ContextMapper(CONTEXT);
HttpServletRequest originalRequest =
- createMockRequest("/a/plugins/", PLUGIN_NAME + "/" + RESOURCE);
+ createFakeRequest("/a/plugins/", PLUGIN_NAME + "/" + RESOURCE);
HttpServletRequest result =
classUnderTest.create(originalRequest, PLUGIN_NAME);
- assertEquals(CONTEXT + "/a/plugins/" + PLUGIN_NAME,
- result.getContextPath());
- assertEquals("", result.getServletPath());
- assertEquals("/" + RESOURCE, result.getPathInfo());
- assertEquals(CONTEXT + "/a/plugins/" + PLUGIN_NAME + "/" + RESOURCE,
- result.getRequestURI());
+ assertThat(result.getContextPath())
+ .isEqualTo(CONTEXT + "/a/plugins/" + PLUGIN_NAME);
+ assertThat(result.getServletPath()).isEqualTo("");
+ assertThat(result.getPathInfo()).isEqualTo("/" + RESOURCE);
+ assertThat(result.getRequestURI())
+ .isEqualTo(CONTEXT + "/a/plugins/" + PLUGIN_NAME + "/" + RESOURCE);
}
- private static HttpServletRequest createMockRequest(String servletPath,
+ private static FakeHttpServletRequest createFakeRequest(String servletPath,
String pathInfo) {
- HttpServletRequest req = createNiceMock(HttpServletRequest.class);
- expect(req.getContextPath()).andStubReturn(CONTEXT);
- expect(req.getServletPath()).andStubReturn(servletPath);
- expect(req.getPathInfo()).andStubReturn(pathInfo);
- String uri = CONTEXT + servletPath + pathInfo;
- expect(req.getRequestURI()).andStubReturn(uri);
- replay(req);
-
- return req;
+ return new FakeHttpServletRequest(
+ "gerrit.example.com", 80, CONTEXT, servletPath).setPathInfo(pathInfo);
}
}
diff --git a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/raw/ResourceServletTest.java b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/raw/ResourceServletTest.java
new file mode 100644
index 0000000..2ddd4eef
--- /dev/null
+++ b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/raw/ResourceServletTest.java
@@ -0,0 +1,337 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 com.google.gerrit.httpd.raw;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Strings;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Lists;
+import com.google.common.io.ByteStreams;
+import com.google.common.jimfs.Configuration;
+import com.google.common.jimfs.Jimfs;
+import com.google.gerrit.httpd.raw.ResourceServlet.Resource;
+import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
+import com.google.gerrit.util.http.testutil.FakeHttpServletResponse;
+
+import org.joda.time.format.ISODateTimeFormat;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.FileSystem;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.zip.GZIPInputStream;
+
+public class ResourceServletTest {
+ private static Cache<Path, Resource> newCache(int size) {
+ return CacheBuilder.newBuilder()
+ .maximumSize(size)
+ .recordStats()
+ .build();
+ }
+
+ private static class Servlet extends ResourceServlet {
+ private static final long serialVersionUID = 1L;
+
+ private final FileSystem fs;
+
+ private Servlet(FileSystem fs, Cache<Path, Resource> cache,
+ boolean refresh) {
+ super(cache, refresh);
+ this.fs = fs;
+ }
+
+ private Servlet(FileSystem fs, Cache<Path, Resource> cache,
+ boolean refresh, int cacheFileSizeLimitBytes) {
+ super(cache, refresh, cacheFileSizeLimitBytes);
+ this.fs = fs;
+ }
+
+ @Override
+ protected Path getResourcePath(String pathInfo) {
+ return fs.getPath("/" + CharMatcher.is('/').trimLeadingFrom(pathInfo));
+ }
+ }
+
+ private FileSystem fs;
+ private AtomicLong ts;
+
+ @Before
+ public void setUp() {
+ fs = Jimfs.newFileSystem(Configuration.unix());
+ ts = new AtomicLong(ISODateTimeFormat.dateTime().parseMillis(
+ "2010-01-30T12:00:00.000-08:00"));
+ }
+
+ @Test
+ public void notFoundWithoutRefresh() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, false);
+
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(request("/notfound"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_NOT_FOUND);
+ assertNotCacheable(res);
+ assertCacheHits(cache, 0, 1);
+
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/notfound"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_NOT_FOUND);
+ assertNotCacheable(res);
+ assertCacheHits(cache, 1, 1);
+ }
+
+ @Test
+ public void notFoundWithRefresh() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, true);
+
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(request("/notfound"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_NOT_FOUND);
+ assertNotCacheable(res);
+ assertCacheHits(cache, 0, 1);
+
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/notfound"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_NOT_FOUND);
+ assertNotCacheable(res);
+ assertCacheHits(cache, 1, 1);
+ }
+
+ @Test
+ public void smallFileWithRefresh() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, true);
+
+ writeFile("/foo", "foo1");
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertCacheable(res, true);
+ assertHasETag(res);
+ // Miss on getIfPresent, miss on get.
+ assertCacheHits(cache, 0, 2);
+
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertCacheable(res, true);
+ assertHasETag(res);
+ assertCacheHits(cache, 1, 2);
+
+ writeFile("/foo", "foo2");
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo2");
+ assertCacheable(res, true);
+ assertHasETag(res);
+ // Hit, invalidate, miss.
+ assertCacheHits(cache, 2, 3);
+ }
+
+ @Test
+ public void smallFileWithoutRefresh() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, false);
+
+ writeFile("/foo", "foo1");
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertCacheable(res, false);
+ assertHasETag(res);
+ // Miss on getIfPresent, miss on get.
+ assertCacheHits(cache, 0, 2);
+
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertCacheable(res, false);
+ assertHasETag(res);
+ assertCacheHits(cache, 1, 2);
+
+ writeFile("/foo", "foo2");
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertCacheable(res, false);
+ assertHasETag(res);
+ assertCacheHits(cache, 2, 2);
+ }
+
+ @Test
+ public void verySmallFileDoesntBotherWithGzip() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, true);
+ writeFile("/foo", "foo1");
+
+ FakeHttpServletRequest req = request("/foo")
+ .addHeader("Accept-Encoding", "gzip");
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(req, res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getHeader("Content-Encoding")).isNull();
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertHasETag(res);
+ assertCacheable(res, true);
+ }
+
+ @Test
+ public void smallFileWithGzip() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, true);
+ String content = Strings.repeat("a", 100);
+ writeFile("/foo", content);
+
+ FakeHttpServletRequest req = request("/foo")
+ .addHeader("Accept-Encoding", "gzip");
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(req, res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getHeader("Content-Encoding")).isEqualTo("gzip");
+ assertThat(gunzip(res.getActualBody())).isEqualTo(content);
+ assertHasETag(res);
+ assertCacheable(res, true);
+ }
+
+ @Test
+ public void largeFileBypassesCacheRegardlessOfRefreshParamter()
+ throws Exception {
+ for (boolean refresh : Lists.newArrayList(true, false)) {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, refresh, 3);
+
+ writeFile("/foo", "foo1");
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertThat(res.getHeader("Last-Modified")).isNotNull();
+ assertCacheable(res, refresh);
+ assertHasLastModified(res);
+ assertCacheHits(cache, 0, 1);
+
+ writeFile("/foo", "foo1");
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo1");
+ assertThat(res.getHeader("Last-Modified")).isNotNull();
+ assertCacheable(res, refresh);
+ assertHasLastModified(res);
+ assertCacheHits(cache, 0, 2);
+
+ writeFile("/foo", "foo2");
+ res = new FakeHttpServletResponse();
+ servlet.doGet(request("/foo"), res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getActualBodyString()).isEqualTo("foo2");
+ assertThat(res.getHeader("Last-Modified")).isNotNull();
+ assertCacheable(res, refresh);
+ assertHasLastModified(res);
+ assertCacheHits(cache, 0, 3);
+ }
+ }
+
+ @Test
+ public void largeFileWithGzip() throws Exception {
+ Cache<Path, Resource> cache = newCache(1);
+ Servlet servlet = new Servlet(fs, cache, true, 3);
+ String content = Strings.repeat("a", 100);
+ writeFile("/foo", content);
+
+ FakeHttpServletRequest req = request("/foo")
+ .addHeader("Accept-Encoding", "gzip");
+ FakeHttpServletResponse res = new FakeHttpServletResponse();
+ servlet.doGet(req, res);
+ assertThat(res.getStatus()).isEqualTo(SC_OK);
+ assertThat(res.getHeader("Content-Encoding")).isEqualTo("gzip");
+ assertThat(gunzip(res.getActualBody())).isEqualTo(content);
+ assertHasLastModified(res);
+ assertCacheable(res, true);
+ }
+
+ // TODO(dborowitz): Check MIME type.
+ // TODO(dborowitz): Test that JS is not gzipped.
+ // TODO(dborowitz): Test ?e parameter.
+ // TODO(dborowitz): Test If-None-Match behavior.
+ // TODO(dborowitz): Test If-Modified-Since behavior.
+
+ private void writeFile(String path, String content) throws Exception {
+ Files.write(fs.getPath(path), content.getBytes(UTF_8));
+ Files.setLastModifiedTime(
+ fs.getPath(path), FileTime.fromMillis(ts.getAndIncrement()));
+ }
+
+ private static void assertCacheHits(Cache<?, ?> cache, int hits, int misses) {
+ assertThat(cache.stats().hitCount()).named("hits").isEqualTo(hits);
+ assertThat(cache.stats().missCount()).named("misses").isEqualTo(misses);
+ }
+
+ private static void assertCacheable(FakeHttpServletResponse res,
+ boolean revalidate) {
+ String header = res.getHeader("Cache-Control").toLowerCase();
+ assertThat(header).contains("public");
+ if (revalidate) {
+ assertThat(header).contains("must-revalidate");
+ } else {
+ assertThat(header).doesNotContain("must-revalidate");
+ }
+ }
+
+ private static void assertHasLastModified(FakeHttpServletResponse res) {
+ assertThat(res.getHeader("Last-Modified")).isNotNull();
+ assertThat(res.getHeader("ETag")).isNull();
+ }
+
+ private static void assertHasETag(FakeHttpServletResponse res) {
+ assertThat(res.getHeader("ETag")).isNotNull();
+ assertThat(res.getHeader("Last-Modified")).isNull();
+ }
+
+ private static void assertNotCacheable(FakeHttpServletResponse res) {
+ assertThat(res.getHeader("Cache-Control")).contains("no-cache");
+ assertThat(res.getHeader("ETag")).isNull();
+ assertThat(res.getHeader("Last-Modified")).isNull();
+ }
+
+ private static FakeHttpServletRequest request(String path) {
+ return new FakeHttpServletRequest().setPathInfo(path);
+ }
+
+ private static String gunzip(byte[] data) throws Exception {
+ try (InputStream in = new GZIPInputStream(new ByteArrayInputStream(data))) {
+ return new String(ByteStreams.toByteArray(in), UTF_8);
+ }
+ }
+}
diff --git a/gerrit-util-http/BUCK b/gerrit-util-http/BUCK
index e770f60..e9b2a3d 100644
--- a/gerrit-util-http/BUCK
+++ b/gerrit-util-http/BUCK
@@ -5,11 +5,30 @@
visibility = ['PUBLIC'],
)
+TESTUTIL_SRCS = glob(['src/test/**/testutil/**/*.java'])
+
+java_library(
+ name = 'testutil',
+ srcs = TESTUTIL_SRCS,
+ deps = [
+ '//gerrit-extension-api:api',
+ '//lib:guava',
+ '//lib:servlet-api-3_1',
+ '//lib/httpcomponents:httpclient',
+ '//lib/jgit:jgit',
+ ],
+ visibility = ['PUBLIC'],
+)
+
java_test(
name = 'http_tests',
- srcs = glob(['src/test/java/**/*.java']),
+ srcs = glob(
+ ['src/test/java/**/*.java'],
+ excludes = TESTUTIL_SRCS,
+ ),
deps = [
':http',
+ ':testutil',
'//lib:junit',
'//lib:servlet-api-3_1',
'//lib:truth',
diff --git a/gerrit-util-http/src/test/java/com/google/gerrit/util/http/RequestUtilTest.java b/gerrit-util-http/src/test/java/com/google/gerrit/util/http/RequestUtilTest.java
index 42fcb16..e656e56 100644
--- a/gerrit-util-http/src/test/java/com/google/gerrit/util/http/RequestUtilTest.java
+++ b/gerrit-util-http/src/test/java/com/google/gerrit/util/http/RequestUtilTest.java
@@ -15,77 +15,50 @@
package com.google.gerrit.util.http;
import static com.google.common.truth.Truth.assertThat;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import org.junit.After;
-import org.junit.Before;
+import com.google.gerrit.util.http.testutil.FakeHttpServletRequest;
+
import org.junit.Test;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
public class RequestUtilTest {
- private List<Object> mocks;
-
- @Before
- public void setUp() {
- mocks = Collections.synchronizedList(new ArrayList<>());
- }
-
- @After
- public void tearDown() {
- for (Object mock : mocks) {
- verify(mock);
- }
- }
-
@Test
public void emptyContextPath() {
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/s/foo/bar", "", "/s"))).isEqualTo("/foo/bar");
+ fakeRequest("", "/s", "/foo/bar"))).isEqualTo("/foo/bar");
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/s/foo%2Fbar", "", "/s"))).isEqualTo("/foo%2Fbar");
+ fakeRequest("", "/s", "/foo%2Fbar"))).isEqualTo("/foo%2Fbar");
}
@Test
public void emptyServletPath() {
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/foo/bar", "", "/c"))).isEqualTo("/foo/bar");
+ fakeRequest("", "/c", "/foo/bar"))).isEqualTo("/foo/bar");
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/foo%2Fbar", "", "/c"))).isEqualTo("/foo%2Fbar");
+ fakeRequest("", "/c", "/foo%2Fbar"))).isEqualTo("/foo%2Fbar");
}
@Test
public void trailingSlashes() {
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/s/foo/bar/", "/c", "/s"))).isEqualTo("/foo/bar/");
+ fakeRequest("/c", "/s", "/foo/bar/"))).isEqualTo("/foo/bar/");
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/s/foo/bar///", "/c", "/s"))).isEqualTo("/foo/bar/");
+ fakeRequest("/c", "/s", "/foo/bar///"))).isEqualTo("/foo/bar/");
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/s/foo%2Fbar/", "/c", "/s"))).isEqualTo("/foo%2Fbar/");
+ fakeRequest("/c", "/s", "/foo%2Fbar/"))).isEqualTo("/foo%2Fbar/");
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/s/foo%2Fbar///", "/c", "/s"))).isEqualTo("/foo%2Fbar/");
+ fakeRequest("/c", "/s", "/foo%2Fbar///"))).isEqualTo("/foo%2Fbar/");
}
@Test
- public void servletPathMatchesRequestPath() {
+ public void emptyPathInfo() {
assertThat(RequestUtil.getEncodedPathInfo(
- mockRequest("/c/s", "/c", "/s"))).isNull();
+ fakeRequest("/c", "/s", ""))).isNull();
}
- private HttpServletRequest mockRequest(String uri, String contextPath, String servletPath) {
- HttpServletRequest req = createMock(HttpServletRequest.class);
- expect(req.getRequestURI()).andStubReturn(uri);
- expect(req.getContextPath()).andStubReturn(contextPath);
- expect(req.getServletPath()).andStubReturn(servletPath);
- replay(req);
- mocks.add(req);
- return req;
+ private FakeHttpServletRequest fakeRequest(String contextPath,
+ String servletPath, String pathInfo) {
+ FakeHttpServletRequest req = new FakeHttpServletRequest(
+ "gerrit.example.com", 80, contextPath, servletPath);
+ return req.setPathInfo(pathInfo);
}
}
diff --git a/gerrit-util-http/src/test/java/com/google/gerrit/util/http/testutil/FakeHttpServletRequest.java b/gerrit-util-http/src/test/java/com/google/gerrit/util/http/testutil/FakeHttpServletRequest.java
new file mode 100644
index 0000000..3991b95
--- /dev/null
+++ b/gerrit-util-http/src/test/java/com/google/gerrit/util/http/testutil/FakeHttpServletRequest.java
@@ -0,0 +1,488 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 com.google.gerrit.util.http.testutil;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Maps;
+import com.google.gerrit.extensions.restapi.Url;
+
+import org.apache.http.client.utils.DateUtils;
+
+import java.io.BufferedReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpUpgradeHandler;
+import javax.servlet.http.Part;
+
+/** Simple fake implementation of {@link HttpServletRequest}. */
+public class FakeHttpServletRequest implements HttpServletRequest {
+ public static final String SERVLET_PATH = "/b";
+
+ private final Map<String, Object> attributes;
+ private final ListMultimap<String, String> headers;
+
+ private ListMultimap<String, String> parameters;
+ private String hostName;
+ private int port;
+ private String contextPath;
+ private String servletPath;
+ private String path;
+
+ public FakeHttpServletRequest() {
+ this("gerrit.example.com", 80, "", SERVLET_PATH);
+ }
+
+ public FakeHttpServletRequest(String hostName, int port, String contextPath,
+ String servletPath) {
+ this.hostName = checkNotNull(hostName, "hostName");
+ checkArgument(port > 0);
+ this.port = port;
+ this.contextPath = checkNotNull(contextPath, "contextPath");
+ this.servletPath = checkNotNull(servletPath, "servletPath");
+ attributes = Maps.newConcurrentMap();
+ parameters = LinkedListMultimap.create();
+ headers = LinkedListMultimap.create();
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return attributes.get(name);
+ }
+
+ @Override
+ public Enumeration<String> getAttributeNames() {
+ return Collections.enumeration(attributes.keySet());
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return UTF_8.name();
+ }
+
+ @Override
+ public int getContentLength() {
+ return -1;
+ }
+
+ @Override
+ public String getContentType() {
+ return null;
+ }
+
+ @Override
+ public ServletInputStream getInputStream() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getLocalAddr() {
+ return "1.2.3.4";
+ }
+
+ @Override
+ public String getLocalName() {
+ return hostName;
+ }
+
+ @Override
+ public int getLocalPort() {
+ return port;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return Locale.US;
+ }
+
+ @Override
+ public Enumeration<Locale> getLocales() {
+ return Collections.enumeration(Collections.singleton(Locale.US));
+ }
+
+ @Override
+ public String getParameter(String name) {
+ return Iterables.getFirst(parameters.get(name), null);
+ }
+
+ private static final Function<Collection<String>, String[]> STRING_COLLECTION_TO_ARRAY =
+ new Function<Collection<String>, String[]>() {
+ @Override
+ public String[] apply(Collection<String> values) {
+ return values.toArray(new String[0]);
+ }
+ };
+
+ @Override
+ public Map<String, String[]> getParameterMap() {
+ return Collections.unmodifiableMap(
+ Maps.transformValues(parameters.asMap(), STRING_COLLECTION_TO_ARRAY));
+ }
+
+ @Override
+ public Enumeration<String> getParameterNames() {
+ return Collections.enumeration(parameters.keySet());
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ return STRING_COLLECTION_TO_ARRAY.apply(parameters.get(name));
+ }
+
+ public void setQueryString(String qs) {
+ ListMultimap<String, String> params = LinkedListMultimap.create();
+ for (String entry : Splitter.on('&').split(qs)) {
+ List<String> kv = Splitter.on('=').limit(2).splitToList(entry);
+ try {
+ params.put(URLDecoder.decode(kv.get(0), UTF_8.name()),
+ kv.size() == 2 ? URLDecoder.decode(kv.get(1), UTF_8.name()) : "");
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ parameters = params;
+ }
+
+ @Override
+ public String getProtocol() {
+ return "HTTP/1.1";
+ }
+
+ @Override
+ public BufferedReader getReader() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public String getRealPath(String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ return "5.6.7.8";
+ }
+
+ @Override
+ public String getRemoteHost() {
+ return "remotehost";
+ }
+
+ @Override
+ public int getRemotePort() {
+ return 1234;
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getScheme() {
+ return port == 443 ? "https" : "http";
+ }
+
+ @Override
+ public String getServerName() {
+ return hostName;
+ }
+
+ @Override
+ public int getServerPort() {
+ return port;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return port == 443;
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ attributes.remove(name);
+ }
+
+ @Override
+ public void setAttribute(String name, Object value) {
+ attributes.put(name, value);
+ }
+
+ @Override
+ public void setCharacterEncoding(String env) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getAuthType() {
+ return null;
+ }
+
+ @Override
+ public String getContextPath() {
+ return contextPath;
+ }
+
+ @Override
+ public Cookie[] getCookies() {
+ return new Cookie[0];
+ }
+
+ @Override
+ public long getDateHeader(String name) {
+ String v = getHeader(name);
+ return v != null ? DateUtils.parseDate(v).getTime() : 0;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ return Iterables.getFirst(headers.get(name), null);
+ }
+
+ @Override
+ public Enumeration<String> getHeaderNames() {
+ return Collections.enumeration(headers.keySet());
+ }
+
+ @Override
+ public Enumeration<String> getHeaders(String name) {
+ return Collections.enumeration(headers.get(name));
+ }
+
+ @Override
+ public int getIntHeader(String name) {
+ return Integer.parseInt(getHeader(name));
+ }
+
+ @Override
+ public String getMethod() {
+ return "GET";
+ }
+
+ @Override
+ public String getPathInfo() {
+ return path;
+ }
+
+ public FakeHttpServletRequest setPathInfo(String path) {
+ this.path = path;
+ return this;
+ }
+
+ @Override
+ public String getPathTranslated() {
+ return path;
+ }
+
+ @Override
+ public String getQueryString() {
+ return paramsToString(parameters);
+ }
+
+ @Override
+ public String getRemoteUser() {
+ return null;
+ }
+
+ @Override
+ public String getRequestURI() {
+ String uri = contextPath + servletPath + path;
+ if (!parameters.isEmpty()) {
+ uri += "?" + paramsToString(parameters);
+ }
+ return uri;
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ return null;
+ }
+
+ @Override
+ public String getRequestedSessionId() {
+ return null;
+ }
+
+ @Override
+ public String getServletPath() {
+ return servletPath;
+ }
+
+ @Override
+ public HttpSession getSession() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public HttpSession getSession(boolean create) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromCookie() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromURL() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public boolean isRequestedSessionIdFromUrl() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isRequestedSessionIdValid() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static String paramsToString(ListMultimap<String, String> params) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (Map.Entry<String, String> e : params.entries()) {
+ if (!first) {
+ sb.append('&');
+ } else {
+ first = false;
+ }
+ sb.append(Url.encode(e.getKey()));
+ if (!"".equals(e.getValue())) {
+ sb.append('=').append(Url.encode(e.getValue()));
+ }
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public AsyncContext getAsyncContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DispatcherType getDispatcherType() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isAsyncStarted() {
+ return false;
+ }
+
+ @Override
+ public boolean isAsyncSupported() {
+ return false;
+ }
+
+ @Override
+ public AsyncContext startAsync() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AsyncContext startAsync(ServletRequest req, ServletResponse res) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean authenticate(HttpServletResponse res) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Part getPart(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Collection<Part> getParts() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void login(String username, String password) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void logout() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getContentLengthLong() {
+ return getContentLength();
+ }
+
+ @Override
+ public String changeSessionId() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T extends HttpUpgradeHandler> T upgrade(
+ Class<T> httpUpgradeHandlerClass) {
+ throw new UnsupportedOperationException();
+ }
+
+ public FakeHttpServletRequest addHeader(String name, String value) {
+ headers.put(name, value);
+ return this;
+ }
+}
diff --git a/gerrit-util-http/src/test/java/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java b/gerrit-util-http/src/test/java/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java
new file mode 100644
index 0000000..442c474
--- /dev/null
+++ b/gerrit-util-http/src/test/java/com/google/gerrit/util/http/testutil/FakeHttpServletResponse.java
@@ -0,0 +1,289 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 com.google.gerrit.util.http.testutil;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.ListMultimap;
+import com.google.common.net.HttpHeaders;
+
+import org.eclipse.jgit.util.RawParseUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.Locale;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+/** Simple fake implementation of {@link HttpServletResponse}. */
+public class FakeHttpServletResponse implements HttpServletResponse {
+ private final ByteArrayOutputStream actualBody = new ByteArrayOutputStream();
+ private final ListMultimap<String, String> headers = LinkedListMultimap.create();
+
+ private int status = SC_OK;
+ private boolean committed;
+ private ServletOutputStream outputStream;
+ private PrintWriter writer;
+
+ public FakeHttpServletResponse() {
+ }
+
+ @Override
+ public synchronized void flushBuffer() throws IOException {
+ if (outputStream != null) {
+ outputStream.flush();
+ }
+ if (writer != null) {
+ writer.flush();
+ }
+ }
+
+ @Override
+ public int getBufferSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return UTF_8.name();
+ }
+
+ @Override
+ public String getContentType() {
+ return null;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return Locale.US;
+ }
+
+ @Override
+ public synchronized ServletOutputStream getOutputStream() {
+ checkState(writer == null, "getWriter() already called");
+ if (outputStream == null) {
+ outputStream = new ServletOutputStream() {
+ @Override
+ public void write(int c) throws IOException {
+ actualBody.write(c);
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener listener) {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ return outputStream;
+ }
+
+ @Override
+ public synchronized PrintWriter getWriter() {
+ checkState(outputStream == null, "getOutputStream() already called");
+ if (writer == null) {
+ writer = new PrintWriter(actualBody);
+ }
+ return writer;
+ }
+
+ @Override
+ public synchronized boolean isCommitted() {
+ return committed;
+ }
+
+ @Override
+ public void reset() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resetBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setBufferSize(int sz) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setCharacterEncoding(String name) {
+ checkArgument(UTF_8.equals(Charset.forName(name)),
+ "unsupported charset: %s", name);
+ }
+
+ @Override
+ public void setContentLength(int length) {
+ setContentLengthLong(length);
+ }
+
+ @Override
+ public void setContentLengthLong(long length) {
+ headers.removeAll(HttpHeaders.CONTENT_LENGTH);
+ addHeader(HttpHeaders.CONTENT_LENGTH, Long.toString(length));
+ }
+
+ @Override
+ public void setContentType(String type) {
+ headers.removeAll(HttpHeaders.CONTENT_TYPE);
+ addHeader(HttpHeaders.CONTENT_TYPE, type);
+ }
+
+ @Override
+ public void setLocale(Locale locale) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addCookie(Cookie cookie) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addDateHeader(String name, long value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addHeader(String name, String value) {
+ headers.put(name.toLowerCase(), value);
+ }
+
+ @Override
+ public void addIntHeader(String name, int value) {
+ addHeader(name, Integer.toString(value));
+ }
+
+ @Override
+ public boolean containsHeader(String name) {
+ return headers.containsKey(name.toLowerCase());
+ }
+
+ @Override
+ public String encodeRedirectURL(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public String encodeRedirectUrl(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String encodeURL(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public String encodeUrl(String url) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized void sendError(int sc) {
+ status = sc;
+ committed = true;
+ }
+
+ @Override
+ public synchronized void sendError(int sc, String msg) {
+ status = sc;
+ committed = true;
+ }
+
+ @Override
+ public synchronized void sendRedirect(String loc) {
+ status = SC_FOUND;
+ setHeader(HttpHeaders.LOCATION, loc);
+ committed = true;
+ }
+
+ @Override
+ public void setDateHeader(String name, long value) {
+ setHeader(name, Long.toString(value));
+ }
+
+ @Override
+ public void setHeader(String name, String value) {
+ headers.removeAll(name.toLowerCase());
+ addHeader(name, value);
+ }
+
+ @Override
+ public void setIntHeader(String name, int value) {
+ headers.removeAll(name.toLowerCase());
+ addIntHeader(name, value);
+ }
+
+ @Override
+ public synchronized void setStatus(int sc) {
+ status = sc;
+ committed = true;
+ }
+
+ @Override
+ @Deprecated
+ public synchronized void setStatus(int sc, String msg) {
+ status = sc;
+ committed = true;
+ }
+
+ @Override
+ public synchronized int getStatus() {
+ return status;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ return Iterables.getFirst(
+ headers.get(checkNotNull(name.toLowerCase())), null);
+ }
+
+ @Override
+ public Collection<String> getHeaderNames() {
+ return headers.keySet();
+ }
+
+ @Override
+ public Collection<String> getHeaders(String name) {
+ return headers.get(checkNotNull(name.toLowerCase()));
+ }
+
+ public byte[] getActualBody() {
+ return actualBody.toByteArray();
+ }
+
+ public String getActualBodyString() {
+ return RawParseUtils.decode(getActualBody());
+ }
+}
diff --git a/lib/BUCK b/lib/BUCK
index a92f910..c635bbb 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -184,6 +184,16 @@
license = 'protobuf',
)
+# Test-only dependencies below.
+
+maven_jar(
+ name = 'jimfs',
+ id = 'com.google.jimfs:jimfs:1.0',
+ sha1 = 'edd65a2b792755f58f11134e76485a928aab4c97',
+ license = 'DO_NOT_DISTRIBUTE',
+ deps = [':guava'],
+)
+
maven_jar(
name = 'junit',
id = 'junit:junit:4.11',