aboutsummaryrefslogtreecommitdiff
path: root/internal/modules/handler_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/modules/handler_test.go')
-rw-r--r--internal/modules/handler_test.go550
1 files changed, 550 insertions, 0 deletions
diff --git a/internal/modules/handler_test.go b/internal/modules/handler_test.go
new file mode 100644
index 0000000..b173f98
--- /dev/null
+++ b/internal/modules/handler_test.go
@@ -0,0 +1,550 @@
+package modules
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ "git.ofmax.li/go-git-server/internal/admin"
+)
+
+func TestNewModuleHandler_WithNilConfig(t *testing.T) {
+ handler := NewModuleHandler("/tmp/repos", "example.com", nil)
+
+ // Test that it returns a valid http.Handler even with nil config
+ if handler == nil {
+ t.Error("NewModuleHandler should return a non-nil handler")
+ }
+}
+
+func TestNewModuleHandler_WithConfig(t *testing.T) {
+ config := &admin.ServerRepos{
+ Repos: []*admin.GitRepo{
+ {
+ Name: "mylib",
+ GoModule: true,
+ },
+ },
+ }
+
+ handler := NewModuleHandler("/tmp/repos", "example.com", config)
+
+ // Test that it returns a valid http.Handler
+ if handler == nil {
+ t.Error("NewModuleHandler should return a non-nil handler")
+ }
+}
+
+func TestHandleGoImport_ConfiguredModule(t *testing.T) {
+ config := &admin.ServerRepos{
+ Repos: []*admin.GitRepo{
+ {
+ Name: "mymodule",
+ GoModule: true,
+ },
+ },
+ }
+
+ handler := NewModuleHandler("/tmp/repos", "git.example.com", config)
+
+ req := httptest.NewRequest("GET", "/mymodule?go-get=1", nil)
+ w := httptest.NewRecorder()
+
+ handler.ServeHTTP(w, req)
+
+ if w.Code != http.StatusOK {
+ t.Errorf("expected status 200, got %d", w.Code)
+ }
+
+ body := w.Body.String()
+
+ // Check for go-import meta tag
+ if !strings.Contains(body, `<meta name="go-import"`) {
+ t.Error("response should contain go-import meta tag")
+ }
+
+ // Check for correct module path and VCS info
+ expectedContent := `content="mymodule git https://git.example.com/mymodule"`
+ if !strings.Contains(body, expectedContent) {
+ t.Errorf("response should contain %s", expectedContent)
+ }
+
+ // Check for go-source meta tag
+ if !strings.Contains(body, `<meta name="go-source"`) {
+ t.Error("response should contain go-source meta tag")
+ }
+
+ // Check content type
+ contentType := w.Header().Get("Content-Type")
+ if contentType != "text/html; charset=utf-8" {
+ t.Errorf("expected content type text/html; charset=utf-8, got %s", contentType)
+ }
+}
+
+func TestModuleHandler_ServeHTTP_VersionList(t *testing.T) {
+ config := &admin.ServerRepos{
+ Repos: []*admin.GitRepo{
+ {
+ Name: "mymodule",
+ GoModule: true,
+ },
+ },
+ }
+
+ handler := NewModuleHandler("/tmp/repos", "git.example.com", config)
+
+ req := httptest.NewRequest("GET", "/mymodule/@v/list", nil)
+ w := httptest.NewRecorder()
+
+ handler.ServeHTTP(w, req)
+
+ // Since we don't have a real repo, this should return 500 (internal server error)
+ // But we can test that it tries to handle the request correctly
+ if w.Code == http.StatusOK {
+ contentType := w.Header().Get("Content-Type")
+ if contentType != "text/plain; charset=utf-8" {
+ t.Errorf("expected content type text/plain; charset=utf-8, got %s", contentType)
+ }
+ }
+}
+
+func TestGoModuleConfiguration(t *testing.T) {
+ config := &admin.ServerRepos{
+ Repos: []*admin.GitRepo{
+ {
+ Name: "mylib",
+ GoModule: true, // This should have module endpoints
+ },
+ {
+ Name: "website",
+ GoModule: false, // This should not have module endpoints
+ },
+ },
+ }
+
+ handler := NewModuleHandler("/tmp/repos", "git.example.com", config)
+
+ // Test Go module repo (should work)
+ t.Run("go_module_true", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mylib?go-get=1", nil)
+ w := httptest.NewRecorder()
+ handler.ServeHTTP(w, req)
+
+ if w.Code != http.StatusOK {
+ t.Errorf("expected status 200 for Go module, got %d", w.Code)
+ }
+ })
+
+ // Test non-Go module repo (should return 404)
+ t.Run("go_module_false", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/website?go-get=1", nil)
+ w := httptest.NewRecorder()
+ handler.ServeHTTP(w, req)
+
+ if w.Code != http.StatusNotFound {
+ t.Errorf("expected status 404 for non-Go module, got %d", w.Code)
+ }
+ })
+
+ // Test proxy endpoints for Go module
+ t.Run("go_module_proxy_endpoints", func(t *testing.T) {
+ endpoints := []string{
+ "/mylib/@v/list",
+ "/mylib/@latest",
+ }
+
+ for _, endpoint := range endpoints {
+ req := httptest.NewRequest("GET", endpoint, nil)
+ w := httptest.NewRecorder()
+ handler.ServeHTTP(w, req)
+
+ // Should get 500 (repo doesn't exist) not 404 (route doesn't exist)
+ if w.Code == http.StatusNotFound {
+ t.Errorf("endpoint %s should be routed (got 404, want 500 or 200)", endpoint)
+ }
+ }
+ })
+
+ // Test proxy endpoints for non-Go module (should all be 404)
+ t.Run("non_go_module_proxy_endpoints", func(t *testing.T) {
+ endpoints := []string{
+ "/website/@v/list",
+ "/website/@latest",
+ }
+
+ for _, endpoint := range endpoints {
+ req := httptest.NewRequest("GET", endpoint, nil)
+ w := httptest.NewRecorder()
+ handler.ServeHTTP(w, req)
+
+ if w.Code != http.StatusNotFound {
+ t.Errorf("endpoint %s should return 404 for non-Go module, got %d", endpoint, w.Code)
+ }
+ }
+ })
+}
+
+// Test the catch-all handler (handleAllRequests) - currently 0% coverage
+func TestHandleAllRequests(t *testing.T) {
+ handler := &ModuleHandler{
+ reposDir: "/tmp/repos",
+ serverHost: "git.example.com",
+ }
+
+ t.Run("version_list_endpoint", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/list", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ // Should get 500 (repo doesn't exist) not 404 (route doesn't exist)
+ if w.Code == http.StatusNotFound {
+ t.Error("handleAllRequests should route version list requests")
+ }
+ })
+
+ t.Run("latest_endpoint", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@latest", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ // Should get 500 (repo doesn't exist) not 404 (route doesn't exist)
+ if w.Code == http.StatusNotFound {
+ t.Error("handleAllRequests should route latest version requests")
+ }
+ })
+
+ t.Run("version_info_endpoint", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.info", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ // Should get 500/404 (repo/version doesn't exist) not 404 (route doesn't exist)
+ if w.Code == http.StatusOK {
+ t.Error("expected error for nonexistent repository/version")
+ }
+ })
+
+ t.Run("mod_file_endpoint", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.mod", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ // Should get 500/404 (repo/version doesn't exist) not 404 (route doesn't exist)
+ if w.Code == http.StatusOK {
+ t.Error("expected error for nonexistent repository/version")
+ }
+ })
+
+ t.Run("zip_file_endpoint", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.zip", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ // Should get 500/404 (repo/version doesn't exist) not 404 (route doesn't exist)
+ if w.Code == http.StatusOK {
+ t.Error("expected error for nonexistent repository/version")
+ }
+ })
+
+ t.Run("go_import_request", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule?go-get=1", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ if w.Code != http.StatusOK {
+ t.Errorf("expected 200 for go-import request, got %d", w.Code)
+ }
+
+ body := w.Body.String()
+ if !strings.Contains(body, "go-import") {
+ t.Error("response should contain go-import meta tag")
+ }
+ })
+
+ t.Run("regular_request", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleAllRequests(w, req)
+
+ // Should get 404 because go-get=1 is required for go-import
+ if w.Code != http.StatusNotFound {
+ t.Errorf("expected 404 for regular request without go-get, got %d", w.Code)
+ }
+ })
+}
+
+// Test non-"ForModule" handler functions - currently 0% coverage
+func TestNonForModuleHandlers(t *testing.T) {
+ handler := &ModuleHandler{
+ reposDir: "/tmp/repos",
+ serverHost: "git.example.com",
+ }
+
+ t.Run("handleGoImport", func(t *testing.T) {
+ // Test without go-get parameter
+ req := httptest.NewRequest("GET", "/mymodule", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleGoImport(w, req)
+
+ if w.Code != http.StatusNotFound {
+ t.Error("expected 404 when go-get parameter is missing")
+ }
+
+ // Test with go-get=1
+ req = httptest.NewRequest("GET", "/mymodule?go-get=1", nil)
+ w = httptest.NewRecorder()
+
+ handler.handleGoImport(w, req)
+
+ if w.Code != http.StatusOK {
+ t.Errorf("expected 200 with go-get=1, got %d", w.Code)
+ }
+
+ body := w.Body.String()
+ if !strings.Contains(body, "go-import") {
+ t.Error("response should contain go-import meta tag")
+ }
+ })
+
+ t.Run("handleVersionList", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/list", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleVersionList(w, req)
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleLatestVersion", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@latest", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleLatestVersion(w, req)
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleVersionInfo", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.info", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleVersionInfo(w, req)
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleModFile", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.mod", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleModFile(w, req)
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleModuleZip", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.zip", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleModuleZip(w, req)
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+}
+
+// Test ForModule handlers that have 0% coverage
+func TestForModuleHandlersZeroCoverage(t *testing.T) {
+ handler := &ModuleHandler{
+ reposDir: "/tmp/repos",
+ serverHost: "git.example.com",
+ }
+
+ t.Run("handleVersionInfoForModule", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.info", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleVersionInfoForModule(w, req, "mymodule", "v1.0.0")
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleModFileForModule", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.mod", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleModFileForModule(w, req, "mymodule", "v1.0.0")
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleModuleZipForModule", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.zip", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleModuleZipForModule(w, req, "mymodule", "v1.0.0")
+
+ // Should get 500 (repo doesn't exist)
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("handleGoImportForModule_without_go_get", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleGoImportForModule(w, req, "mymodule")
+
+ if w.Code != http.StatusNotFound {
+ t.Error("expected 404 when go-get parameter is missing")
+ }
+ })
+
+ t.Run("handleGoImportForModule_with_go_get", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule?go-get=1", nil)
+ w := httptest.NewRecorder()
+
+ handler.handleGoImportForModule(w, req, "mymodule")
+
+ if w.Code != http.StatusOK {
+ t.Errorf("expected 200 with go-get=1, got %d", w.Code)
+ }
+
+ body := w.Body.String()
+ if !strings.Contains(body, "go-import") {
+ t.Error("response should contain go-import meta tag")
+ }
+ })
+}
+
+// Test createGenericVersionHandler which has low coverage (8.3%)
+func TestCreateGenericVersionHandler(t *testing.T) {
+ handler := &ModuleHandler{
+ reposDir: "/tmp/repos",
+ serverHost: "git.example.com",
+ }
+
+ genericHandler := handler.createGenericVersionHandler("mymodule")
+
+ t.Run("info_file", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.info", nil)
+ w := httptest.NewRecorder()
+
+ genericHandler(w, req)
+
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("mod_file", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.mod", nil)
+ w := httptest.NewRecorder()
+
+ genericHandler(w, req)
+
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("zip_file", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/v1.0.0.zip", nil)
+ w := httptest.NewRecorder()
+
+ genericHandler(w, req)
+
+ if w.Code != http.StatusInternalServerError {
+ t.Errorf("expected 500 for nonexistent repo, got %d", w.Code)
+ }
+ })
+
+ t.Run("unknown_endpoint", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/unknown", nil)
+ w := httptest.NewRecorder()
+
+ genericHandler(w, req)
+
+ if w.Code != http.StatusNotFound {
+ t.Errorf("expected 404 for unknown endpoint, got %d", w.Code)
+ }
+ })
+}
+
+// Test middleware coverage
+func TestModuleMiddleware(t *testing.T) {
+ moduleHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte("module-response"))
+ })
+
+ nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte("next-response"))
+ })
+
+ middleware := ModuleMiddleware(moduleHandler, nextHandler)
+
+ t.Run("module_request_go_get", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule?go-get=1", nil)
+ w := httptest.NewRecorder()
+
+ middleware.ServeHTTP(w, req)
+
+ if w.Body.String() != "module-response" {
+ t.Error("should route to module handler for go-get requests")
+ }
+ })
+
+ t.Run("module_request_version_list", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule/@v/list", nil)
+ w := httptest.NewRecorder()
+
+ middleware.ServeHTTP(w, req)
+
+ if w.Body.String() != "module-response" {
+ t.Error("should route to module handler for version list requests")
+ }
+ })
+
+ t.Run("non_module_request", func(t *testing.T) {
+ req := httptest.NewRequest("GET", "/mymodule.git/info/refs", nil)
+ w := httptest.NewRecorder()
+
+ middleware.ServeHTTP(w, req)
+
+ if w.Body.String() != "next-response" {
+ t.Error("should route to next handler for git requests")
+ }
+ })
+}