blob: b9e48905c47df368e28449a5dbf67b4c9174f626 [file] [log] [blame]
// Copyright 2021 Google LLC. 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.truth.Truth.assertThat;
import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.base.Strings;
import com.google.common.net.HttpHeaders;
import java.util.Optional;
import javax.annotation.Nullable;
import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for BranchRedirect. */
@RunWith(JUnit4.class)
public class BranchRedirectTest {
private static final String MASTER = "refs/heads/master";
private static final String MAIN = "refs/heads/main";
private static final String DEVELOP = "refs/heads/develop";
private static final String FOO = "refs/heads/foo";
private static final String BAR = "refs/heads/bar";
private static final String ORIGIN = "http://localhost";
private static final String QUERY_STRING_HTML = "format=html";
private static final String QUERY_STRING_JSON = "format=json";
private TestRepository<DfsRepository> repo;
private GitilesServlet servlet;
@Before
public void setUp() throws Exception {
repo = new TestRepository<>(new InMemoryRepository(new DfsRepositoryDescription("repo")));
BranchRedirect branchRedirect =
new BranchRedirect() {
@Override
protected Optional<String> getRedirectBranch(Repository repo, String sourceBranch) {
if (MASTER.equals(toFullBranchName(sourceBranch))) {
return Optional.of(MAIN);
}
if (FOO.equals(toFullBranchName(sourceBranch))) {
return Optional.of(BAR);
}
return Optional.empty();
}
};
servlet = TestGitilesServlet.create(repo, new GitwebRedirectFilter(), branchRedirect);
}
@Test
public void show_withoutRedirect() throws Exception {
repo.branch("develop").commit().add("foo", "contents").create();
String path = "/repo/+/refs/heads/develop/foo";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
}
@Test
public void show_withRedirect() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+/refs/heads/master/foo";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getActualBodyString()).contains("repo/+/refs/heads/main/foo");
assertThat(res.getActualBodyString()).doesNotContain("repo/+/refs/heads/master/foo");
}
@Test
public void show_withRedirect_onDefaultFormatType() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+/refs/heads/master/foo";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, null);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString()).contains("repo/+/refs/heads/main/foo");
assertThat(res.getActualBodyString()).doesNotContain("repo/+/refs/heads/master/foo");
}
@Test
public void show_withRedirect_usingShortRefInUrl() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+/master/foo";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString()).contains("repo/+/refs/heads/main/foo");
assertThat(res.getActualBodyString()).doesNotContain("repo/+/master/foo");
}
@Test
public void show_onAutomationRequest() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+/refs/heads/master/foo";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_JSON);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString()).contains("\"revision\": \"refs/heads/master\"");
assertThat(res.getActualBodyString()).contains("\"path\": \"foo\"");
}
@Test
public void showParent_withRedirect() throws Exception {
RevCommit parent = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MASTER).commit().add("bar", "contents").parent(parent).create();
repo.branch(MAIN).commit().parent(parent).create();
String path = "/repo/+/refs/heads/master^";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
// It is resolved to the object id by ViewFilter.
assertThat(res.getStatus()).isEqualTo(SC_MOVED_TEMPORARILY);
assertThat(res.getHeader(HttpHeaders.LOCATION))
.isEqualTo("/b/repo/+/" + parent.toObjectId().name() + "?format=html");
}
@Test
public void diff_withRedirect_onSingleBranch() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
repo.branch(DEVELOP).commit().add("foo", "contents").create();
String path = "/repo/+/refs/heads/master..refs/heads/develop";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString())
.contains("/b/repo/+/refs/heads/main..refs/heads/develop/?format=html");
}
@Test
public void diff_withRedirect_onBothBranch() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
RevCommit foo = repo.branch(FOO).commit().add("foo", "contents").create();
repo.branch(BAR).commit().parent(foo).create();
String path = "/repo/+/refs/heads/foo..refs/heads/master";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString())
.contains("/b/repo/+/refs/heads/bar..refs/heads/main/?format=html");
}
@Test
public void diff_withRedirect() throws Exception {
RevCommit master = repo.branch(MASTER).commit().add("foo", "contents").create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+diff/refs/heads/master^!";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString()).contains("/b/repo/+/refs/heads/main%5E%21/?format=html");
}
@Test
public void log_withRedirect() throws Exception {
repo.branch(MASTER).commit().add("foo", "contents").create();
RevCommit main = repo.branch(MAIN).commit().create();
String path = "/repo/+log/refs/heads/master";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString()).contains("Log - refs/heads/main");
assertThat(res.getActualBodyString()).contains("/b/repo/+/" + main.toObjectId().getName());
}
@Test
public void diff_withGrandParent_redirect() throws Exception {
RevCommit parent1 = repo.branch(MASTER).commit().add("foo", "contents").create();
RevCommit parent2 =
repo.branch(MASTER).commit().add("bar", "contents").parent(parent1).create();
RevCommit master = repo.branch(MASTER).commit().add("bar", "contents").parent(parent2).create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+diff/refs/heads/master^^..refs/heads/master";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString())
.contains("/b/repo/+/refs/heads/main%5E%5E..refs/heads/main/?format=html");
}
@Test
public void diff_withRelativeParent_redirect() throws Exception {
RevCommit parent1 = repo.branch(MASTER).commit().add("foo", "contents").create();
RevCommit parent2 =
repo.branch(MASTER).commit().add("bar", "contents").parent(parent1).create();
RevCommit master = repo.branch(MASTER).commit().add("bar", "contents").parent(parent2).create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+diff/refs/heads/master~1..refs/heads/master";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString()).contains("/b/repo/+/refs/heads/main%5E%21/?format=html");
}
@Test
public void diff_withRelativeGrandParent_redirect() throws Exception {
RevCommit parent1 = repo.branch(MASTER).commit().add("foo", "contents").create();
RevCommit parent2 =
repo.branch(MASTER).commit().add("bar", "contents").parent(parent1).create();
RevCommit master = repo.branch(MASTER).commit().add("bar", "contents").parent(parent2).create();
repo.branch(MAIN).commit().parent(master).create();
String path = "/repo/+diff/refs/heads/master~2..refs/heads/master";
FakeHttpServletRequest req = newHttpRequest(path, ORIGIN, QUERY_STRING_HTML);
FakeHttpServletResponse res = new FakeHttpServletResponse();
servlet.service(req, res);
assertThat(res.getStatus()).isEqualTo(SC_OK);
assertThat(res.getActualBodyString())
.contains("/b/repo/+/refs/heads/main%7E2..refs/heads/main/?format=html");
}
private static String toFullBranchName(String sourceBranch) {
if (sourceBranch.startsWith(Constants.R_REFS)) {
return sourceBranch;
}
return Constants.R_HEADS + sourceBranch;
}
private static FakeHttpServletRequest newHttpRequest(
String path, String origin, @Nullable String queryString) {
FakeHttpServletRequest req = FakeHttpServletRequest.newRequest();
req.setHeader(HttpHeaders.ORIGIN, origin);
req.setPathInfo(path);
if (!Strings.isNullOrEmpty(queryString)) {
req.setQueryString(queryString);
}
return req;
}
}