You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AttributesMatcherTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*
  2. * Copyright (C) 2010, Red Hat Inc. and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.attributes;
  11. import static org.junit.Assert.assertEquals;
  12. import static org.junit.Assert.assertFalse;
  13. import static org.junit.Assert.assertNotNull;
  14. import static org.junit.Assert.assertTrue;
  15. import org.junit.Test;
  16. /**
  17. * Tests git attributes pattern matches
  18. */
  19. public class AttributesMatcherTest {
  20. @Test
  21. public void testBasic() {
  22. String pattern = "/test.stp";
  23. assertMatched(pattern, "/test.stp");
  24. pattern = "#/test.stp";
  25. assertNotMatched(pattern, "/test.stp");
  26. }
  27. @Test
  28. public void testFileNameWildcards() {
  29. //Test basic * and ? for any pattern + any character
  30. String pattern = "*.st?";
  31. assertMatched(pattern, "/test.stp");
  32. assertMatched(pattern, "/anothertest.stg");
  33. assertMatched(pattern, "/anothertest.st0");
  34. assertNotMatched(pattern, "/anothertest.sta1");
  35. //Check that asterisk does not expand to "/"
  36. assertNotMatched(pattern, "/another/test.sta1");
  37. //Same as above, with a leading slash to ensure that doesn't cause problems
  38. pattern = "/*.st?";
  39. assertMatched(pattern, "/test.stp");
  40. assertMatched(pattern, "/anothertest.stg");
  41. assertMatched(pattern, "/anothertest.st0");
  42. assertNotMatched(pattern, "/anothertest.sta1");
  43. //Check that asterisk does not expand to "/"
  44. assertNotMatched(pattern, "/another/test.sta1");
  45. //Test for numbers
  46. pattern = "*.sta[0-5]";
  47. assertMatched(pattern, "/test.sta5");
  48. assertMatched(pattern, "/test.sta4");
  49. assertMatched(pattern, "/test.sta3");
  50. assertMatched(pattern, "/test.sta2");
  51. assertMatched(pattern, "/test.sta1");
  52. assertMatched(pattern, "/test.sta0");
  53. assertMatched(pattern, "/anothertest.sta2");
  54. assertNotMatched(pattern, "test.stag");
  55. assertNotMatched(pattern, "test.sta6");
  56. //Test for letters
  57. pattern = "/[tv]est.sta[a-d]";
  58. assertMatched(pattern, "/test.staa");
  59. assertMatched(pattern, "/test.stab");
  60. assertMatched(pattern, "/test.stac");
  61. assertMatched(pattern, "/test.stad");
  62. assertMatched(pattern, "/vest.stac");
  63. assertNotMatched(pattern, "test.stae");
  64. assertNotMatched(pattern, "test.sta9");
  65. //Test child directory/file is matched
  66. pattern = "/src/ne?";
  67. assertMatched(pattern, "/src/new/");
  68. assertMatched(pattern, "/src/new");
  69. assertNotMatched(pattern, "/src/new/a.c");
  70. assertNotMatched(pattern, "/src/new/a/a.c");
  71. assertNotMatched(pattern, "/src/new.c");
  72. //Test name-only fnmatcher matches
  73. pattern = "ne?";
  74. assertMatched(pattern, "/src/new/");
  75. assertMatched(pattern, "/src/new");
  76. assertNotMatched(pattern, "/src/new/a.c");
  77. assertNotMatched(pattern, "/src/new/a/a.c");
  78. assertMatched(pattern, "/neb");
  79. assertNotMatched(pattern, "/src/new.c");
  80. }
  81. @Test
  82. public void testTargetWithoutLeadingSlash() {
  83. //Test basic * and ? for any pattern + any character
  84. String pattern = "/*.st?";
  85. assertMatched(pattern, "test.stp");
  86. assertMatched(pattern, "anothertest.stg");
  87. assertMatched(pattern, "anothertest.st0");
  88. assertNotMatched(pattern, "anothertest.sta1");
  89. //Check that asterisk does not expand to ""
  90. assertNotMatched(pattern, "another/test.sta1");
  91. //Same as above, with a leading slash to ensure that doesn't cause problems
  92. pattern = "/*.st?";
  93. assertMatched(pattern, "test.stp");
  94. assertMatched(pattern, "anothertest.stg");
  95. assertMatched(pattern, "anothertest.st0");
  96. assertNotMatched(pattern, "anothertest.sta1");
  97. //Check that asterisk does not expand to ""
  98. assertNotMatched(pattern, "another/test.sta1");
  99. //Test for numbers
  100. pattern = "/*.sta[0-5]";
  101. assertMatched(pattern, "test.sta5");
  102. assertMatched(pattern, "test.sta4");
  103. assertMatched(pattern, "test.sta3");
  104. assertMatched(pattern, "test.sta2");
  105. assertMatched(pattern, "test.sta1");
  106. assertMatched(pattern, "test.sta0");
  107. assertMatched(pattern, "anothertest.sta2");
  108. assertNotMatched(pattern, "test.stag");
  109. assertNotMatched(pattern, "test.sta6");
  110. //Test for letters
  111. pattern = "/[tv]est.sta[a-d]";
  112. assertMatched(pattern, "test.staa");
  113. assertMatched(pattern, "test.stab");
  114. assertMatched(pattern, "test.stac");
  115. assertMatched(pattern, "test.stad");
  116. assertMatched(pattern, "vest.stac");
  117. assertNotMatched(pattern, "test.stae");
  118. assertNotMatched(pattern, "test.sta9");
  119. //Test child directory/file is matched
  120. pattern = "/src/ne?";
  121. assertMatched(pattern, "src/new/");
  122. assertMatched(pattern, "src/new");
  123. assertNotMatched(pattern, "src/new/a.c");
  124. assertNotMatched(pattern, "src/new/a/a.c");
  125. assertNotMatched(pattern, "src/new.c");
  126. //Test name-only fnmatcher matches
  127. pattern = "ne?";
  128. assertMatched(pattern, "src/new/");
  129. assertMatched(pattern, "src/new");
  130. assertNotMatched(pattern, "src/new/a.c");
  131. assertNotMatched(pattern, "src/new/a/a.c");
  132. assertMatched(pattern, "neb");
  133. assertNotMatched(pattern, "src/new.c");
  134. }
  135. @Test
  136. public void testParentDirectoryGitAttributes() {
  137. //Contains git attribute patterns such as might be seen in a parent directory
  138. //Test for wildcards
  139. String pattern = "/*/*.c";
  140. assertMatched(pattern, "/file/a.c");
  141. assertMatched(pattern, "/src/a.c");
  142. assertNotMatched(pattern, "/src/new/a.c");
  143. //Test child directory/file is matched
  144. pattern = "/src/new";
  145. assertMatched(pattern, "/src/new/");
  146. assertMatched(pattern, "/src/new");
  147. assertNotMatched(pattern, "/src/new/a.c");
  148. assertNotMatched(pattern, "/src/new/a/a.c");
  149. assertNotMatched(pattern, "/src/new.c");
  150. //Test child directory is matched, slash after name
  151. pattern = "/src/new/";
  152. assertMatched(pattern, "/src/new/");
  153. assertNotMatched(pattern, "/src/new/a.c");
  154. assertNotMatched(pattern, "/src/new/a/a.c");
  155. assertNotMatched(pattern, "/src/new");
  156. assertNotMatched(pattern, "/src/new.c");
  157. //Test directory is matched by name only
  158. pattern = "b1";
  159. assertNotMatched(pattern, "/src/new/a/b1/a.c");
  160. assertNotMatched(pattern, "/src/new/a/b2/file.c");
  161. assertNotMatched(pattern, "/src/new/a/bb1/file.c");
  162. assertNotMatched(pattern, "/src/new/a/file.c");
  163. assertNotMatched(pattern, "/src/new/a/bb1");
  164. assertMatched(pattern, "/src/new/a/b1");
  165. }
  166. @Test
  167. public void testTrailingSlash() {
  168. String pattern = "/src/";
  169. assertMatched(pattern, "/src/");
  170. assertNotMatched(pattern, "/src/new");
  171. assertNotMatched(pattern, "/src/new/a.c");
  172. assertNotMatched(pattern, "/src/a.c");
  173. assertNotMatched(pattern, "/src");
  174. assertNotMatched(pattern, "/srcA/");
  175. pattern = "src/";
  176. assertMatched(pattern, "src/");
  177. assertMatched(pattern, "/src/");
  178. assertNotMatched(pattern, "src");
  179. assertNotMatched(pattern, "/src/new");
  180. assertNotMatched(pattern, "/src/new/a.c");
  181. assertNotMatched(pattern, "/src/a.c");
  182. assertNotMatched(pattern, "foo/src/a.c");
  183. assertNotMatched(pattern, "foo/src/bar/a.c");
  184. assertNotMatched(pattern, "foo/src/bar/src");
  185. assertMatched(pattern, "foo/src/");
  186. assertMatched(pattern, "foo/src/bar/src/");
  187. }
  188. @Test
  189. public void testNameOnlyMatches() {
  190. /*
  191. * Name-only matches do not contain any path separators
  192. */
  193. //Test matches for file extension
  194. String pattern = "*.stp";
  195. assertMatched(pattern, "/test.stp");
  196. assertMatched(pattern, "/src/test.stp");
  197. assertNotMatched(pattern, "/test.stp1");
  198. assertNotMatched(pattern, "/test.astp");
  199. assertNotMatched(pattern, "test.stp/foo.bar");
  200. assertMatched(pattern, "test.stp");
  201. assertMatched(pattern, "test.stp/");
  202. assertMatched(pattern, "test.stp/test.stp");
  203. //Test matches for name-only, applies to file name or folder name
  204. pattern = "src";
  205. assertMatched(pattern, "/src");
  206. assertMatched(pattern, "/src/");
  207. assertNotMatched(pattern, "/src/a.c");
  208. assertNotMatched(pattern, "/src/new/a.c");
  209. assertNotMatched(pattern, "/new/src/a.c");
  210. assertMatched(pattern, "/file/src");
  211. //Test matches for name-only, applies only to folder names
  212. pattern = "src/";
  213. assertNotMatched(pattern, "/src/a.c");
  214. assertNotMatched(pattern, "/src/new/a.c");
  215. assertNotMatched(pattern, "/new/src/a.c");
  216. assertNotMatched(pattern, "/src");
  217. assertNotMatched(pattern, "/file/src");
  218. assertMatched(pattern, "/file/src/");
  219. //Test matches for name-only, applies to file name or folder name
  220. //With a small wildcard
  221. pattern = "?rc";
  222. assertNotMatched(pattern, "/src/a.c");
  223. assertNotMatched(pattern, "/src/new/a.c");
  224. assertNotMatched(pattern, "/new/src/a.c");
  225. assertMatched(pattern, "/new/src/");
  226. assertMatched(pattern, "/file/src");
  227. assertMatched(pattern, "/src/");
  228. //Test matches for name-only, applies to file name or folder name
  229. //With a small wildcard
  230. pattern = "?r[a-c]";
  231. assertNotMatched(pattern, "/src/a.c");
  232. assertNotMatched(pattern, "/src/new/a.c");
  233. assertNotMatched(pattern, "/new/src/a.c");
  234. assertMatched(pattern, "/file/src");
  235. assertMatched(pattern, "/src/");
  236. assertNotMatched(pattern, "/srb/a.c");
  237. assertNotMatched(pattern, "/grb/new/a.c");
  238. assertNotMatched(pattern, "/new/crb/a.c");
  239. assertMatched(pattern, "/file/3rb");
  240. assertMatched(pattern, "/xrb/");
  241. assertNotMatched(pattern, "/3ra/a.c");
  242. assertNotMatched(pattern, "/5ra/new/a.c");
  243. assertNotMatched(pattern, "/new/1ra/a.c");
  244. assertNotMatched(pattern, "/new/1ra/a.c/");
  245. assertMatched(pattern, "/file/dra");
  246. assertMatched(pattern, "/file/dra/");
  247. assertMatched(pattern, "/era/");
  248. assertNotMatched(pattern, "/crg");
  249. assertNotMatched(pattern, "/cr3");
  250. }
  251. @Test
  252. public void testGetters() {
  253. AttributesRule r = new AttributesRule("/pattern/", "");
  254. assertFalse(r.isNameOnly());
  255. assertTrue(r.isDirOnly());
  256. assertNotNull(r.getAttributes());
  257. assertTrue(r.getAttributes().isEmpty());
  258. assertEquals(r.getPattern(), "/pattern");
  259. r = new AttributesRule("/patter?/", "");
  260. assertFalse(r.isNameOnly());
  261. assertTrue(r.isDirOnly());
  262. assertNotNull(r.getAttributes());
  263. assertTrue(r.getAttributes().isEmpty());
  264. assertEquals(r.getPattern(), "/patter?");
  265. r = new AttributesRule("patt*", "");
  266. assertTrue(r.isNameOnly());
  267. assertFalse(r.isDirOnly());
  268. assertNotNull(r.getAttributes());
  269. assertTrue(r.getAttributes().isEmpty());
  270. assertEquals(r.getPattern(), "patt*");
  271. r = new AttributesRule("pattern", "attribute1");
  272. assertTrue(r.isNameOnly());
  273. assertFalse(r.isDirOnly());
  274. assertNotNull(r.getAttributes());
  275. assertFalse(r.getAttributes().isEmpty());
  276. assertEquals(r.getAttributes().size(), 1);
  277. assertEquals(r.getPattern(), "pattern");
  278. r = new AttributesRule("pattern", "attribute1 -attribute2");
  279. assertTrue(r.isNameOnly());
  280. assertFalse(r.isDirOnly());
  281. assertNotNull(r.getAttributes());
  282. assertEquals(r.getAttributes().size(), 2);
  283. assertEquals(r.getPattern(), "pattern");
  284. r = new AttributesRule("pattern", "attribute1 \t-attribute2 \t");
  285. assertTrue(r.isNameOnly());
  286. assertFalse(r.isDirOnly());
  287. assertNotNull(r.getAttributes());
  288. assertEquals(r.getAttributes().size(), 2);
  289. assertEquals(r.getPattern(), "pattern");
  290. r = new AttributesRule("pattern", "attribute1\t-attribute2\t");
  291. assertTrue(r.isNameOnly());
  292. assertFalse(r.isDirOnly());
  293. assertNotNull(r.getAttributes());
  294. assertEquals(r.getAttributes().size(), 2);
  295. assertEquals(r.getPattern(), "pattern");
  296. r = new AttributesRule("pattern", "attribute1\t -attribute2\t ");
  297. assertTrue(r.isNameOnly());
  298. assertFalse(r.isDirOnly());
  299. assertNotNull(r.getAttributes());
  300. assertEquals(r.getAttributes().size(), 2);
  301. assertEquals(r.getPattern(), "pattern");
  302. r = new AttributesRule("pattern",
  303. "attribute1 -attribute2 attribute3=value ");
  304. assertTrue(r.isNameOnly());
  305. assertFalse(r.isDirOnly());
  306. assertNotNull(r.getAttributes());
  307. assertEquals(r.getAttributes().size(), 3);
  308. assertEquals(r.getPattern(), "pattern");
  309. assertEquals(r.getAttributes().get(0).toString(), "attribute1");
  310. assertEquals(r.getAttributes().get(1).toString(), "-attribute2");
  311. assertEquals(r.getAttributes().get(2).toString(), "attribute3=value");
  312. }
  313. @Test
  314. public void testBracketsInGroup() {
  315. //combinations of brackets in brackets, escaped and not
  316. String[] patterns = new String[]{"[[\\]]", "[\\[\\]]"};
  317. for (String pattern : patterns) {
  318. assertNotMatched(pattern, "");
  319. assertNotMatched(pattern, "[]");
  320. assertNotMatched(pattern, "][");
  321. assertNotMatched(pattern, "[\\[]");
  322. assertNotMatched(pattern, "[[]");
  323. assertNotMatched(pattern, "[[]]");
  324. assertNotMatched(pattern, "[\\[\\]]");
  325. assertMatched(pattern, "[");
  326. assertMatched(pattern, "]");
  327. }
  328. patterns = new String[]{"[[]]", "[\\[]]"};
  329. for (String pattern : patterns) {
  330. assertNotMatched(pattern, "");
  331. assertMatched(pattern, "[]");
  332. assertNotMatched(pattern, "][");
  333. assertNotMatched(pattern, "[\\[]");
  334. assertNotMatched(pattern, "[[]");
  335. assertNotMatched(pattern, "[[]]");
  336. assertNotMatched(pattern, "[\\[\\]]");
  337. assertNotMatched(pattern, "[");
  338. assertNotMatched(pattern, "]");
  339. }
  340. }
  341. @Test
  342. public void testFileNameWithLineTerminator() {
  343. assertMatched("a?", "a\r");
  344. assertMatched("a?", "dir/a\r");
  345. assertMatched("*a", "\ra");
  346. assertMatched("dir/*a*", "dir/\ra\r");
  347. }
  348. /**
  349. * Check for a match. If target ends with "/", match will assume that the
  350. * target is meant to be a directory.
  351. *
  352. * @param pattern
  353. * Pattern as it would appear in a .gitattributes file
  354. * @param target
  355. * Target file path relative to repository's GIT_DIR
  356. */
  357. private void assertMatched(String pattern, String target) {
  358. boolean value = match(pattern, target);
  359. assertTrue("Expected a match for: " + pattern + " with: " + target,
  360. value);
  361. }
  362. /**
  363. * Check for a match. If target ends with "/", match will assume that the
  364. * target is meant to be a directory.
  365. *
  366. * @param pattern
  367. * Pattern as it would appear in a .gitattributes file
  368. * @param target
  369. * Target file path relative to repository's GIT_DIR
  370. */
  371. private void assertNotMatched(String pattern, String target) {
  372. boolean value = match(pattern, target);
  373. assertFalse("Expected no match for: " + pattern + " with: " + target,
  374. value);
  375. }
  376. /**
  377. * Check for a match. If target ends with "/", match will assume that the
  378. * target is meant to be a directory.
  379. *
  380. * @param pattern
  381. * Pattern as it would appear in a .gitattributes file
  382. * @param target
  383. * Target file path relative to repository's GIT_DIR
  384. * @return Result of {@link AttributesRule#isMatch(String, boolean)}
  385. */
  386. private static boolean match(String pattern, String target) {
  387. AttributesRule r = new AttributesRule(pattern, "");
  388. //If speed of this test is ever an issue, we can use a presetRule field
  389. //to avoid recompiling a pattern each time.
  390. return r.isMatch(target, target.endsWith("/"));
  391. }
  392. }