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