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 package org.eclipse.jgit.lib;
45
46 import static org.eclipse.jgit.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertEquals;
48
49 import org.eclipse.jgit.junit.MockSystemReader;
50 import org.eclipse.jgit.util.SystemReader;
51 import org.junit.Test;
52
53 public class ValidRefNameTest {
54 private static void assertValid(boolean exp, String name) {
55 SystemReader instance = SystemReader.getInstance();
56 try {
57 setUnixSystemReader();
58 assertEquals("\"" + name + "\"", exp,
59 Repository.isValidRefName(name));
60 setWindowsSystemReader();
61 assertEquals("\"" + name + "\"", exp,
62 Repository.isValidRefName(name));
63 } finally {
64 SystemReader.setInstance(instance);
65 }
66 }
67
68 private static void setWindowsSystemReader() {
69 SystemReader.setInstance(new MockSystemReader() {
70 {
71 setWindows();
72 }
73 });
74 }
75
76 private static void setUnixSystemReader() {
77 SystemReader.setInstance(new MockSystemReader() {
78 {
79 setUnix();
80 }
81 });
82 }
83
84 private static void assertInvalidOnWindows(String name) {
85 SystemReader instance = SystemReader.getInstance();
86 try {
87 setUnixSystemReader();
88 assertEquals("\"" + name + "\"", true,
89 Repository.isValidRefName(name));
90 setWindowsSystemReader();
91 assertEquals("\"" + name + "\"", false,
92 Repository.isValidRefName(name));
93 } finally {
94 SystemReader.setInstance(instance);
95 }
96 }
97
98 private static void assertNormalized(final String name,
99 final String expected) {
100 SystemReader instance = SystemReader.getInstance();
101 try {
102 setUnixSystemReader();
103 String normalized = Repository.normalizeBranchName(name);
104 assertEquals("Normalization of " + name, expected, normalized);
105 assertEquals("\"" + normalized + "\"", true,
106 Repository.isValidRefName(Constants.R_HEADS + normalized));
107 setWindowsSystemReader();
108 normalized = Repository.normalizeBranchName(name);
109 assertEquals("Normalization of " + name, expected, normalized);
110 assertEquals("\"" + normalized + "\"", true,
111 Repository.isValidRefName(Constants.R_HEADS + normalized));
112 } finally {
113 SystemReader.setInstance(instance);
114 }
115 }
116
117 @Test
118 public void testEmptyString() {
119 assertValid(false, "");
120 assertValid(false, "/");
121 }
122
123 @Test
124 public void testMustHaveTwoComponents() {
125 assertValid(false, "master");
126 assertValid(true, "heads/master");
127 }
128
129 @Test
130 public void testValidHead() {
131 assertValid(true, "refs/heads/master");
132 assertValid(true, "refs/heads/pu");
133 assertValid(true, "refs/heads/z");
134 assertValid(true, "refs/heads/FoO");
135 }
136
137 @Test
138 public void testValidTag() {
139 assertValid(true, "refs/tags/v1.0");
140 }
141
142 @Test
143 public void testNoLockSuffix() {
144 assertValid(false, "refs/heads/master.lock");
145 }
146
147 @Test
148 public void testNoDirectorySuffix() {
149 assertValid(false, "refs/heads/master/");
150 }
151
152 @Test
153 public void testNoSpace() {
154 assertValid(false, "refs/heads/i haz space");
155 }
156
157 @Test
158 public void testNoAsciiControlCharacters() {
159 for (char c = '\0'; c < ' '; c++)
160 assertValid(false, "refs/heads/mast" + c + "er");
161 }
162
163 @Test
164 public void testNoBareDot() {
165 assertValid(false, "refs/heads/.");
166 assertValid(false, "refs/heads/..");
167 assertValid(false, "refs/heads/./master");
168 assertValid(false, "refs/heads/../master");
169 }
170
171 @Test
172 public void testNoLeadingOrTrailingDot() {
173 assertValid(false, ".");
174 assertValid(false, "refs/heads/.bar");
175 assertValid(false, "refs/heads/..bar");
176 assertValid(false, "refs/heads/bar.");
177 }
178
179 @Test
180 public void testContainsDot() {
181 assertValid(true, "refs/heads/m.a.s.t.e.r");
182 assertValid(false, "refs/heads/master..pu");
183 }
184
185 @Test
186 public void testNoMagicRefCharacters() {
187 assertValid(false, "refs/heads/master^");
188 assertValid(false, "refs/heads/^master");
189 assertValid(false, "^refs/heads/master");
190
191 assertValid(false, "refs/heads/master~");
192 assertValid(false, "refs/heads/~master");
193 assertValid(false, "~refs/heads/master");
194
195 assertValid(false, "refs/heads/master:");
196 assertValid(false, "refs/heads/:master");
197 assertValid(false, ":refs/heads/master");
198 }
199
200 @Test
201 public void testShellGlob() {
202 assertValid(false, "refs/heads/master?");
203 assertValid(false, "refs/heads/?master");
204 assertValid(false, "?refs/heads/master");
205
206 assertValid(false, "refs/heads/master[");
207 assertValid(false, "refs/heads/[master");
208 assertValid(false, "[refs/heads/master");
209
210 assertValid(false, "refs/heads/master*");
211 assertValid(false, "refs/heads/*master");
212 assertValid(false, "*refs/heads/master");
213 }
214
215 @Test
216 public void testValidSpecialCharacterUnixs() {
217 assertValid(true, "refs/heads/!");
218 assertValid(true, "refs/heads/#");
219 assertValid(true, "refs/heads/$");
220 assertValid(true, "refs/heads/%");
221 assertValid(true, "refs/heads/&");
222 assertValid(true, "refs/heads/'");
223 assertValid(true, "refs/heads/(");
224 assertValid(true, "refs/heads/)");
225 assertValid(true, "refs/heads/+");
226 assertValid(true, "refs/heads/,");
227 assertValid(true, "refs/heads/-");
228 assertValid(true, "refs/heads/;");
229 assertValid(true, "refs/heads/=");
230 assertValid(true, "refs/heads/@");
231 assertValid(true, "refs/heads/]");
232 assertValid(true, "refs/heads/_");
233 assertValid(true, "refs/heads/`");
234 assertValid(true, "refs/heads/{");
235 assertValid(true, "refs/heads/}");
236
237
238
239
240 assertValid(false, "refs/heads/\\");
241
242
243 assertInvalidOnWindows("refs/heads/\"");
244 assertInvalidOnWindows("refs/heads/<");
245 assertInvalidOnWindows("refs/heads/>");
246 assertInvalidOnWindows("refs/heads/|");
247 }
248
249 @Test
250 public void testUnicodeNames() {
251 assertValid(true, "refs/heads/\u00e5ngstr\u00f6m");
252 }
253
254 @Test
255 public void testRefLogQueryIsValidRef() {
256 assertValid(false, "refs/heads/master@{1}");
257 assertValid(false, "refs/heads/master@{1.hour.ago}");
258 }
259
260 @Test
261 public void testWindowsReservedNames() {
262
263
264 assertInvalidOnWindows("refs/heads/con");
265 assertInvalidOnWindows("refs/con/x");
266 assertInvalidOnWindows("con/heads/x");
267 assertValid(true, "refs/heads/conx");
268 assertValid(true, "refs/heads/xcon");
269 }
270
271 @Test
272 public void testNormalizeBranchName() {
273 assertEquals("", Repository.normalizeBranchName(null));
274 assertEquals("", Repository.normalizeBranchName(""));
275 assertNormalized("Bug 12345::::Hello World", "Bug_12345-Hello_World");
276 assertNormalized("Bug 12345 :::: Hello World", "Bug_12345_Hello_World");
277 assertNormalized("Bug 12345 :::: Hello::: World",
278 "Bug_12345_Hello-World");
279 assertNormalized(":::Bug 12345 - Hello World", "Bug_12345_Hello_World");
280 assertNormalized("---Bug 12345 - Hello World", "Bug_12345_Hello_World");
281 assertNormalized("Bug 12345 ---- Hello --- World",
282 "Bug_12345_Hello_World");
283 assertNormalized("Bug 12345 - Hello World!", "Bug_12345_Hello_World!");
284 assertNormalized("Bug 12345 : Hello World!", "Bug_12345_Hello_World!");
285 assertNormalized("Bug 12345 _ Hello World!", "Bug_12345_Hello_World!");
286 assertNormalized("Bug 12345 - Hello World!",
287 "Bug_12345_Hello_World!");
288 assertNormalized(" Bug 12345 - Hello World! ",
289 "Bug_12345_Hello_World!");
290 assertNormalized(" Bug 12345 - Hello World! ",
291 "Bug_12345_Hello_World!");
292 assertNormalized("Bug 12345 - Hello______ World!",
293 "Bug_12345_Hello_World!");
294 assertNormalized("_Bug 12345 - Hello World!", "Bug_12345_Hello_World!");
295 }
296
297 @Test
298 public void testNormalizeWithSlashes() {
299 assertNormalized("foo/bar/baz", "foo/bar/baz");
300 assertNormalized("foo/bar.lock/baz.lock", "foo/bar_lock/baz_lock");
301 assertNormalized("foo/.git/.git~1/bar", "foo/git/git-1/bar");
302 assertNormalized(".foo/aux/con/com3.txt/com0/prn/lpt1",
303 "foo/+aux/+con/+com3.txt/com0/+prn/+lpt1");
304 assertNormalized("foo/../bar///.--ba...z", "foo/bar/ba.z");
305 }
306
307 @Test
308 public void testNormalizeWithUnicode() {
309 assertNormalized("f\u00f6\u00f6/.b\u00e0r/*[<>|^~/b\u00e9\\z",
310 "f\u00f6\u00f6/b\u00e0r/b\u00e9-z");
311 assertNormalized("\u5165\u53e3 entrance;/.\u51fa\u53e3_*ex*it*/",
312 "\u5165\u53e3_entrance;/\u51fa\u53e3_ex-it");
313 }
314
315 @Test
316 public void testNormalizeAlreadyValidRefName() {
317 assertNormalized("refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r");
318 assertNormalized("refs/tags/v1.0-20170223", "refs/tags/v1.0-20170223");
319 }
320
321 @Test
322 public void testNormalizeTrimmedUnicodeAlreadyValidRefName() {
323 assertNormalized(" \u00e5ngstr\u00f6m\t", "\u00e5ngstr\u00f6m");
324 }
325 }