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