/*
 * Copyright (C) 2010, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.http.test;

import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jgit.errors.RemoteRepositoryException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.junit.TestRng;
import org.eclipse.jgit.junit.http.AccessEvent;
import org.eclipse.jgit.junit.http.AppServer;
import org.eclipse.jgit.junit.http.HttpTestCase;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.util.HttpSupport;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class SmartClientSmartServerTest extends HttpTestCase {
	private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";

	private Repository remoteRepository;

	private URIish remoteURI;

	private URIish brokenURI;

	private URIish redirectURI;

	private RevBlob A_txt;

	private RevCommit A, B;

	@Parameters
	public static Collection<Object[]> data() {
		// run all tests with both connection factories we have
		return Arrays.asList(new Object[][] {
				{ new JDKHttpConnectionFactory() },
				{ new HttpClientConnectionFactory() } });
	}

	public SmartClientSmartServerTest(HttpConnectionFactory cf) {
		HttpTransport.setConnectionFactory(cf);
	}

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();

		final TestRepository<Repository> src = createTestRepository();
		final String srcName = src.getRepository().getDirectory().getName();
		src.getRepository()
				.getConfig()
				.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
						ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);

		GitServlet gs = new GitServlet();

		ServletContextHandler app = addNormalContext(gs, src, srcName);

		ServletContextHandler broken = addBrokenContext(gs, src, srcName);

		ServletContextHandler redirect = addRedirectContext(gs, src, srcName);

		server.setUp();

		remoteRepository = src.getRepository();
		remoteURI = toURIish(app, srcName);
		brokenURI = toURIish(broken, srcName);
		redirectURI = toURIish(redirect, srcName);

		A_txt = src.blob("A");
		A = src.commit().add("A_txt", A_txt).create();
		B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
		src.update(master, B);

		src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
	}

	private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
		ServletContextHandler app = server.addContext("/git");
		gs.setRepositoryResolver(new TestRepoResolver(src, srcName));
		app.addServlet(new ServletHolder(gs), "/*");
		return app;
	}

	@SuppressWarnings("unused")
	private ServletContextHandler addBrokenContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
		ServletContextHandler broken = server.addContext("/bad");
		broken.addFilter(new FilterHolder(new Filter() {

			@Override
			public void doFilter(ServletRequest request,
					ServletResponse response, FilterChain chain)
					throws IOException, ServletException {
				final HttpServletResponse r = (HttpServletResponse) response;
				r.setContentType("text/plain");
				r.setCharacterEncoding("UTF-8");
				PrintWriter w = r.getWriter();
				w.print("OK");
				w.close();
			}

			@Override
			public void init(FilterConfig filterConfig)
					throws ServletException {
				// empty
			}

			@Override
			public void destroy() {
				// empty
			}
		}), "/" + srcName + "/git-upload-pack",
				EnumSet.of(DispatcherType.REQUEST));
		broken.addServlet(new ServletHolder(gs), "/*");
		return broken;
	}

	@SuppressWarnings("unused")
	private ServletContextHandler addRedirectContext(GitServlet gs,
			TestRepository<Repository> src, String srcName) {
		ServletContextHandler redirect = server.addContext("/redirect");
		redirect.addFilter(new FilterHolder(new Filter() {

			@Override
			public void init(FilterConfig filterConfig)
					throws ServletException {
				// empty
			}

			@Override
			public void doFilter(ServletRequest request,
					ServletResponse response, FilterChain chain)
					throws IOException, ServletException {
				final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
				final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
				final StringBuffer fullUrl = httpServletRequest.getRequestURL();
				if (httpServletRequest.getQueryString() != null) {
					fullUrl.append("?")
							.append(httpServletRequest.getQueryString());
				}
				httpServletResponse
						.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
				httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
						fullUrl.toString().replace("/redirect", "/git"));
			}

			@Override
			public void destroy() {
				// empty
			}
		}), "/*", EnumSet.of(DispatcherType.REQUEST));
		redirect.addServlet(new ServletHolder(gs), "/*");
		return redirect;
	}

	@Test
	public void testListRemote() throws IOException {
		Repository dst = createBareRepository();

		assertEquals("http", remoteURI.getScheme());

		Map<String, Ref> map;
		try (Transport t = Transport.open(dst, remoteURI)) {
			// I didn't make up these public interface names, I just
			// approved them for inclusion into the code base. Sorry.
			// --spearce
			//
			assertTrue("isa TransportHttp", t instanceof TransportHttp);
			assertTrue("isa HttpTransport", t instanceof HttpTransport);

			FetchConnection c = t.openFetch();
			try {
				map = c.getRefsMap();
			} finally {
				c.close();
			}
		}

		assertNotNull("have map of refs", map);
		assertEquals(3, map.size());

		assertNotNull("has " + master, map.get(master));
		assertEquals(B, map.get(master).getObjectId());

		assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD));
		assertEquals(B, map.get(Constants.HEAD).getObjectId());

		List<AccessEvent> requests = getRequests();
		assertEquals(1, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement", info
				.getResponseHeader(HDR_CONTENT_TYPE));
		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
	}

	@Test
	public void testListRemote_BadName() throws IOException, URISyntaxException {
		Repository dst = createBareRepository();
		URIish uri = new URIish(this.remoteURI.toString() + ".invalid");
		try (Transport t = Transport.open(dst, uri)) {
			try {
				t.openFetch();
				fail("fetch connection opened");
			} catch (RemoteRepositoryException notFound) {
				assertEquals(uri + ": Git repository not found",
						notFound.getMessage());
			}
		}

		List<AccessEvent> requests = getRequests();
		assertEquals(1, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(uri, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement",
				info.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testInitialClone_Small() throws Exception {
		Repository dst = createBareRepository();
		assertFalse(dst.hasObject(A_txt));

		try (Transport t = Transport.open(dst, remoteURI)) {
			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
		}

		assertTrue(dst.hasObject(A_txt));
		assertEquals(B, dst.exactRef(master).getObjectId());
		fsck(dst, B);

		List<AccessEvent> requests = getRequests();
		assertEquals(2, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement", info
				.getResponseHeader(HDR_CONTENT_TYPE));
		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

		AccessEvent service = requests.get(1);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNotNull("has content-length", service
				.getRequestHeader(HDR_CONTENT_LENGTH));
		assertNull("not chunked", service
				.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-upload-pack-result", service
				.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testInitialClone_RedirectSmall() throws Exception {
		Repository dst = createBareRepository();
		assertFalse(dst.hasObject(A_txt));

		try (Transport t = Transport.open(dst, redirectURI)) {
			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
		}

		assertTrue(dst.hasObject(A_txt));
		assertEquals(B, dst.exactRef(master).getObjectId());
		fsck(dst, B);

		List<AccessEvent> requests = getRequests();
		assertEquals(4, requests.size());

		AccessEvent firstRedirect = requests.get(0);
		assertEquals(301, firstRedirect.getStatus());

		AccessEvent info = requests.get(1);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement",
				info.getResponseHeader(HDR_CONTENT_TYPE));
		assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

		AccessEvent secondRedirect = requests.get(2);
		assertEquals(301, secondRedirect.getStatus());

		AccessEvent service = requests.get(3);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNotNull("has content-length",
				service.getRequestHeader(HDR_CONTENT_LENGTH));
		assertNull("not chunked",
				service.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-upload-pack-result",
				service.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testFetch_FewLocalCommits() throws Exception {
		// Bootstrap by doing the clone.
		//
		TestRepository dst = createTestRepository();
		try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
		}
		assertEquals(B, dst.getRepository().exactRef(master).getObjectId());
		List<AccessEvent> cloneRequests = getRequests();

		// Only create a few new commits.
		TestRepository.BranchBuilder b = dst.branch(master);
		for (int i = 0; i < 4; i++)
			b.commit().tick(3600 /* 1 hour */).message("c" + i).create();

		// Create a new commit on the remote.
		//
		b = new TestRepository<>(remoteRepository).branch(master);
		RevCommit Z = b.commit().message("Z").create();

		// Now incrementally update.
		//
		try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
		}
		assertEquals(Z, dst.getRepository().exactRef(master).getObjectId());

		List<AccessEvent> requests = getRequests();
		requests.removeAll(cloneRequests);
		assertEquals(2, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement",
				info.getResponseHeader(HDR_CONTENT_TYPE));

		// We should have needed one request to perform the fetch.
		//
		AccessEvent service = requests.get(1);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNotNull("has content-length",
				service.getRequestHeader(HDR_CONTENT_LENGTH));
		assertNull("not chunked",
				service.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-upload-pack-result",
				service.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testFetch_TooManyLocalCommits() throws Exception {
		// Bootstrap by doing the clone.
		//
		TestRepository dst = createTestRepository();
		try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
		}
		assertEquals(B, dst.getRepository().exactRef(master).getObjectId());
		List<AccessEvent> cloneRequests = getRequests();

		// Force enough into the local client that enumeration will
		// need multiple packets, but not too many to overflow and
		// not pick up the ACK_COMMON message.
		//
		TestRepository.BranchBuilder b = dst.branch(master);
		for (int i = 0; i < 32 - 1; i++)
			b.commit().tick(3600 /* 1 hour */).message("c" + i).create();

		// Create a new commit on the remote.
		//
		b = new TestRepository<>(remoteRepository).branch(master);
		RevCommit Z = b.commit().message("Z").create();

		// Now incrementally update.
		//
		try (Transport t = Transport.open(dst.getRepository(), remoteURI)) {
			t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
		}
		assertEquals(Z, dst.getRepository().exactRef(master).getObjectId());

		List<AccessEvent> requests = getRequests();
		requests.removeAll(cloneRequests);
		assertEquals(3, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement", info
				.getResponseHeader(HDR_CONTENT_TYPE));

		// We should have needed two requests to perform the fetch
		// due to the high number of local unknown commits.
		//
		AccessEvent service = requests.get(1);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNotNull("has content-length", service
				.getRequestHeader(HDR_CONTENT_LENGTH));
		assertNull("not chunked", service
				.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-upload-pack-result", service
				.getResponseHeader(HDR_CONTENT_TYPE));

		service = requests.get(2);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNotNull("has content-length", service
				.getRequestHeader(HDR_CONTENT_LENGTH));
		assertNull("not chunked", service
				.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-upload-pack-result", service
				.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testInitialClone_BrokenServer() throws Exception {
		Repository dst = createBareRepository();
		assertFalse(dst.hasObject(A_txt));

		try (Transport t = Transport.open(dst, brokenURI)) {
			try {
				t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
				fail("fetch completed despite upload-pack being broken");
			} catch (TransportException err) {
				String exp = brokenURI + ": expected"
						+ " Content-Type application/x-git-upload-pack-result;"
						+ " received Content-Type text/plain;charset=utf-8";
				assertEquals(exp, err.getMessage());
			}
		}

		List<AccessEvent> requests = getRequests();
		assertEquals(2, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(brokenURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-upload-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-upload-pack-advertisement", info
				.getResponseHeader(HDR_CONTENT_TYPE));

		AccessEvent service = requests.get(1);
		assertEquals("POST", service.getMethod());
		assertEquals(join(brokenURI, "git-upload-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertEquals(200, service.getStatus());
		assertEquals("text/plain;charset=utf-8",
				service.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testInvalidWant() throws Exception {
		@SuppressWarnings("resource")
		ObjectId id = new ObjectInserter.Formatter().idFor(Constants.OBJ_BLOB,
				"testInvalidWant".getBytes(StandardCharsets.UTF_8));

		Repository dst = createBareRepository();
		try (Transport t = Transport.open(dst, remoteURI);
				FetchConnection c = t.openFetch()) {
			Ref want = new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, id.name(),
					id);
			c.fetch(NullProgressMonitor.INSTANCE, Collections.singleton(want),
					Collections.<ObjectId> emptySet());
			fail("Server accepted want " + id.name());
		} catch (TransportException err) {
			assertEquals("want " + id.name() + " not valid", err.getMessage());
		}
	}

	@Test
	public void testFetch_RefsUnreadableOnUpload() throws Exception {
		AppServer noRefServer = new AppServer();
		try {
			final String repoName = "refs-unreadable";
			RefsUnreadableInMemoryRepository badRefsRepo = new RefsUnreadableInMemoryRepository(
					new DfsRepositoryDescription(repoName));
			final TestRepository<Repository> repo = new TestRepository<>(
					badRefsRepo);

			ServletContextHandler app = noRefServer.addContext("/git");
			GitServlet gs = new GitServlet();
			gs.setRepositoryResolver(new TestRepoResolver(repo, repoName));
			app.addServlet(new ServletHolder(gs), "/*");
			noRefServer.setUp();

			RevBlob A2_txt = repo.blob("A2");
			RevCommit A2 = repo.commit().add("A2_txt", A2_txt).create();
			RevCommit B2 = repo.commit().parent(A2).add("A2_txt", "C2")
					.add("B2", "B2").create();
			repo.update(master, B2);

			URIish badRefsURI = new URIish(noRefServer.getURI()
					.resolve(app.getContextPath() + "/" + repoName).toString());

			Repository dst = createBareRepository();
			try (Transport t = Transport.open(dst, badRefsURI);
					FetchConnection c = t.openFetch()) {
				// We start failing here to exercise the post-advertisement
				// upload pack handler.
				badRefsRepo.startFailing();
				// Need to flush caches because ref advertisement populated them.
				badRefsRepo.getRefDatabase().refresh();
				c.fetch(NullProgressMonitor.INSTANCE,
						Collections.singleton(c.getRef(master)),
						Collections.<ObjectId> emptySet());
				fail("Successfully served ref with value " + c.getRef(master));
			} catch (TransportException err) {
				assertEquals("internal server error", err.getMessage());
			}
		} finally {
			noRefServer.tearDown();
		}
	}

	@Test
	public void testPush_NotAuthorized() throws Exception {
		final TestRepository src = createTestRepository();
		final RevBlob Q_txt = src.blob("new text");
		final RevCommit Q = src.commit().add("Q", Q_txt).create();
		final Repository db = src.getRepository();
		final String dstName = Constants.R_HEADS + "new.branch";

		// push anonymous shouldn't be allowed.
		//
		try (Transport t = Transport.open(db, remoteURI)) {
			final String srcExpr = Q.name();
			final boolean forceUpdate = false;
			final String localName = null;
			final ObjectId oldId = null;

			RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
					srcExpr, dstName, forceUpdate, localName, oldId);
			try {
				t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
				fail("anonymous push incorrectly accepted without error");
			} catch (TransportException e) {
				final String exp = remoteURI + ": "
						+ JGitText.get().authenticationNotSupported;
				assertEquals(exp, e.getMessage());
			}
		}

		List<AccessEvent> requests = getRequests();
		assertEquals(1, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-receive-pack", info.getParameter("service"));
		assertEquals(401, info.getStatus());
	}

	@Test
	public void testPush_CreateBranch() throws Exception {
		final TestRepository src = createTestRepository();
		final RevBlob Q_txt = src.blob("new text");
		final RevCommit Q = src.commit().add("Q", Q_txt).create();
		final Repository db = src.getRepository();
		final String dstName = Constants.R_HEADS + "new.branch";

		enableReceivePack();

		try (Transport t = Transport.open(db, remoteURI)) {
			final String srcExpr = Q.name();
			final boolean forceUpdate = false;
			final String localName = null;
			final ObjectId oldId = null;

			RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
					srcExpr, dstName, forceUpdate, localName, oldId);
			t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
		}

		assertTrue(remoteRepository.hasObject(Q_txt));
		assertNotNull("has " + dstName, remoteRepository.exactRef(dstName));
		assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId());
		fsck(remoteRepository, Q);

		final ReflogReader log = remoteRepository.getReflogReader(dstName);
		assertNotNull("has log for " + dstName, log);

		final ReflogEntry last = log.getLastEntry();
		assertNotNull("has last entry", last);
		assertEquals(ObjectId.zeroId(), last.getOldId());
		assertEquals(Q, last.getNewId());
		assertEquals("anonymous", last.getWho().getName());

		// Assumption: The host name we use to contact the server should
		// be the server's own host name, because it should be the loopback
		// network interface.
		//
		final String clientHost = remoteURI.getHost();
		assertEquals("anonymous@" + clientHost, last.getWho().getEmailAddress());
		assertEquals("push: created", last.getComment());

		List<AccessEvent> requests = getRequests();
		assertEquals(2, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-receive-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-receive-pack-advertisement", info
				.getResponseHeader(HDR_CONTENT_TYPE));

		AccessEvent service = requests.get(1);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-receive-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNotNull("has content-length", service
				.getRequestHeader(HDR_CONTENT_LENGTH));
		assertNull("not chunked", service
				.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-receive-pack-result", service
				.getResponseHeader(HDR_CONTENT_TYPE));
	}

	@Test
	public void testPush_ChunkedEncoding() throws Exception {
		final TestRepository<Repository> src = createTestRepository();
		final RevBlob Q_bin = src.blob(new TestRng("Q").nextBytes(128 * 1024));
		final RevCommit Q = src.commit().add("Q", Q_bin).create();
		final Repository db = src.getRepository();
		final String dstName = Constants.R_HEADS + "new.branch";

		enableReceivePack();

		final StoredConfig cfg = db.getConfig();
		cfg.setInt("core", null, "compression", 0);
		cfg.setInt("http", null, "postbuffer", 8 * 1024);
		cfg.save();

		try (Transport t = Transport.open(db, remoteURI)) {
			final String srcExpr = Q.name();
			final boolean forceUpdate = false;
			final String localName = null;
			final ObjectId oldId = null;

			RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
					srcExpr, dstName, forceUpdate, localName, oldId);
			t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
		}

		assertTrue(remoteRepository.hasObject(Q_bin));
		assertNotNull("has " + dstName, remoteRepository.exactRef(dstName));
		assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId());
		fsck(remoteRepository, Q);

		List<AccessEvent> requests = getRequests();
		assertEquals(2, requests.size());

		AccessEvent info = requests.get(0);
		assertEquals("GET", info.getMethod());
		assertEquals(join(remoteURI, "info/refs"), info.getPath());
		assertEquals(1, info.getParameters().size());
		assertEquals("git-receive-pack", info.getParameter("service"));
		assertEquals(200, info.getStatus());
		assertEquals("application/x-git-receive-pack-advertisement", info
				.getResponseHeader(HDR_CONTENT_TYPE));

		AccessEvent service = requests.get(1);
		assertEquals("POST", service.getMethod());
		assertEquals(join(remoteURI, "git-receive-pack"), service.getPath());
		assertEquals(0, service.getParameters().size());
		assertNull("no content-length", service
				.getRequestHeader(HDR_CONTENT_LENGTH));
		assertEquals("chunked", service.getRequestHeader(HDR_TRANSFER_ENCODING));

		assertEquals(200, service.getStatus());
		assertEquals("application/x-git-receive-pack-result", service
				.getResponseHeader(HDR_CONTENT_TYPE));
	}

	private void enableReceivePack() throws IOException {
		final StoredConfig cfg = remoteRepository.getConfig();
		cfg.setBoolean("http", null, "receivepack", true);
		cfg.save();
	}

	private final class TestRepoResolver
			implements RepositoryResolver<HttpServletRequest> {

		private final TestRepository<Repository> repo;

		private final String repoName;

		private TestRepoResolver(TestRepository<Repository> repo,
				String repoName) {
			this.repo = repo;
			this.repoName = repoName;
		}

		@Override
		public Repository open(HttpServletRequest req, String name)
				throws RepositoryNotFoundException, ServiceNotEnabledException {
			if (!name.equals(repoName))
				throw new RepositoryNotFoundException(name);

			Repository db = repo.getRepository();
			db.incrementOpen();
			return db;
		}
	}
}
