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.jupiter.api.Assertions.assertArrayEquals; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertFalse; 023import static org.junit.jupiter.api.Assertions.assertTrue; 024import static org.junit.jupiter.api.Assertions.fail; 025 026import java.util.Comparator; 027import java.util.Iterator; 028import java.util.List; 029import java.util.ListIterator; 030import org.apache.hadoop.hbase.testclassification.MiscTests; 031import org.apache.hadoop.hbase.testclassification.SmallTests; 032import org.junit.jupiter.api.Tag; 033import org.junit.jupiter.api.Test; 034 035import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 036 037@Tag(MiscTests.TAG) 038@Tag(SmallTests.TAG) 039public class TestSortedList { 040 041 static class StringComparator implements Comparator<String> { 042 @Override 043 public int compare(String o1, String o2) { 044 return o1.compareTo(o2); 045 } 046 } 047 048 @Test 049 public void testSorting() throws Exception { 050 SortedList<String> list = new SortedList<>(new StringComparator()); 051 list.add("c"); 052 list.add("d"); 053 list.add("a"); 054 list.add("b"); 055 056 assertEquals(4, list.size()); 057 assertArrayEquals(new String[] { "a", "b", "c", "d" }, list.toArray(new String[4])); 058 059 list.add("c"); 060 assertEquals(5, list.size()); 061 assertArrayEquals(new String[] { "a", "b", "c", "c", "d" }, list.toArray(new String[5])); 062 063 // Test that removal from head or middle maintains sort 064 list.remove("b"); 065 assertEquals(4, list.size()); 066 assertArrayEquals(new String[] { "a", "c", "c", "d" }, list.toArray(new String[4])); 067 list.remove("c"); 068 assertEquals(3, list.size()); 069 assertArrayEquals(new String[] { "a", "c", "d" }, list.toArray(new String[3])); 070 list.remove("a"); 071 assertEquals(2, list.size()); 072 assertArrayEquals(new String[] { "c", "d" }, list.toArray(new String[2])); 073 } 074 075 @Test 076 public void testReadOnlyIterators() throws Exception { 077 SortedList<String> list = 078 new SortedList<>(Lists.newArrayList("a", "b", "c", "d", "e"), new StringComparator()); 079 080 Iterator<String> i = list.iterator(); 081 i.next(); 082 try { 083 i.remove(); 084 fail("Iterator should have thrown an exception"); 085 } catch (UnsupportedOperationException e) { 086 // ok 087 } 088 089 ListIterator<String> li = list.listIterator(); 090 li.next(); 091 try { 092 li.add("a"); 093 fail("Iterator should have thrown an exception"); 094 } catch (UnsupportedOperationException e) { 095 // ok 096 } 097 try { 098 li.set("b"); 099 fail("Iterator should have thrown an exception"); 100 } catch (UnsupportedOperationException e) { 101 // ok 102 } 103 try { 104 li.remove(); 105 fail("Iterator should have thrown an exception"); 106 } catch (UnsupportedOperationException e) { 107 // ok 108 } 109 } 110 111 @Test 112 public void testIteratorIsolation() throws Exception { 113 SortedList<String> list = 114 new SortedList<>(Lists.newArrayList("a", "b", "c", "d", "e"), new StringComparator()); 115 116 // isolation of remove() 117 Iterator<String> iter = list.iterator(); 118 list.remove("c"); 119 boolean found = false; 120 while (iter.hasNext() && !found) { 121 found = "c".equals(iter.next()); 122 } 123 assertTrue(found); 124 125 iter = list.iterator(); 126 found = false; 127 while (iter.hasNext() && !found) { 128 found = "c".equals(iter.next()); 129 } 130 assertFalse(found); 131 132 // isolation of add() 133 iter = list.iterator(); 134 list.add("f"); 135 found = false; 136 while (iter.hasNext() && !found) { 137 String next = iter.next(); 138 found = "f".equals(next); 139 } 140 assertFalse(found); 141 142 // isolation of addAll() 143 iter = list.iterator(); 144 list.addAll(Lists.newArrayList("g", "h", "i")); 145 found = false; 146 while (iter.hasNext() && !found) { 147 String next = iter.next(); 148 found = "g".equals(next) || "h".equals(next) || "i".equals(next); 149 } 150 assertFalse(found); 151 152 // isolation of clear() 153 iter = list.iterator(); 154 list.clear(); 155 assertEquals(0, list.size()); 156 int size = 0; 157 while (iter.hasNext()) { 158 iter.next(); 159 size++; 160 } 161 assertTrue(size > 0); 162 } 163 164 @Test 165 public void testRandomAccessIsolation() throws Exception { 166 SortedList<String> list = 167 new SortedList<>(Lists.newArrayList("a", "b", "c"), new StringComparator()); 168 List<String> innerList = list.get(); 169 assertEquals("a", innerList.get(0)); 170 assertEquals("b", innerList.get(1)); 171 list.clear(); 172 assertEquals("c", innerList.get(2)); 173 } 174}