repo_test.go
·
98 строк
·
2.8 KB
| 1 | package repo |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "os" |
| 6 | "path/filepath" |
| 7 | "testing" |
| 8 | |
| 9 | "polar/internal/db" |
| 10 | "polar/internal/user" |
| 11 | ) |
| 12 | |
| 13 | func TestValidateRepoName(t *testing.T) { |
| 14 | valid := []string{"alice", "my-repo_1", "v1.0.0", "x", "core.go"} |
| 15 | for _, n := range valid { |
| 16 | if err := ValidateRepoName(n); err != nil { |
| 17 | t.Errorf("expected repo name %q to be valid, got %v", n, err) |
| 18 | } |
| 19 | } |
| 20 | |
| 21 | invalid := []string{ |
| 22 | "", ".", "..", ".hidden", "-dash", "repo.git", "repo.lock", |
| 23 | "repo.", "a..b", "foo/bar", `foo\bar`, "settings", "commits", |
| 24 | "commit", "tree", "blob", "raw", "info", "git-upload-pack", |
| 25 | } |
| 26 | for _, n := range invalid { |
| 27 | if err := ValidateRepoName(n); err == nil { |
| 28 | t.Errorf("expected repo name %q to be rejected", n) |
| 29 | } |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | func TestRepoCRUDAndAccessControl(t *testing.T) { |
| 34 | ctx := context.Background() |
| 35 | tmp := t.TempDir() |
| 36 | database, err := db.Open(ctx, filepath.Join(tmp, "repo.db"), true) |
| 37 | if err != nil { |
| 38 | t.Fatalf("open db: %v", err) |
| 39 | } |
| 40 | defer database.Close() |
| 41 | |
| 42 | userSvc := user.NewService(database) |
| 43 | owner, err := userSvc.Register(ctx, "alice", "alice@example.com", "password123", true) |
| 44 | if err != nil { |
| 45 | t.Fatalf("register owner: %v", err) |
| 46 | } |
| 47 | stranger, err := userSvc.Register(ctx, "bob", "bob@example.com", "password123", true) |
| 48 | if err != nil { |
| 49 | t.Fatalf("register stranger: %v", err) |
| 50 | } |
| 51 | |
| 52 | repoSvc := NewService(database, filepath.Join(tmp, "repos")) |
| 53 | |
| 54 | privRepo, err := repoSvc.Create(ctx, owner, "secret-notes", "Private repo", true) |
| 55 | if err != nil { |
| 56 | t.Fatalf("Create private repo failed: %v", err) |
| 57 | } |
| 58 | |
| 59 | // Verify bare git repository exists on disk |
| 60 | diskPath, err := repoSvc.DiskPath(owner.Username, privRepo.Name) |
| 61 | if err != nil { |
| 62 | t.Fatalf("DiskPath failed: %v", err) |
| 63 | } |
| 64 | if _, err := os.Stat(filepath.Join(diskPath, "HEAD")); err != nil { |
| 65 | t.Fatalf("expected bare repo HEAD on disk: %v", err) |
| 66 | } |
| 67 | |
| 68 | // Private repo access checks |
| 69 | if repoSvc.CanRead(ctx, privRepo, nil) { |
| 70 | t.Fatalf("anonymous user must NOT read private repo") |
| 71 | } |
| 72 | if repoSvc.CanRead(ctx, privRepo, stranger) { |
| 73 | t.Fatalf("other regular user must NOT read private repo") |
| 74 | } |
| 75 | if !repoSvc.CanRead(ctx, privRepo, owner) { |
| 76 | t.Fatalf("owner must read private repo") |
| 77 | } |
| 78 | if !repoSvc.CanWrite(ctx, privRepo, owner) || repoSvc.CanWrite(ctx, privRepo, stranger) { |
| 79 | t.Fatalf("unexpected CanWrite result") |
| 80 | } |
| 81 | |
| 82 | // Rename repository |
| 83 | if err := repoSvc.Rename(ctx, privRepo, "renamed-notes"); err != nil { |
| 84 | t.Fatalf("Rename failed: %v", err) |
| 85 | } |
| 86 | newDiskPath, _ := repoSvc.DiskPath(owner.Username, "renamed-notes") |
| 87 | if _, err := os.Stat(filepath.Join(newDiskPath, "HEAD")); err != nil { |
| 88 | t.Fatalf("expected renamed bare repo on disk: %v", err) |
| 89 | } |
| 90 | |
| 91 | // Delete repository |
| 92 | if err := repoSvc.Delete(ctx, privRepo); err != nil { |
| 93 | t.Fatalf("Delete failed: %v", err) |
| 94 | } |
| 95 | if _, err := os.Stat(newDiskPath); !os.IsNotExist(err) { |
| 96 | t.Fatalf("expected bare repo directory to be deleted from disk") |
| 97 | } |
| 98 | } |
| 99 |