Factor out test class for getting GitilesView from a path

The alternative of refactoring GitilesView itself to make parse(path)
just work is tempting, but it turns out that GitilesViewTest is
testing more than just GitilesView. Specifically, it's testing that
the various regexes in the MetaServlet actually end up getting parsed
into the right positions.

The implementation is a bit ugly of course but the ugliness is
confined to the GitilesViewTest class.

Change-Id: I9d390b97883ee73fb7291226fd1e5caa4bc1c714
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java
index d3bf7cf..c429abe 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java
@@ -460,6 +460,14 @@
     this.anchor = anchor;
   }
 
+  public Builder copyFrom(GitilesView other) {
+    return new Builder(other.type).copyFrom(this);
+  }
+
+  public Builder toBuilder() {
+    return copyFrom(this);
+  }
+
   public String getHostName() {
     return hostName;
   }
diff --git a/gitiles-servlet/src/test/java/com/google/gitiles/TestViewFilter.java b/gitiles-servlet/src/test/java/com/google/gitiles/TestViewFilter.java
new file mode 100644
index 0000000..4f1e5ba
--- /dev/null
+++ b/gitiles-servlet/src/test/java/com/google/gitiles/TestViewFilter.java
@@ -0,0 +1,114 @@
+// Copyright (C) 2014 Google Inc. All Rights Reserved.
+//
+// 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.gitiles;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.gitiles.GitilesFilter.REPO_PATH_REGEX;
+import static com.google.gitiles.GitilesFilter.REPO_REGEX;
+import static com.google.gitiles.GitilesFilter.ROOT_REGEX;
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+
+import org.eclipse.jgit.http.server.glue.MetaFilter;
+import org.eclipse.jgit.http.server.glue.MetaServlet;
+import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
+import org.eclipse.jgit.junit.TestRepository;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** Run {@link ViewFilter} in a test environment. */
+class TestViewFilter {
+  static class Result {
+    private final GitilesView view;
+    private final FakeHttpServletResponse res;
+
+    private Result(GitilesView view, FakeHttpServletResponse res) {
+      this.view = view;
+      this.res = res;
+    }
+
+    GitilesView getView() {
+      return view;
+    }
+
+    FakeHttpServletResponse getResponse() {
+      return res;
+    }
+  }
+
+  static Result service(TestRepository<? extends DfsRepository> repo, String pathAndQuery)
+      throws IOException, ServletException {
+    TestServlet servlet = new TestServlet();
+    ViewFilter vf = new ViewFilter(
+        new TestGitilesAccess(repo.getRepository()),
+        TestGitilesUrls.URLS,
+        new VisibilityCache(false));
+    MetaFilter mf = new MetaFilter();
+
+    for (Pattern p : ImmutableList.of(ROOT_REGEX, REPO_REGEX, REPO_PATH_REGEX)) {
+      mf.serveRegex(p)
+          .through(vf)
+          .with(servlet);
+    }
+    FakeHttpServletResponse res = new FakeHttpServletResponse();
+    dummyServlet(mf).service(newRequest(repo, pathAndQuery), res);
+    if (servlet.view != null && servlet.view.getRepositoryName() != null) {
+      assertEquals(repo.getRepository().getDescription().getRepositoryName(),
+          servlet.view.getRepositoryName());
+    }
+    return new Result(servlet.view, res);
+  }
+
+  private static class TestServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    private GitilesView view;
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse res) {
+      checkState(view == null);
+      view = ViewFilter.getView(req);
+    }
+  }
+
+  private static FakeHttpServletRequest newRequest(TestRepository<? extends DfsRepository> repo,
+      String pathAndQuery) {
+    FakeHttpServletRequest req = FakeHttpServletRequest.newRequest(repo.getRepository());
+    int q = pathAndQuery.indexOf('?');
+    if (q > 0) {
+      req.setPathInfo(pathAndQuery.substring(0, q));
+      req.setQueryString(pathAndQuery.substring(q + 1));
+    } else {
+      req.setPathInfo(pathAndQuery);
+    }
+    return req;
+  }
+
+  private static MetaServlet dummyServlet(MetaFilter mf) {
+    return new MetaServlet(mf) {
+      private static final long serialVersionUID = 1L;
+    };
+  }
+
+  private TestViewFilter() {
+  }
+}
diff --git a/gitiles-servlet/src/test/java/com/google/gitiles/ViewFilterTest.java b/gitiles-servlet/src/test/java/com/google/gitiles/ViewFilterTest.java
index 581bee0..ed6cc79 100644
--- a/gitiles-servlet/src/test/java/com/google/gitiles/ViewFilterTest.java
+++ b/gitiles-servlet/src/test/java/com/google/gitiles/ViewFilterTest.java
@@ -14,21 +14,13 @@
 
 package com.google.gitiles;
 
