| /* |
| * Copyright (C) 2010, Google Inc. |
| * and other copyright owners as documented in the project's IP log. |
| * |
| * This program and the accompanying materials are made available |
| * under the terms of the Eclipse Distribution License v1.0 which |
| * accompanies this distribution, is reproduced below, and is |
| * available at http://www.eclipse.org/org/documents/edl-v10.php |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or |
| * without modification, are permitted provided that the following |
| * conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * |
| * - Neither the name of the Eclipse Foundation, Inc. nor the |
| * names of its contributors may be used to endorse or promote |
| * products derived from this software without specific prior |
| * written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
| * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.eclipse.jgit.util; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| |
| import org.eclipse.jgit.lib.ObjectId; |
| import org.eclipse.jgit.lib.ObjectIdRef; |
| import org.eclipse.jgit.lib.Ref; |
| import org.eclipse.jgit.lib.SymbolicRef; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class RefMapTest { |
| private static final ObjectId ID_ONE = ObjectId |
| .fromString("41eb0d88f833b558bddeb269b7ab77399cdf98ed"); |
| |
| private static final ObjectId ID_TWO = ObjectId |
| .fromString("698dd0b8d0c299f080559a1cffc7fe029479a408"); |
| |
| private RefList<Ref> packed; |
| |
| private RefList<Ref> loose; |
| |
| private RefList<Ref> resolved; |
| |
| @Before |
| public void setUp() throws Exception { |
| packed = RefList.emptyList(); |
| loose = RefList.emptyList(); |
| resolved = RefList.emptyList(); |
| } |
| |
| @Test |
| public void testEmpty_NoPrefix1() { |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertTrue(map.isEmpty()); // before size was computed |
| assertEquals(0, map.size()); |
| assertTrue(map.isEmpty()); // after size was computed |
| |
| assertFalse(map.entrySet().iterator().hasNext()); |
| assertFalse(map.keySet().iterator().hasNext()); |
| assertFalse(map.containsKey("a")); |
| assertNull(map.get("a")); |
| } |
| |
| @Test |
| public void testEmpty_NoPrefix2() { |
| RefMap map = new RefMap(); |
| assertTrue(map.isEmpty()); // before size was computed |
| assertEquals(0, map.size()); |
| assertTrue(map.isEmpty()); // after size was computed |
| |
| assertFalse(map.entrySet().iterator().hasNext()); |
| assertFalse(map.keySet().iterator().hasNext()); |
| assertFalse(map.containsKey("a")); |
| assertNull(map.get("a")); |
| } |
| |
| @Test |
| public void testNotEmpty_NoPrefix() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| packed = toList(master); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertFalse(map.isEmpty()); // before size was computed |
| assertEquals(1, map.size()); |
| assertFalse(map.isEmpty()); // after size was computed |
| assertSame(master, map.values().iterator().next()); |
| } |
| |
| @Test |
| public void testEmpty_WithPrefix() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| packed = toList(master); |
| |
| RefMap map = new RefMap("refs/tags/", packed, loose, resolved); |
| assertTrue(map.isEmpty()); // before size was computed |
| assertEquals(0, map.size()); |
| assertTrue(map.isEmpty()); // after size was computed |
| |
| assertFalse(map.entrySet().iterator().hasNext()); |
| assertFalse(map.keySet().iterator().hasNext()); |
| } |
| |
| @Test |
| public void testNotEmpty_WithPrefix() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| packed = toList(master); |
| |
| RefMap map = new RefMap("refs/heads/", packed, loose, resolved); |
| assertFalse(map.isEmpty()); // before size was computed |
| assertEquals(1, map.size()); |
| assertFalse(map.isEmpty()); // after size was computed |
| assertSame(master, map.values().iterator().next()); |
| } |
| |
| @Test |
| public void testClear() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| loose = toList(master); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertSame(master, map.get("refs/heads/master")); |
| |
| map.clear(); |
| assertNull(map.get("refs/heads/master")); |
| assertTrue(map.isEmpty()); |
| assertEquals(0, map.size()); |
| } |
| |
| @Test |
| public void testIterator_RefusesRemove() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| loose = toList(master); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| Iterator<Ref> itr = map.values().iterator(); |
| assertTrue(itr.hasNext()); |
| assertSame(master, itr.next()); |
| try { |
| itr.remove(); |
| fail("iterator allowed remove"); |
| } catch (UnsupportedOperationException err) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testIterator_FailsAtEnd() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| loose = toList(master); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| Iterator<Ref> itr = map.values().iterator(); |
| assertTrue(itr.hasNext()); |
| assertSame(master, itr.next()); |
| try { |
| itr.next(); |
| fail("iterator allowed next"); |
| } catch (NoSuchElementException err) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testIterator_MissingUnresolvedSymbolicRefIsBug() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| final Ref headR = newRef("HEAD", master); |
| |
| loose = toList(master); |
| // loose should have added newRef("HEAD", "refs/heads/master") |
| resolved = toList(headR); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| Iterator<Ref> itr = map.values().iterator(); |
| try { |
| itr.hasNext(); |
| fail("iterator did not catch bad input"); |
| } catch (IllegalStateException err) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testMerge_HeadMaster() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| final Ref headU = newRef("HEAD", "refs/heads/master"); |
| final Ref headR = newRef("HEAD", master); |
| |
| loose = toList(headU, master); |
| resolved = toList(headR); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertEquals(2, map.size()); |
| assertFalse(map.isEmpty()); |
| assertTrue(map.containsKey("refs/heads/master")); |
| assertSame(master, map.get("refs/heads/master")); |
| |
| // resolved overrides loose given same name |
| assertSame(headR, map.get("HEAD")); |
| |
| Iterator<Ref> itr = map.values().iterator(); |
| assertTrue(itr.hasNext()); |
| assertSame(headR, itr.next()); |
| assertTrue(itr.hasNext()); |
| assertSame(master, itr.next()); |
| assertFalse(itr.hasNext()); |
| } |
| |
| @Test |
| public void testMerge_PackedLooseLoose() { |
| final Ref refA = newRef("A", ID_ONE); |
| final Ref refB_ONE = newRef("B", ID_ONE); |
| final Ref refB_TWO = newRef("B", ID_TWO); |
| final Ref refc = newRef("c", ID_ONE); |
| |
| packed = toList(refA, refB_ONE); |
| loose = toList(refB_TWO, refc); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertEquals(3, map.size()); |
| assertFalse(map.isEmpty()); |
| assertTrue(map.containsKey(refA.getName())); |
| assertSame(refA, map.get(refA.getName())); |
| |
| // loose overrides packed given same name |
| assertSame(refB_TWO, map.get(refB_ONE.getName())); |
| |
| Iterator<Ref> itr = map.values().iterator(); |
| assertTrue(itr.hasNext()); |
| assertSame(refA, itr.next()); |
| assertTrue(itr.hasNext()); |
| assertSame(refB_TWO, itr.next()); |
| assertTrue(itr.hasNext()); |
| assertSame(refc, itr.next()); |
| assertFalse(itr.hasNext()); |
| } |
| |
| @Test |
| public void testMerge_WithPrefix() { |
| final Ref a = newRef("refs/heads/A", ID_ONE); |
| final Ref b = newRef("refs/heads/foo/bar/B", ID_TWO); |
| final Ref c = newRef("refs/heads/foo/rab/C", ID_TWO); |
| final Ref g = newRef("refs/heads/g", ID_ONE); |
| packed = toList(a, b, c, g); |
| |
| RefMap map = new RefMap("refs/heads/foo/", packed, loose, resolved); |
| assertEquals(2, map.size()); |
| |
| assertSame(b, map.get("bar/B")); |
| assertSame(c, map.get("rab/C")); |
| assertNull(map.get("refs/heads/foo/bar/B")); |
| assertNull(map.get("refs/heads/A")); |
| |
| assertTrue(map.containsKey("bar/B")); |
| assertTrue(map.containsKey("rab/C")); |
| assertFalse(map.containsKey("refs/heads/foo/bar/B")); |
| assertFalse(map.containsKey("refs/heads/A")); |
| |
| Iterator<Map.Entry<String, Ref>> itr = map.entrySet().iterator(); |
| Map.Entry<String, Ref> ent; |
| assertTrue(itr.hasNext()); |
| ent = itr.next(); |
| assertEquals("bar/B", ent.getKey()); |
| assertSame(b, ent.getValue()); |
| assertTrue(itr.hasNext()); |
| ent = itr.next(); |
| assertEquals("rab/C", ent.getKey()); |
| assertSame(c, ent.getValue()); |
| assertFalse(itr.hasNext()); |
| } |
| |
| @Test |
| public void testPut_KeyMustMatchName_NoPrefix() { |
| final Ref refA = newRef("refs/heads/A", ID_ONE); |
| RefMap map = new RefMap("", packed, loose, resolved); |
| try { |
| map.put("FOO", refA); |
| fail("map accepted invalid key/value pair"); |
| } catch (IllegalArgumentException err) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testPut_KeyMustMatchName_WithPrefix() { |
| final Ref refA = newRef("refs/heads/A", ID_ONE); |
| RefMap map = new RefMap("refs/heads/", packed, loose, resolved); |
| try { |
| map.put("FOO", refA); |
| fail("map accepted invalid key/value pair"); |
| } catch (IllegalArgumentException err) { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testPut_NoPrefix() { |
| final Ref refA_one = newRef("refs/heads/A", ID_ONE); |
| final Ref refA_two = newRef("refs/heads/A", ID_TWO); |
| |
| packed = toList(refA_one); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertSame(refA_one, map.get(refA_one.getName())); |
| assertSame(refA_one, map.put(refA_one.getName(), refA_two)); |
| |
| // map changed, but packed, loose did not |
| assertSame(refA_two, map.get(refA_one.getName())); |
| assertSame(refA_one, packed.get(0)); |
| assertEquals(0, loose.size()); |
| |
| assertSame(refA_two, map.put(refA_one.getName(), refA_one)); |
| assertSame(refA_one, map.get(refA_one.getName())); |
| } |
| |
| @Test |
| public void testPut_WithPrefix() { |
| final Ref refA_one = newRef("refs/heads/A", ID_ONE); |
| final Ref refA_two = newRef("refs/heads/A", ID_TWO); |
| |
| packed = toList(refA_one); |
| |
| RefMap map = new RefMap("refs/heads/", packed, loose, resolved); |
| assertSame(refA_one, map.get("A")); |
| assertSame(refA_one, map.put("A", refA_two)); |
| |
| // map changed, but packed, loose did not |
| assertSame(refA_two, map.get("A")); |
| assertSame(refA_one, packed.get(0)); |
| assertEquals(0, loose.size()); |
| |
| assertSame(refA_two, map.put("A", refA_one)); |
| assertSame(refA_one, map.get("A")); |
| } |
| |
| @Test |
| public void testPut_CollapseResolved() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| final Ref headU = newRef("HEAD", "refs/heads/master"); |
| final Ref headR = newRef("HEAD", master); |
| final Ref a = newRef("refs/heads/A", ID_ONE); |
| |
| loose = toList(headU, master); |
| resolved = toList(headR); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertNull(map.put(a.getName(), a)); |
| assertSame(a, map.get(a.getName())); |
| assertSame(headR, map.get("HEAD")); |
| } |
| |
| @Test |
| public void testRemove() { |
| final Ref master = newRef("refs/heads/master", ID_ONE); |
| final Ref headU = newRef("HEAD", "refs/heads/master"); |
| final Ref headR = newRef("HEAD", master); |
| |
| packed = toList(master); |
| loose = toList(headU, master); |
| resolved = toList(headR); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertNull(map.remove("not.a.reference")); |
| |
| assertSame(master, map.remove("refs/heads/master")); |
| assertNull(map.get("refs/heads/master")); |
| |
| assertSame(headR, map.remove("HEAD")); |
| assertNull(map.get("HEAD")); |
| |
| assertTrue(map.isEmpty()); |
| } |
| |
| @Test |
| public void testToString_NoPrefix() { |
| final Ref a = newRef("refs/heads/A", ID_ONE); |
| final Ref b = newRef("refs/heads/B", ID_TWO); |
| |
| packed = toList(a, b); |
| |
| StringBuilder exp = new StringBuilder(); |
| exp.append("["); |
| exp.append(a.toString()); |
| exp.append(", "); |
| exp.append(b.toString()); |
| exp.append("]"); |
| |
| RefMap map = new RefMap("", packed, loose, resolved); |
| assertEquals(exp.toString(), map.toString()); |
| } |
| |
| @Test |
| public void testToString_WithPrefix() { |
| final Ref a = newRef("refs/heads/A", ID_ONE); |
| final Ref b = newRef("refs/heads/foo/B", ID_TWO); |
| final Ref c = newRef("refs/heads/foo/C", ID_TWO); |
| final Ref g = newRef("refs/heads/g", ID_ONE); |
| |
| packed = toList(a, b, c, g); |
| |
| StringBuilder exp = new StringBuilder(); |
| exp.append("["); |
| exp.append(b.toString()); |
| exp.append(", "); |
| exp.append(c.toString()); |
| exp.append("]"); |
| |
| RefMap map = new RefMap("refs/heads/foo/", packed, loose, resolved); |
| assertEquals(exp.toString(), map.toString()); |
| } |
| |
| @Test |
| public void testEntryType() { |
| final Ref a = newRef("refs/heads/A", ID_ONE); |
| final Ref b = newRef("refs/heads/B", ID_TWO); |
| |
| packed = toList(a, b); |
| |
| RefMap map = new RefMap("refs/heads/", packed, loose, resolved); |
| Iterator<Map.Entry<String, Ref>> itr = map.entrySet().iterator(); |
| Map.Entry<String, Ref> ent_a = itr.next(); |
| Map.Entry<String, Ref> ent_b = itr.next(); |
| |
| assertEquals(ent_a.hashCode(), "A".hashCode()); |
| assertEquals(ent_a, ent_a); |
| assertFalse(ent_a.equals(ent_b)); |
| |
| assertEquals(a.toString(), ent_a.toString()); |
| } |
| |
| @Test |
| public void testEntryTypeSet() { |
| final Ref refA_one = newRef("refs/heads/A", ID_ONE); |
| final Ref refA_two = newRef("refs/heads/A", ID_TWO); |
| |
| packed = toList(refA_one); |
| |
| RefMap map = new RefMap("refs/heads/", packed, loose, resolved); |
| assertSame(refA_one, map.get("A")); |
| |
| Map.Entry<String, Ref> ent = map.entrySet().iterator().next(); |
| assertEquals("A", ent.getKey()); |
| assertSame(refA_one, ent.getValue()); |
| |
| assertSame(refA_one, ent.setValue(refA_two)); |
| assertSame(refA_two, ent.getValue()); |
| assertSame(refA_two, map.get("A")); |
| assertEquals(1, map.size()); |
| } |
| |
| private static RefList<Ref> toList(Ref... refs) { |
| RefList.Builder<Ref> b = new RefList.Builder<>(refs.length); |
| b.addAll(refs, 0, refs.length); |
| return b.toRefList(); |
| } |
| |
| private static Ref newRef(String name, String dst) { |
| return newRef(name, |
| new ObjectIdRef.Unpeeled(Ref.Storage.NEW, dst, null)); |
| } |
| |
| private static Ref newRef(String name, Ref dst) { |
| return new SymbolicRef(name, dst); |
| } |
| |
| private static Ref newRef(String name, ObjectId id) { |
| return new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, id); |
| } |
| } |