001package edu.pdx.cs.joy; 002 003import org.junit.jupiter.api.Test; 004 005import java.util.AbstractMap; 006import java.util.Iterator; 007import java.util.NoSuchElementException; 008 009import static org.junit.jupiter.api.Assertions.*; 010 011/** 012 * This is a set of JUnit unit tests that test the functionality of an 013 * {@link AbstractLRUMap LRU Map}. 014 */ 015public abstract class LRUMapTestCase { 016 017 /** 018 * A factory method that creates a new instance of the LRU Map to be tested. 019 * 020 * @param capacity The maximum number of mappings in the newly-created LRU 021 * map 022 * @return A new LRU Map with the given capacity 023 * @throws IllegalArgumentException A map cannot be created 024 */ 025 public abstract <K, V> AbstractLRUMap<K, V> createLRUMap(int capacity); 026 027 /** 028 * Tests creating a new LRU Map 029 * 030 * @see LRUMapTestCase#createLRUMap(int) 031 */ 032 @Test 033 public void testCreate() { 034 createLRUMap(4); 035 } 036 037 /** 038 * Tests the {@link AbstractLRUMap#getStudentNames()} methods 039 */ 040 @Test 041 public void testGetStudentNames() { 042 AbstractLRUMap map = 043 createLRUMap(4); 044 Iterator students = map.getStudentNames().iterator(); 045 System.out.println("\n\nImplemented by:"); 046 while (students.hasNext()) { 047 System.out.println(" " + students.next()); 048 } 049 System.out.println("\n"); 050 } 051 052 /** 053 * Tests that the size of the LRU map is bounded 054 * 055 * @see AbstractLRUMap#put(Object, Object) 056 */ 057 @Test 058 public void testMapSizeIsBounded() { 059 int maxMappings = 4; 060 AbstractLRUMap<Integer, String> map = 061 createLRUMap(maxMappings); 062 assertEquals(0, map.size()); 063 064 for (int i = 0; i < maxMappings; i++) { 065 map.put(i, String.valueOf(i)); 066 assertEquals(i + 1, map.size()); 067 } 068 069 map.put(maxMappings + 1, 070 String.valueOf(maxMappings + 1)); 071 072 assertEquals(maxMappings, map.size()); 073 } 074 075 /** 076 * Makes sure that entrySet() Iterator iterates 077 * 078 * @see AbstractMap#containsKey(Object) 079 */ 080 @Test 081 public void testLRUMappingIterates() { 082 int maxMappings = 4; 083 AbstractLRUMap<Integer, String> map = 084 createLRUMap(maxMappings); 085 assertEquals(0, map.size()); 086 087 for (int i = 0; i < maxMappings; i++) { 088 map.put(i, String.valueOf(i)); 089 assertEquals(i + 1, map.size()); 090 } 091 092 try { 093 // get the iterator for this map's mappings 094 Iterator iter = map.entrySet().iterator(); 095 096 // iterate through the mappings 097 for (int i = 0; i < maxMappings; i++) { 098 iter.next(); 099 } 100 101 // there should be no more mappings so this should 102 // throw a NoSuchElementException error 103 iter.next(); 104 System.out.println("Bad iterator returned by entrySet()." 105 + "\nFix before continuing unit tests."); 106 System.exit(1); 107 108 } catch (IndexOutOfBoundsException ex) { 109 // pass 110 } catch (NoSuchElementException ex) { 111 // pass 112 } 113 } 114 115 /** 116 * Makes sure that the LRU mapping is removed 117 * 118 * @see AbstractLRUMap#put(Object, Object) 119 */ 120 @Test 121 public void testLRUMappingIsRemoved() { 122 int maxMappings = 4; 123 AbstractLRUMap<Integer, String> map = 124 createLRUMap(maxMappings); 125 assertEquals(0, map.size()); 126 127 for (int i = 0; i < maxMappings; i++) { 128 map.put(i, String.valueOf(i)); 129 assertEquals(i + 1, map.size()); 130 } 131 132 assertTrue(map.containsKey(new Integer(0))); 133 134 map.put(maxMappings + 1, 135 String.valueOf(maxMappings + 1)); 136 137 assertTrue(!map.containsKey(new Integer(0))); 138 } 139 140 /** 141 * Tests that getting an element from a map puts it at the end of 142 * the LRU queue. 143 * 144 * @see AbstractLRUMap#get(Object) 145 */ 146 @Test 147 public void testGetFromMap() { 148 int maxMappings = 4; 149 AbstractLRUMap<Integer, String> map = 150 createLRUMap(maxMappings); 151 assertEquals(0, map.size()); 152 153 for (int i = 0; i < maxMappings; i++) { 154 map.put(i, String.valueOf(i)); 155 assertEquals(i + 1, map.size()); 156 } 157 158 assertTrue(map.containsKey(new Integer(0))); 159 assertNotNull(map.get(new Integer(0))); 160 161 map.put(maxMappings + 1, 162 String.valueOf(maxMappings + 1)); 163 164 assertTrue(!map.containsKey(new Integer(1))); 165 } 166 167 /** 168 * Tests getting an non-existent entry 169 * 170 * @see AbstractLRUMap#get(Object) 171 */ 172 @Test 173 public void testGetNonExistent() { 174 int maxMappings = 4; 175 AbstractLRUMap map = 176 createLRUMap(maxMappings); 177 assertEquals(null, map.get("Test")); 178 } 179 180 /** 181 * Tests that removing and element doesn't effect the LRU order 182 * 183 * @see AbstractLRUMap#remove(Object) 184 */ 185 @Test 186 public void testRemoveFromMap() { 187 int maxMappings = 4; 188 AbstractLRUMap<Integer, String> map = 189 createLRUMap(maxMappings); 190 assertEquals(0, map.size()); 191 192 for (int i = 0; i < maxMappings; i++) { 193 map.put(i, String.valueOf(i)); 194 assertEquals(i + 1, map.size()); 195 } 196 197 assertTrue(map.containsKey(new Integer(0))); 198 assertNotNull(map.remove(new Integer(0))); 199 200 map.put(maxMappings + 1, 201 String.valueOf(maxMappings + 1)); 202 assertTrue(map.containsKey(new Integer(1))); 203 204 map.put(maxMappings + 2, 205 String.valueOf(maxMappings + 2)); 206 207 assertTrue(!map.containsKey(new Integer(1))); 208 } 209 210 /** 211 * Tests removing an non-existent entry 212 * 213 * @see AbstractLRUMap#remove(Object) 214 */ 215 @Test 216 public void testRemoveNonExistent() { 217 int maxMappings = 4; 218 AbstractLRUMap map = 219 createLRUMap(maxMappings); 220 assertEquals(null, map.remove("Test")); 221 } 222 223 /** 224 * Tests clearing a map 225 * 226 * @see AbstractLRUMap#clear() 227 */ 228 @Test 229 public void testClear() { 230 int maxMappings = 4; 231 AbstractLRUMap<Integer, String> map = 232 createLRUMap(maxMappings); 233 assertEquals(0, map.size()); 234 235 for (int i = 0; i < maxMappings; i++) { 236 map.put(i, String.valueOf(i)); 237 assertEquals(i + 1, map.size()); 238 } 239 240 map.clear(); 241 assertEquals(0, map.size()); 242 } 243 /** 244 * An obscure and amusing edge case. Parent's method signature throws no exception, so this 245 * method will accept any exception. 246 */ 247 public void testNegativeSize() 248 { 249 try 250 { 251 createLRUMap( -1 ); 252 fail( "Negative sizes should not be accepted" ); 253 } 254 catch( Exception e ) // we don't know what kind of exception the implementor will throw 255 { 256 // success 257 } 258 } 259 260 /** 261 * This will accept EITHER an exception being thrown, or the creation of map that never stores data. 262 */ 263 public void testZeroSize() 264 { 265 AbstractLRUMap<Integer, String> zmap; 266 try 267 { 268 zmap = createLRUMap(0); 269 } 270 catch (Exception e) // we don't know what kind of exception the implementor will throw 271 { 272 // success 273 return; 274 } 275 assertEquals( 0, zmap.size() ); 276 zmap.put( 3, "Three" ); 277 assertEquals(0, zmap.size()); 278 assertNull( zmap.get( 3 ) ); 279 assertEquals( 0, zmap.entrySet().size() ); 280 assertNull( zmap.remove( 3 ) ); 281 282 } 283 284 /* 285 I wrote this to make sure I matched the behavior of a regular map. 286 public void testRegMapCompare() { 287 HashMap<Integer, String> zmap; 288 zmap = new HashMap<Integer, String>(0); 289 assertEquals(0, zmap.size()); 290 assertNull(zmap.get(3)); 291 assertEquals(0, zmap.entrySet().size()); 292 assertNull(zmap.remove(3)); 293 } 294 */ 295 296}