001 /** 002 * This is part of the Problem Set 0: Introduction for CSE331 003 */ 004 package ps0.test; 005 import ps0.*; 006 007 import java.util.Iterator; 008 import java.util.LinkedList; 009 import java.util.Random; 010 import java.util.Set; 011 import java.util.HashSet; 012 013 import org.junit.Test; 014 import org.junit.BeforeClass; 015 import static org.junit.Assert.*; 016 017 /** 018 * BoxTest is a glassbox test of the Box class. 019 * 020 * Recall that like a BallContainer, the Box is a container for Balls and you 021 * can only put a Ball into a Box once. After you put the Ball into 022 * the Box, further attempts to do so will fail, since the Ball is 023 * already in the Box! Similarly, you cannot expect to remove a Ball 024 * from a Box if it is not inside the Box. 025 * 026 * In addition, a Box differs from a ballcontainer because it only has a finite 027 * volume. As Balls get put into a Box, it gets filled up. Once a Box 028 * is full, further attempts to put Balls into the Box will also fail. 029 * 030 * @see ps0.Ball 031 * @see ps0.BallContainer 032 * @see ps0.Box 033 */ 034 public class BoxTest { 035 036 private static Box box = null; 037 private static Ball[] b = null; 038 039 private static final int NUM_BALLS_TO_TEST = 5; 040 private static final int BOX_CAPACITY = NUM_BALLS_TO_TEST - 1; 041 private static final double BALL_UNIT_VOLUME = 10.0; 042 private static final double JUNIT_DOUBLE_DELTA = 0.0001; 043 private static final int TRIES_FOR_BALLS_TEST = 3; 044 045 @BeforeClass 046 public static void setupBeforeTests() throws Exception { 047 assertThat("Test case error, you must test at least 1 Ball!!", 048 NUM_BALLS_TO_TEST, greaterThan(0)); 049 assertThat("This test case is set up assuming that the box cannot contain all the balls, please check and change parameters!", 050 NUM_BALLS_TO_TEST, greaterThan(BOX_CAPACITY)); 051 052 double box_volume = 0; 053 054 // Let's create the balls we need. 055 b = new Ball[NUM_BALLS_TO_TEST]; 056 for (int i=0; i<NUM_BALLS_TO_TEST; i++) { 057 if (i<BOX_CAPACITY) { 058 box_volume += (i+1)*BALL_UNIT_VOLUME; 059 } 060 b[i] = new Ball((i+1)*BALL_UNIT_VOLUME); 061 } 062 063 // Now, we create the box once we figure out how big a box we 064 // need. 065 box = new Box(box_volume); 066 067 } 068 069 /** Test to check that Box.add(Ball) is implemented correctly */ 070 @Test 071 public void testAdd() { 072 box.clear(); 073 for (int i=0; i<BOX_CAPACITY; i++) { 074 assertTrue("Box.add(Ball) failed to add a new Ball!", 075 box.add(b[i])); 076 assertFalse("Box.add(Ball) seems to allow the same Ball to be added twice!", 077 box.add(b[i])); 078 assertTrue("Box does not contain a ball after it is supposed to have been added!", 079 box.contains(b[i])); 080 } 081 for (int i=BOX_CAPACITY; i<NUM_BALLS_TO_TEST; i++) { 082 assertFalse("Box.add(Ball) allows a Ball to be added even though it is already full!", 083 box.add(b[i])); 084 } 085 } 086 087 /** Test to check that Box.getBallsFromSmallest() is implemented correctly */ 088 @Test 089 public void testGetBalls() { 090 Random rnd = new Random(); 091 092 for (int k=0; k<TRIES_FOR_BALLS_TEST; k++) { 093 094 box.clear(); 095 096 // Let's put all the balls into a list. 097 LinkedList<Ball> list = new LinkedList<Ball>(); 098 for (int i=0; i<BOX_CAPACITY; i++) { 099 list.add(b[i]); 100 } 101 102 // First we add the balls to the box in some random order. 103 for (int i=0; i<BOX_CAPACITY; i++) { 104 box.add(list.remove(rnd.nextInt(list.size()))); 105 } 106 107 int contentsSize = box.size(); 108 // Next we call the iterator and check that the balls come out 109 // in the correct order. 110 Iterator<Ball> it = box.getBallsFromSmallest(); 111 int count = 0; 112 while (it.hasNext() && count < BOX_CAPACITY) { 113 Ball ball = it.next(); 114 assertEquals("Balls are not returned by Box.getBallsFromSmallest() iterator in the correct order", 115 b[count], ball); 116 if (b[count] != ball) { 117 break; 118 } 119 count++; 120 } 121 assertEquals("Box.getBallsFromSmallest() did not return all the balls", 122 BOX_CAPACITY, count); 123 assertEquals("Number of balls in box was modified", 124 contentsSize, box.size()); 125 } 126 } 127 128 /** 129 * Test to check that Box.remove(Ball) is implemented 130 * correctly. Depending on how <code>getBallsFromSmallest()</code> 131 * is implemented, remove() might have to be overridden and this 132 * test helps ensure that remove() is not broken in the process. 133 */ 134 @Test 135 public void testRemove() { 136 box.clear(); 137 assertFalse("Box.remove(Ball) should fail because box is empty, but it didn't!", 138 box.remove(b[0])); 139 for (int i=0; i<BOX_CAPACITY; i++) { 140 box.clear(); 141 for (int j=0; j<i; j++) { 142 box.add(b[j]); 143 } 144 for (int j=0; j<i; j++) { 145 assertTrue("Box.remove(Ball) failed to remove a Ball that is supposed to be inside", 146 box.remove(b[j])); 147 assertFalse("Box still contains a ball after it is supposed to have been removed!", 148 box.contains(b[j])); 149 } 150 for (int j=i; j<NUM_BALLS_TO_TEST; j++) { 151 assertFalse("Box.remove(Ball) did not fail for a Ball that is not inside", 152 box.remove(b[j])); 153 } 154 } 155 } 156 157 158 /** Test to check that Box.clear() is implemented correctly */ 159 @Test 160 public void testClear() { 161 box.clear(); 162 assertEquals("Box is not empty after being cleared!", 0, box.size()); 163 box.add(b[0]); 164 box.clear(); 165 assertEquals("Box is not empty after being cleared!", 0, box.size()); 166 } 167 168 /** Test to check that check that we can put a Ball into a Box */ 169 @Test 170 public void testVolume() { 171 box.clear(); 172 assertEquals("Volume of empty Box is not zero!", 173 0, box.getVolume(), JUNIT_DOUBLE_DELTA); 174 for (int i=0; i<BOX_CAPACITY; i++) { 175 box.add(b[i]); 176 assertEquals("Volume of Box with one ball", 177 (i+1)*(i+2)*BALL_UNIT_VOLUME/2, box.getVolume(), 178 JUNIT_DOUBLE_DELTA); 179 } 180 } 181 182 /** Test to check that size() returns the correct number. */ 183 @Test 184 public void testSize() { 185 box.clear(); 186 assertEquals("size() of empty Box is not zero!", 0, box.size()); 187 for (int i=0; i<BOX_CAPACITY; i++) { 188 box.add(b[i]); 189 assertEquals("size() of Box with "+(i+1)+" ball(s)", 190 i+1, box.size()); 191 } 192 } 193 194 /** Test to check that size() returns the correct number. */ 195 @Test 196 public void testContains() { 197 box.clear(); 198 for (int i=0; i<BOX_CAPACITY; i++) { 199 assertFalse("Empty Box seems to contain a ball!", 200 box.contains(b[i])); 201 } 202 for (int i=0; i<BOX_CAPACITY; i++) { 203 box.add(b[i]); 204 assertTrue("Box does not contain a Ball that is supposed to be inside!", 205 box.contains(b[i])); 206 for (int j=i+1; j<BOX_CAPACITY; j++) { 207 assertFalse("Box seems to contain a Ball that is not inside!", 208 box.contains(b[j])); 209 } 210 } 211 } 212 213 /** 214 * Test to check that iterator() is implemented correctly. 215 */ 216 @Test 217 public void testIterator() { 218 Set<Ball> allBalls = new HashSet<Ball>(); 219 Set<Ball> seenBalls = new HashSet<Ball>(); 220 box.clear(); 221 for (Ball aBall : b) { 222 box.add(aBall); 223 allBalls.add(aBall); 224 } 225 int i = 0; 226 for (Ball aBall : box) { 227 assertTrue("Iterator returned a ball that isn't in the container: " + aBall, 228 allBalls.contains(aBall)); 229 assertFalse("Iterator returned the same ball twice: " + aBall, 230 seenBalls.contains(aBall)); 231 seenBalls.add(aBall); 232 i++; 233 } 234 assertEquals("BallContainer iterator did not return enough items!", 235 b.length-1, i); 236 } 237 }