001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.util;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023import static org.junit.Assert.fail;
024
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Iterator;
028import java.util.List;
029import java.util.NoSuchElementException;
030import org.apache.hadoop.hbase.HBaseClassTestRule;
031import org.apache.hadoop.hbase.testclassification.MiscTests;
032import org.apache.hadoop.hbase.testclassification.SmallTests;
033import org.junit.ClassRule;
034import org.junit.Test;
035import org.junit.experimental.categories.Category;
036
037@Category({ MiscTests.class, SmallTests.class })
038public class TestConcatenatedLists {
039
040  @ClassRule
041  public static final HBaseClassTestRule CLASS_RULE =
042    HBaseClassTestRule.forClass(TestConcatenatedLists.class);
043
044  @Test
045  public void testUnsupportedOps() {
046    // If adding support, add tests.
047    ConcatenatedLists<Long> c = new ConcatenatedLists<>();
048    c.addSublist(Arrays.asList(0L, 1L));
049    try {
050      c.add(2L);
051      fail("Should throw");
052    } catch (UnsupportedOperationException ex) {
053    }
054    try {
055      c.addAll(Arrays.asList(2L, 3L));
056      fail("Should throw");
057    } catch (UnsupportedOperationException ex) {
058    }
059    try {
060      c.remove(0L);
061      fail("Should throw");
062    } catch (UnsupportedOperationException ex) {
063    }
064    try {
065      c.removeAll(Arrays.asList(0L, 1L));
066      fail("Should throw");
067    } catch (UnsupportedOperationException ex) {
068    }
069    try {
070      c.clear();
071      fail("Should throw");
072    } catch (UnsupportedOperationException ex) {
073    }
074    try {
075      c.retainAll(Arrays.asList(0L, 2L));
076      fail("Should throw");
077    } catch (UnsupportedOperationException ex) {
078    }
079    Iterator<Long> iter = c.iterator();
080    iter.next();
081    try {
082      iter.remove();
083      fail("Should throw");
084    } catch (UnsupportedOperationException ex) {
085    }
086  }
087
088  @Test
089  public void testEmpty() {
090    verify(new ConcatenatedLists<>(), -1);
091  }
092
093  @Test
094  public void testOneOne() {
095    ConcatenatedLists<Long> c = new ConcatenatedLists<>();
096    c.addSublist(Arrays.asList(0L));
097    verify(c, 0);
098  }
099
100  @Test
101  public void testOneMany() {
102    ConcatenatedLists<Long> c = new ConcatenatedLists<>();
103    c.addSublist(Arrays.asList(0L, 1L, 2L));
104    verify(c, 2);
105  }
106
107  @Test
108  @SuppressWarnings("unchecked")
109  public void testManyOne() {
110    ConcatenatedLists<Long> c = new ConcatenatedLists<>();
111    c.addSublist(Arrays.asList(0L));
112    c.addAllSublists(Arrays.asList(Arrays.asList(1L), Arrays.asList(2L)));
113    verify(c, 2);
114  }
115
116  @Test
117  public void testManyMany() {
118    ConcatenatedLists<Long> c = new ConcatenatedLists<>();
119    c.addAllSublists(Arrays.asList(Arrays.asList(0L, 1L)));
120    c.addSublist(Arrays.asList(2L, 3L, 4L));
121    c.addAllSublists(Arrays.asList(Arrays.asList(5L), Arrays.asList(6L, 7L)));
122    verify(c, 7);
123  }
124
125  @SuppressWarnings("ModifyingCollectionWithItself")
126  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "DMI_VACUOUS_SELF_COLLECTION_CALL",
127      justification = "Intended vacuous containsAll call on 'c'")
128  private void verify(ConcatenatedLists<Long> c, int last) {
129    assertEquals((last == -1), c.isEmpty());
130    assertEquals(last + 1, c.size());
131    // This check is O(n^2), test with care
132    assertTrue(c.containsAll(c));
133    Long[] array = c.toArray(new Long[c.size()]);
134    List<Long> all = new ArrayList<>();
135    Iterator<Long> iter = c.iterator();
136    for (Long i = 0L; i <= last; ++i) {
137      assertTrue(iter.hasNext());
138      assertEquals(i, iter.next());
139      assertEquals(i, array[i.intValue()]);
140      assertTrue(c.contains(i));
141      assertTrue(c.containsAll(Arrays.asList(i)));
142      all.add(i);
143    }
144    assertTrue(c.containsAll(all));
145    assertFalse(iter.hasNext());
146    try {
147      iter.next();
148      fail("Should have thrown");
149    } catch (NoSuchElementException nsee) {
150      // Expected
151    }
152  }
153}