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 }