aboutsummaryrefslogtreecommitdiff
path: root/ref/name/validate_test.go
blob: b32e4ff01e55e013754c3bc152b378d40df462c0 (about) (plain) (blame)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package name_test

import (
	"testing"

	"lindenii.org/go/furgit/internal/testgit"
	"lindenii.org/go/furgit/ref/name"
)

func TestValidate(t *testing.T) {
	t.Parallel()

	repo, err := testgit.NewRepo(t, testgit.RepoOptions{})
	if err != nil {
		t.Fatalf("NewRepo: %v", err)
	}

	type testCase struct {
		name string
		opts name.Options //exhaustruct:optional
	}

	tests := []testCase{
		{name: ""},
		{name: "/"},
		{name: "/", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "foo/bar/baz"},
		{name: "refs/heads/main"},
		{name: "refs/tags/v1.0.0"},
		{name: "refs///heads/foo"},
		{name: "heads/foo/"},
		{name: "/heads/foo"},
		{name: "///heads/foo"},
		{name: "./foo"},
		{name: "./foo/bar"},
		{name: "foo/./bar"},
		{name: "foo/bar/."},
		{name: ".refs/foo"},
		{name: "refs/heads/foo."},
		{name: "HEAD"},
		{name: "HEAD", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "refs/heads/.main"},
		{name: "heads/foo..bar"},
		{name: "refs/heads/main.lock"},
		{name: "heads///foo.lock"},
		{name: "refs/heads/foo..bar"},
		{name: "refs/heads/foo bar"},
		{name: "refs/heads/foo@{bar"},
		{name: "heads/foo?bar"},
		{name: "foo./bar"},
		{name: "foo.lock/bar"},
		{name: "foo.lock///bar"},
		{name: "heads/foo@bar"},
		{name: "heads/foo\\bar"},
		{name: "heads/foo\tbar"},
		{name: "heads/foo\x7fbar"},
		{name: "heads/fu\xC3\x9F"},
		{name: "heads/*foo/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "heads/foo*/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "heads/f*o/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "heads/f*o*/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "heads/foo*/bar*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "refs/heads/foo/bar."},
		{name: "refs//heads///main"},
		{name: "foo"},
		{name: "foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "foo/bar"},
		{name: "foo/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "foo/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "foo/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "refs/heads/*"},
		{name: "refs/heads/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "refs/heads/feature*branch", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "refs/heads/foo*bar*baz", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "foo/*"},
		{name: "foo/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "foo/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "foo/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "*/foo"},
		{name: "*/foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "*/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "*/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "foo/*/bar"},
		{name: "foo/*/bar", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "foo/*/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "foo/*/bar", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "*"},
		{name: "*", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "foo/*/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "foo/*/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "*/foo/*", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "*/foo/*", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "*/*/foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "*/*/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "/foo"},
		{name: "/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: false}},
		{name: "/foo", opts: name.Options{AllowOneLevel: false, RefspecPattern: true}},
		{name: "/foo", opts: name.Options{AllowOneLevel: true, RefspecPattern: true}},
		{name: "@"},
	}

	for _, tt := range tests {
		t.Run(tt.name+"_"+tt.opts.String(), func(t *testing.T) {
			t.Parallel()

			err := name.Validate(tt.name, tt.opts)
			gitErr := repo.CheckRefFormat(t, tt.name, testgit.RefFormatOptions(tt.opts))

			if (err == nil) != (gitErr == nil) {
				t.Fatalf("Validate(%q, %+v) err=%v, git err=%v", tt.name, tt.opts, err, gitErr)
			}
		})
	}
}

func TestSanitizeComponent(t *testing.T) {
	t.Parallel()

	tests := []struct {
		component string
		want      string
	}{
		{component: ".", want: "-"},
		{component: "..", want: "-"},
		{component: "foo..bar", want: "foo.bar"},
		{component: "foo.lock", want: "foo"},
		{component: "foo.lock.lock", want: "foo"},
		{component: "foo bar", want: "foo-bar"},
		{component: "@", want: "-/@"},
		{component: "a@{b", want: "a@-b"},
		{component: "a*b", want: "a-b"},
	}

	for _, tt := range tests {
		if got := name.SanitizeComponent(tt.component); got != tt.want {
			t.Fatalf("SanitizeComponent(%q) = %q, want %q", tt.component, got, tt.want)
		}
	}
}