package remoteurl import ( "strings" "testing" ) func TestRoundTrip(t *testing.T) { want := Spec{ Bucket: "bucket", Prefix: "owner/repo.git", Endpoint: "https://example.invalid", Profile: "r2", PublicURL: "https://public.invalid", } raw, err := Build(want) if err != nil { t.Fatal(err) } got, err := Parse(raw) if err != nil { t.Fatal(err) } if got != want { t.Fatalf("got %#v, want %#v", got, want) } if got.PublicRepoURL() != "https://public.invalid/owner/repo.git" { t.Fatalf("unexpected public URL %q", got.PublicRepoURL()) } } func TestPublicRepoURLEscapesObjectPath(t *testing.T) { spec := Spec{ Bucket: "bucket", Prefix: "projects/my repo.git", Endpoint: "https://example.invalid", PublicURL: "https://public.invalid/git", } raw, err := Build(spec) if err != nil { t.Fatal(err) } parsed, err := Parse(raw) if err != nil { t.Fatal(err) } if got := parsed.PublicRepoURL(); got != "https://public.invalid/git/projects/my%20repo.git" { t.Fatalf("unexpected public URL %q", got) } } func TestRejectsUnsafeLocations(t *testing.T) { tests := []struct { name string spec Spec want string }{ { name: "parent prefix", spec: Spec{Bucket: "bucket", Prefix: "../other.git", Endpoint: "https://example.invalid"}, want: "canonical relative object path", }, { name: "duplicate separator", spec: Spec{Bucket: "bucket", Prefix: "projects//repo.git", Endpoint: "https://example.invalid"}, want: "canonical relative object path", }, { name: "endpoint scheme", spec: Spec{Bucket: "bucket", Prefix: "repo.git", Endpoint: "file:///tmp/bucket"}, want: "absolute HTTP or HTTPS URL", }, { name: "public credentials", spec: Spec{Bucket: "bucket", Prefix: "repo.git", Endpoint: "https://example.invalid", PublicURL: "https://user:pass@public.invalid"}, want: "must not contain credentials", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, err := Build(test.spec) if err == nil || !strings.Contains(err.Error(), test.want) { t.Fatalf("Build() error = %v, want %q", err, test.want) } }) } } func TestParseRejectsEmbeddedSecret(t *testing.T) { _, err := Parse("dumbforge://profile:secret@bucket/repo.git?endpoint=https%3A%2F%2Fexample.invalid") if err == nil || !strings.Contains(err.Error(), "must not be embedded") { t.Fatalf("Parse() error = %v", err) } }