-import static com.google.gitiles.FakeHttpServletRequest.newRequest;
-import static com.google.gitiles.GitilesFilter.REPO_PATH_REGEX;
-import static com.google.gitiles.GitilesFilter.REPO_REGEX;
-import static com.google.gitiles.GitilesFilter.ROOT_REGEX;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.net.HttpHeaders;
-import com.google.common.util.concurrent.Atomics;
 import com.google.gitiles.GitilesView.Type;
 
-import org.eclipse.jgit.http.server.glue.MetaFilter;
-import org.eclipse.jgit.http.server.glue.MetaServlet;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
@@ -38,13 +30,8 @@
 import org.junit.Test;
 
 import java.io.IOException;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Pattern;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 /** Tests for the view filter. */
 public class ViewFilterTest {
@@ -53,7 +40,7 @@
   @Before
   public void setUp() throws Exception {
     repo = new TestRepository<DfsRepository>(
-        new InMemoryRepository(new DfsRepositoryDescription("test")));
+        new InMemoryRepository(new DfsRepositoryDescription("repo")));
   }
 
   @Test
@@ -479,57 +466,16 @@
   }
 
   private String getRedirectUrl(String pathAndQuery) throws ServletException, IOException {
-    FakeHttpServletResponse res = new FakeHttpServletResponse();
-    service(pathAndQuery, Atomics.<GitilesView> newReference(), res);
-    assertEquals(302, res.getStatus());
-    return res.getHeader(HttpHeaders.LOCATION);
+    TestViewFilter.Result result = TestViewFilter.service(repo, pathAndQuery);
+    assertEquals(302, result.getResponse().getStatus());
+    return result.getResponse().getHeader(HttpHeaders.LOCATION);
   }
 
   private GitilesView getView(String pathAndQuery) throws ServletException, IOException {
-    AtomicReference<GitilesView> view = Atomics.newReference();
-    FakeHttpServletResponse res = new FakeHttpServletResponse();
-    service(pathAndQuery, view, res);
-    assertTrue("expected non-redirect status, got " + res.getStatus(),
-        res.getStatus() < 300 || res.getStatus() >= 400);
-    return view.get();
-  }
-
-  private void service(String pathAndQuery, final AtomicReference<GitilesView> view,
-      FakeHttpServletResponse res) throws ServletException, IOException {
-    HttpServlet testServlet = new HttpServlet() {
-      private static final long serialVersionUID = 1L;
-      @Override
-      protected void doGet(HttpServletRequest req, HttpServletResponse res) {
-        view.set(ViewFilter.getView(req));
-      }
-    };
-
-    ViewFilter vf = new ViewFilter(
-        new TestGitilesAccess(repo.getRepository()),
-        TestGitilesUrls.URLS,
-        new VisibilityCache(false));
-    MetaFilter mf = new MetaFilter();
-
-    for (Pattern p : ImmutableList.of(ROOT_REGEX, REPO_REGEX, REPO_PATH_REGEX)) {
-      mf.serveRegex(p)
-          .through(vf)
-          .with(testServlet);
-    }
-
-    FakeHttpServletRequest req = newRequest(repo.getRepository());
-    int q = pathAndQuery.indexOf('?');
-    if (q > 0) {
-      req.setPathInfo(pathAndQuery.substring(0, q));
-      req.setQueryString(pathAndQuery.substring(q + 1));
-    } else {
-      req.setPathInfo(pathAndQuery);
-    }
-    dummyServlet(mf).service(req, res);
-  }
-
-  private MetaServlet dummyServlet(MetaFilter mf) {
-    return new MetaServlet(mf) {
-      private static final long serialVersionUID = 1L;
-    };
+    TestViewFilter.Result result = TestViewFilter.service(repo, pathAndQuery);
+    FakeHttpServletResponse resp = result.getResponse();
+    assertTrue("expected non-redirect status, got " + resp.getStatus(),
+        resp.getStatus() < 300 || resp.getStatus() >= 400);
+    return result.getView();
   }
 }