internal/remoteurl/remoteurl_test.go2.4 KB · Go
Raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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:[email protected]"},
			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)
	}
}