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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*
  2. * Copyright (C) 2010, Google Inc.
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.util;
  44. import static org.junit.Assert.assertEquals;
  45. import static org.junit.Assert.assertFalse;
  46. import static org.junit.Assert.assertNull;
  47. import static org.junit.Assert.assertSame;
  48. import static org.junit.Assert.assertTrue;
  49. import static org.junit.Assert.fail;
  50. import java.util.Iterator;
  51. import java.util.Map;
  52. import java.util.NoSuchElementException;
  53. import org.eclipse.jgit.lib.ObjectId;
  54. import org.eclipse.jgit.lib.ObjectIdRef;
  55. import org.eclipse.jgit.lib.Ref;
  56. import org.eclipse.jgit.lib.SymbolicRef;
  57. import org.junit.Before;
  58. import org.junit.Test;
  59. public class RefMapTest {
  60. private static final ObjectId ID_ONE = ObjectId
  61. .fromString("41eb0d88f833b558bddeb269b7ab77399cdf98ed");
  62. private static final ObjectId ID_TWO = ObjectId
  63. .fromString("698dd0b8d0c299f080559a1cffc7fe029479a408");
  64. private RefList<Ref> packed;
  65. private RefList<Ref> loose;
  66. private RefList<Ref> resolved;
  67. @Before
  68. public void setUp() throws Exception {
  69. packed = RefList.emptyList();
  70. loose = RefList.emptyList();
  71. resolved = RefList.emptyList();
  72. }
  73. @Test
  74. public void testEmpty_NoPrefix1() {
  75. RefMap map = new RefMap("", packed, loose, resolved);
  76. assertTrue(map.isEmpty()); // before size was computed
  77. assertEquals(0, map.size());
  78. assertTrue(map.isEmpty()); // after size was computed
  79. assertFalse(map.entrySet().iterator().hasNext());
  80. assertFalse(map.keySet().iterator().hasNext());
  81. assertFalse(map.containsKey("a"));
  82. assertNull(map.get("a"));
  83. }
  84. @Test
  85. public void testEmpty_NoPrefix2() {
  86. RefMap map = new RefMap();
  87. assertTrue(map.isEmpty()); // before size was computed
  88. assertEquals(0, map.size());
  89. assertTrue(map.isEmpty()); // after size was computed
  90. assertFalse(map.entrySet().iterator().hasNext());
  91. assertFalse(map.keySet().iterator().hasNext());
  92. assertFalse(map.containsKey("a"));
  93. assertNull(map.get("a"));
  94. }
  95. @Test
  96. public void testNotEmpty_NoPrefix() {
  97. final Ref master = newRef("refs/heads/master", ID_ONE);
  98. packed = toList(master);
  99. RefMap map = new RefMap("", packed, loose, resolved);
  100. assertFalse(map.isEmpty()); // before size was computed
  101. assertEquals(1, map.size());
  102. assertFalse(map.isEmpty()); // after size was computed
  103. assertSame(master, map.values().iterator().next());
  104. }
  105. @Test
  106. public void testEmpty_WithPrefix() {
  107. final Ref master = newRef("refs/heads/master", ID_ONE);
  108. packed = toList(master);
  109. RefMap map = new RefMap("refs/tags/", packed, loose, resolved);
  110. assertTrue(map.isEmpty()); // before size was computed
  111. assertEquals(0, map.size());
  112. assertTrue(map.isEmpty()); // after size was computed
  113. assertFalse(map.entrySet().iterator().hasNext());
  114. assertFalse(map.keySet().iterator().hasNext());
  115. }
  116. @Test
  117. public void testNotEmpty_WithPrefix() {
  118. final Ref master = newRef("refs/heads/master", ID_ONE);
  119. packed = toList(master);
  120. RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
  121. assertFalse(map.isEmpty()); // before size was computed
  122. assertEquals(1, map.size());
  123. assertFalse(map.isEmpty()); // after size was computed
  124. assertSame(master, map.values().iterator().next());
  125. }
  126. @Test
  127. public void testClear() {
  128. final Ref master = newRef("refs/heads/master", ID_ONE);
  129. loose = toList(master);
  130. RefMap map = new RefMap("", packed, loose, resolved);
  131. assertSame(master, map.get("refs/heads/master"));
  132. map.clear();
  133. assertNull(map.get("refs/heads/master"));
  134. assertTrue(map.isEmpty());
  135. assertEquals(0, map.size());
  136. }
  137. @Test
  138. public void testIterator_RefusesRemove() {
  139. final Ref master = newRef("refs/heads/master", ID_ONE);
  140. loose = toList(master);
  141. RefMap map = new RefMap("", packed, loose, resolved);
  142. Iterator<Ref> itr = map.values().iterator();
  143. assertTrue(itr.hasNext());
  144. assertSame(master, itr.next());
  145. try {
  146. itr.remove();
  147. fail("iterator allowed remove");
  148. } catch (UnsupportedOperationException err) {
  149. // expected
  150. }
  151. }
  152. @Test
  153. public void testIterator_FailsAtEnd() {
  154. final Ref master = newRef("refs/heads/master", ID_ONE);
  155. loose = toList(master);
  156. RefMap map = new RefMap("", packed, loose, resolved);
  157. Iterator<Ref> itr = map.values().iterator();
  158. assertTrue(itr.hasNext());
  159. assertSame(master, itr.next());
  160. try {
  161. itr.next();
  162. fail("iterator allowed next");
  163. } catch (NoSuchElementException err) {
  164. // expected
  165. }
  166. }
  167. @Test
  168. public void testIterator_MissingUnresolvedSymbolicRefIsBug() {
  169. final Ref master = newRef("refs/heads/master", ID_ONE);
  170. final Ref headR = newRef("HEAD", master);
  171. loose = toList(master);
  172. // loose should have added newRef("HEAD", "refs/heads/master")
  173. resolved = toList(headR);
  174. RefMap map = new RefMap("", packed, loose, resolved);
  175. Iterator<Ref> itr = map.values().iterator();
  176. try {
  177. itr.hasNext();
  178. fail("iterator did not catch bad input");
  179. } catch (IllegalStateException err) {
  180. // expected
  181. }
  182. }
  183. @Test
  184. public void testMerge_HeadMaster() {
  185. final Ref master = newRef("refs/heads/master", ID_ONE);
  186. final Ref headU = newRef("HEAD", "refs/heads/master");
  187. final Ref headR = newRef("HEAD", master);
  188. loose = toList(headU, master);
  189. resolved = toList(headR);
  190. RefMap map = new RefMap("", packed, loose, resolved);
  191. assertEquals(2, map.size());
  192. assertFalse(map.isEmpty());
  193. assertTrue(map.containsKey("refs/heads/master"));
  194. assertSame(master, map.get("refs/heads/master"));
  195. // resolved overrides loose given same name
  196. assertSame(headR, map.get("HEAD"));
  197. Iterator<Ref> itr = map.values().iterator();
  198. assertTrue(itr.hasNext());
  199. assertSame(headR, itr.next());
  200. assertTrue(itr.hasNext());
  201. assertSame(master, itr.next());
  202. assertFalse(itr.hasNext());
  203. }
  204. @Test
  205. public void testMerge_PackedLooseLoose() {
  206. final Ref refA = newRef("A", ID_ONE);
  207. final Ref refB_ONE = newRef("B", ID_ONE);
  208. final Ref refB_TWO = newRef("B", ID_TWO);
  209. final Ref refc = newRef("c", ID_ONE);
  210. packed = toList(refA, refB_ONE);
  211. loose = toList(refB_TWO, refc);
  212. RefMap map = new RefMap("", packed, loose, resolved);
  213. assertEquals(3, map.size());
  214. assertFalse(map.isEmpty());
  215. assertTrue(map.containsKey(refA.getName()));
  216. assertSame(refA, map.get(refA.getName()));
  217. // loose overrides packed given same name
  218. assertSame(refB_TWO, map.get(refB_ONE.getName()));
  219. Iterator<Ref> itr = map.values().iterator();
  220. assertTrue(itr.hasNext());
  221. assertSame(refA, itr.next());
  222. assertTrue(itr.hasNext());
  223. assertSame(refB_TWO, itr.next());
  224. assertTrue(itr.hasNext());
  225. assertSame(refc, itr.next());
  226. assertFalse(itr.hasNext());
  227. }
  228. @Test
  229. public void testMerge_WithPrefix() {
  230. final Ref a = newRef("refs/heads/A", ID_ONE);
  231. final Ref b = newRef("refs/heads/foo/bar/B", ID_TWO);
  232. final Ref c = newRef("refs/heads/foo/rab/C", ID_TWO);
  233. final Ref g = newRef("refs/heads/g", ID_ONE);
  234. packed = toList(a, b, c, g);
  235. RefMap map = new RefMap("refs/heads/foo/", packed, loose, resolved);
  236. assertEquals(2, map.size());
  237. assertSame(b, map.get("bar/B"));
  238. assertSame(c, map.get("rab/C"));
  239. assertNull(map.get("refs/heads/foo/bar/B"));
  240. assertNull(map.get("refs/heads/A"));
  241. assertTrue(map.containsKey("bar/B"));
  242. assertTrue(map.containsKey("rab/C"));
  243. assertFalse(map.containsKey("refs/heads/foo/bar/B"));
  244. assertFalse(map.containsKey("refs/heads/A"));
  245. Iterator<Map.Entry<String, Ref>> itr = map.entrySet().iterator();
  246. Map.Entry<String, Ref> ent;
  247. assertTrue(itr.hasNext());
  248. ent = itr.next();
  249. assertEquals("bar/B", ent.getKey());
  250. assertSame(b, ent.getValue());
  251. assertTrue(itr.hasNext());
  252. ent = itr.next();
  253. assertEquals("rab/C", ent.getKey());
  254. assertSame(c, ent.getValue());
  255. assertFalse(itr.hasNext());
  256. }
  257. @Test
  258. public void testPut_KeyMustMatchName_NoPrefix() {
  259. final Ref refA = newRef("refs/heads/A", ID_ONE);
  260. RefMap map = new RefMap("", packed, loose, resolved);
  261. try {
  262. map.put("FOO", refA);
  263. fail("map accepted invalid key/value pair");
  264. } catch (IllegalArgumentException err) {
  265. // expected
  266. }
  267. }
  268. @Test
  269. public void testPut_KeyMustMatchName_WithPrefix() {
  270. final Ref refA = newRef("refs/heads/A", ID_ONE);
  271. RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
  272. try {
  273. map.put("FOO", refA);
  274. fail("map accepted invalid key/value pair");
  275. } catch (IllegalArgumentException err) {
  276. // expected
  277. }
  278. }
  279. @Test
  280. public void testPut_NoPrefix() {
  281. final Ref refA_one = newRef("refs/heads/A", ID_ONE);
  282. final Ref refA_two = newRef("refs/heads/A", ID_TWO);
  283. packed = toList(refA_one);
  284. RefMap map = new RefMap("", packed, loose, resolved);
  285. assertSame(refA_one, map.get(refA_one.getName()));
  286. assertSame(refA_one, map.put(refA_one.getName(), refA_two));
  287. // map changed, but packed, loose did not
  288. assertSame(refA_two, map.get(refA_one.getName()));
  289. assertSame(refA_one, packed.get(0));
  290. assertEquals(0, loose.size());
  291. assertSame(refA_two, map.put(refA_one.getName(), refA_one));
  292. assertSame(refA_one, map.get(refA_one.getName()));
  293. }
  294. @Test
  295. public void testPut_WithPrefix() {
  296. final Ref refA_one = newRef("refs/heads/A", ID_ONE);
  297. final Ref refA_two = newRef("refs/heads/A", ID_TWO);
  298. packed = toList(refA_one);
  299. RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
  300. assertSame(refA_one, map.get("A"));
  301. assertSame(refA_one, map.put("A", refA_two));
  302. // map changed, but packed, loose did not
  303. assertSame(refA_two, map.get("A"));
  304. assertSame(refA_one, packed.get(0));
  305. assertEquals(0, loose.size());
  306. assertSame(refA_two, map.put("A", refA_one));
  307. assertSame(refA_one, map.get("A"));
  308. }
  309. @Test
  310. public void testPut_CollapseResolved() {
  311. final Ref master = newRef("refs/heads/master", ID_ONE);
  312. final Ref headU = newRef("HEAD", "refs/heads/master");
  313. final Ref headR = newRef("HEAD", master);
  314. final Ref a = newRef("refs/heads/A", ID_ONE);
  315. loose = toList(headU, master);
  316. resolved = toList(headR);
  317. RefMap map = new RefMap("", packed, loose, resolved);
  318. assertNull(map.put(a.getName(), a));
  319. assertSame(a, map.get(a.getName()));
  320. assertSame(headR, map.get("HEAD"));
  321. }
  322. @Test
  323. public void testRemove() {
  324. final Ref master = newRef("refs/heads/master", ID_ONE);
  325. final Ref headU = newRef("HEAD", "refs/heads/master");
  326. final Ref headR = newRef("HEAD", master);
  327. packed = toList(master);
  328. loose = toList(headU, master);
  329. resolved = toList(headR);
  330. RefMap map = new RefMap("", packed, loose, resolved);
  331. assertNull(map.remove("not.a.reference"));
  332. assertSame(master, map.remove("refs/heads/master"));
  333. assertNull(map.get("refs/heads/master"));
  334. assertSame(headR, map.remove("HEAD"));
  335. assertNull(map.get("HEAD"));
  336. assertTrue(map.isEmpty());
  337. }
  338. @Test
  339. public void testToString_NoPrefix() {
  340. final Ref a = newRef("refs/heads/A", ID_ONE);
  341. final Ref b = newRef("refs/heads/B", ID_TWO);
  342. packed = toList(a, b);
  343. StringBuilder exp = new StringBuilder();
  344. exp.append("[");
  345. exp.append(a.toString());
  346. exp.append(", ");
  347. exp.append(b.toString());
  348. exp.append("]");
  349. RefMap map = new RefMap("", packed, loose, resolved);
  350. assertEquals(exp.toString(), map.toString());
  351. }
  352. @Test
  353. public void testToString_WithPrefix() {
  354. final Ref a = newRef("refs/heads/A", ID_ONE);
  355. final Ref b = newRef("refs/heads/foo/B", ID_TWO);
  356. final Ref c = newRef("refs/heads/foo/C", ID_TWO);
  357. final Ref g = newRef("refs/heads/g", ID_ONE);
  358. packed = toList(a, b, c, g);
  359. StringBuilder exp = new StringBuilder();
  360. exp.append("[");
  361. exp.append(b.toString());
  362. exp.append(", ");
  363. exp.append(c.toString());
  364. exp.append("]");
  365. RefMap map = new RefMap("refs/heads/foo/", packed, loose, resolved);
  366. assertEquals(exp.toString(), map.toString());
  367. }
  368. @Test
  369. public void testEntryType() {
  370. final Ref a = newRef("refs/heads/A", ID_ONE);
  371. final Ref b = newRef("refs/heads/B", ID_TWO);
  372. packed = toList(a, b);
  373. RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
  374. Iterator<Map.Entry<String, Ref>> itr = map.entrySet().iterator();
  375. Map.Entry<String, Ref> ent_a = itr.next();
  376. Map.Entry<String, Ref> ent_b = itr.next();
  377. assertEquals(ent_a.hashCode(), "A".hashCode());
  378. assertEquals(ent_a, ent_a);
  379. assertFalse(ent_a.equals(ent_b));
  380. assertEquals(a.toString(), ent_a.toString());
  381. }
  382. @Test
  383. public void testEntryTypeSet() {
  384. final Ref refA_one = newRef("refs/heads/A", ID_ONE);
  385. final Ref refA_two = newRef("refs/heads/A", ID_TWO);
  386. packed = toList(refA_one);
  387. RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
  388. assertSame(refA_one, map.get("A"));
  389. Map.Entry<String, Ref> ent = map.entrySet().iterator().next();
  390. assertEquals("A", ent.getKey());
  391. assertSame(refA_one, ent.getValue());
  392. assertSame(refA_one, ent.setValue(refA_two));
  393. assertSame(refA_two, ent.getValue());
  394. assertSame(refA_two, map.get("A"));
  395. assertEquals(1, map.size());
  396. }
  397. private static RefList<Ref> toList(Ref... refs) {
  398. RefList.Builder<Ref> b = new RefList.Builder<>(refs.length);
  399. b.addAll(refs, 0, refs.length);
  400. return b.toRefList();
  401. }
  402. private static Ref newRef(String name, String dst) {
  403. return newRef(name,
  404. new ObjectIdRef.Unpeeled(Ref.Storage.NEW, dst, null));
  405. }
  406. private static Ref newRef(String name, Ref dst) {
  407. return new SymbolicRef(name, dst);
  408. }
  409. private static Ref newRef(String name, ObjectId id) {
  410. return new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, id);
  411. }
  412. }