package web import ( "net/http" "os" "os/exec" "path/filepath" "strings" "testing" ) // seedFiles gives a repo created via /new one commit on main. func seedFiles(t *testing.T, dataDir, name string) { t.Helper() bare := filepath.Join(dataDir, "repos", "josie", name+".git") work := filepath.Join(t.TempDir(), "work") cmd := exec.Command("git", "clone", "-q", bare, work) if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("clone seed: %v: %s", err, out) } write := func(rel, content string) { full := filepath.Join(work, rel) if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { t.Fatalf("mkdir: %v", err) } if err := os.WriteFile(full, []byte(content), 0o644); err != nil { t.Fatalf("write %s: %v", rel, err) } } write("README.md", "# demo repo\n\nthe **readme** body\n") write("LICENSE", "MIT License\n\nPermission is hereby granted, free of charge, to any person...\n") write("hello.c", "int main(void) { return 0; }\n") write("sub/note.txt", "note\n") for _, args := range [][]string{ {"add", "."}, {"-c", "user.email=t@t", "-c", "user.name=t", "commit", "-qm", "seed"}, {"push", "-q", "origin", "main"}, } { cmd := exec.Command("git", args...) cmd.Dir = work if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("git %v: %v: %s", args, err, out) } } } func TestRepoHomePublic(t *testing.T) { httpServer, _, dataDir := newTestServer(t) createRepo(t, newLoggedInClient(t, httpServer), httpServer, "pub", "public") seedFiles(t, dataDir, "pub") resp, err := (&http.Client{}).Get(httpServer.URL + "/josie/pub") if err != nil { t.Fatalf("GET /josie/pub: %v", err) } body := readAll(t, resp) if resp.StatusCode != http.StatusOK { t.Fatalf("status = %d, want 200: %q", resp.StatusCode, body) } for _, want := range []string{ "josie/pub", "README.md", "hello.c", "sub/", "readme", "MIT", "/josie/pub.git", "/josie/pub/blob/main/hello.c", "/josie/pub/blob/main/sub/note.txt", `class="file-tree`, "✓ main", `value="http`, } { if !strings.Contains(body, want) { t.Errorf("body lacks %q", want) } } } func TestRepoHomePrivate(t *testing.T) { httpServer, _, dataDir := newTestServer(t) loggedIn := newLoggedInClient(t, httpServer) createRepo(t, loggedIn, httpServer, "sec", "private") seedFiles(t, dataDir, "sec") noFollow := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }} resp, err := noFollow.Get(httpServer.URL + "/josie/sec") if err != nil { t.Fatalf("anonymous GET private home: %v", err) } readAll(t, resp) if resp.StatusCode != http.StatusNotFound { t.Errorf("anonymous status = %d, want 404 (no existence oracle)", resp.StatusCode) } resp, err = loggedIn.Get(httpServer.URL + "/josie/sec") if err != nil { t.Fatalf("signed-in GET private home: %v", err) } body := readAll(t, resp) if resp.StatusCode != http.StatusOK || !strings.Contains(body, "README.md") { t.Errorf("signed-in status = %d, want 200 with listing", resp.StatusCode) } } func TestRepoHomeEmptyRepoShowsInstructions(t *testing.T) { httpServer, _, _ := newTestServer(t) loggedIn := newLoggedInClient(t, httpServer) createRepo(t, loggedIn, httpServer, "fresh", "private") resp, err := loggedIn.Get(httpServer.URL + "/josie/fresh") if err != nil { t.Fatalf("GET empty home: %v", err) } body := readAll(t, resp) if !strings.Contains(body, "The repository is empty") || !strings.Contains(body, "git remote add origin") { t.Errorf("empty repo page lacks push instructions: %q", body) } } func TestRepoHomePrivateOwnerOnly(t *testing.T) { httpServer, database, dataDir := newTestServer(t) createRepo(t, newLoggedInClient(t, httpServer), httpServer, "sec", "private") seedFiles(t, dataDir, "sec") addUser(t, database, "mallory", "pw") mallory := loginAs(t, httpServer, "mallory", "pw") for _, path := range []string{"/josie/sec", "/josie/sec/tree/main", "/josie/sec/blob/main/README.md"} { resp, err := mallory.Get(httpServer.URL + path) if err != nil { t.Fatalf("GET %s as non-owner: %v", path, err) } readAll(t, resp) if resp.StatusCode != http.StatusNotFound { t.Errorf("non-owner GET %s = %d, want 404", path, resp.StatusCode) } } } func TestRepoHomeUnknown(t *testing.T) { httpServer, _, _ := newTestServer(t) resp, err := (&http.Client{}).Get(httpServer.URL + "/josie/nope") if err != nil { t.Fatalf("GET unknown: %v", err) } readAll(t, resp) if resp.StatusCode != http.StatusNotFound { t.Errorf("status = %d, want 404", resp.StatusCode) } }