Add archive servlet integration test In change Ic7dc1c8e96e an update of commons-compress from 1.25.0 to 1.28.0 was attempted as part of a broader WORKSPACE dependency refresh. commons-compress 1.28.0 introduces a runtime dependency on commons-io (via org.apache.commons.io.output.CountingOutputStream), which is used by JGit's archive implementation (org.eclipse.jgit.archive.TarFormat / TgzFormat) when writing tar/tgz archives. Gitiles' Bazel configuration does not automatically pull in Maven transitive dependencies, so commons-io must be declared explicitly. The attempted upgrade initially omitted this dependency, which would have caused runtime failures when serving archive downloads, e.g.: /<repo>/+archive/refs/heads/<ref>.tar.gz resulting in: java.lang.NoClassDefFoundError: org/apache/commons/io/output/CountingOutputStream This issue was identified during code review and corrected before submission, but the existing test suite did not exercise the archive servlet code path and therefore did not detect the breakage. Add a servlet-level integration test for the archive endpoint that: * creates a small in-memory test repository * requests a .tar.gz archive via GitilesServlet * verifies HTTP 200 response * verifies response body is non-empty This test executes ArchiveCommand.call() end-to-end and will fail with NoClassDefFoundError if commons-io is missing from the runtime classpath, preventing similar dependency regressions in future dependency updates. Change-Id: Ia9266aa6a6ca63b119e2216d8376ce0382ae6e44
diff --git a/javatests/com/google/gitiles/ArchiveServletTest.java b/javatests/com/google/gitiles/ArchiveServletTest.java new file mode 100644 index 0000000..89db8c2 --- /dev/null +++ b/javatests/com/google/gitiles/ArchiveServletTest.java
@@ -0,0 +1,55 @@ +// Copyright (C) 2026 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.truth.Truth.assertThat; +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import com.google.common.net.HttpHeaders; +import org.junit.Test; + +public class ArchiveServletTest extends ServletTest { + + @Test + public void tarGzArchive_smokeTest() throws Exception { + // Create a commit on master so refs/heads/master exists and points to a tree. + repo.branch("master").commit().add("README.md", "hello\n").create(); + + FakeHttpServletResponse res = + buildResponse("/repo/+archive/refs/heads/master.tar.gz", /* queryString= */ null, SC_OK); + + // Content-Type depends on ArchiveFormat mapping; be tolerant but ensure it's gzip-ish. + String contentType = res.getHeader(HttpHeaders.CONTENT_TYPE); + assertThat(contentType).isNotNull(); + assertThat(contentType.toLowerCase()).contains("gzip"); + + // Content-Disposition should suggest a downloadable filename. + String cd = res.getHeader(HttpHeaders.CONTENT_DISPOSITION); + assertThat(cd).isNotNull(); + assertThat(cd).contains("attachment"); + + // Be robust: Gitiles' filename includes the "revision name", which may be "master" or + // "refs/heads/master" depending on how the URL was formed/resolved. + assertThat(cd).contains("filename="); + assertThat(cd).contains("repo-"); + assertThat(cd).contains("master"); + assertThat(cd).contains(".tar.gz"); + + // Body should be non-empty. Note: FakeHttpServletResponse writes via a Writer (UTF-8), + // so binary bytes are not preserved; don't assert gzip magic bytes here. + byte[] body = res.getActualBody(); + assertThat(body.length).isGreaterThan(20); + } +}