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