blob: e6402a46dc3d40fca970e6e7e6ba6795e3468ada [file] [log] [blame]
/*
* 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);
}
}