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    }