001 /**
002 * This is part of HW2: Environment Setup and Java Introduction for CSE 331.
003 */
004 package hw2.test;
005 import hw2.*;
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 import 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 hw2.Ball
032 * @see hw2.BallContainer
033 * @see hw2.Box
034 */
035 public 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 }