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.Set;
008import java.util.HashSet;
009
010import org.junit.Test;
011import org.junit.BeforeClass;
012import static org.junit.Assert.*;
013import static org.hamcrest.Matchers.greaterThan;
014
015/**
016 * BallContainerTest is a glassbox test of the BallContainer class.
017 *
018 * Recall that the BallContainer is a container for Balls. However, you can only
019 * put a Ball into a BallContainer once. After you put the Ball into the BallContainer,
020 * further attempts to do so will fail, since the Ball is already in
021 * the BallContainer! Similarly, you cannot expect to remove a Ball from a BallContainer
022 * if it is not inside the BallContainer.
023 *
024 * @see hw3.Ball
025 * @see hw3.BallContainer
026 */
027public class BallContainerTest {
028
029    private static BallContainer ballcontainer = null;
030    private static Ball[] b = null;
031
032    private static final int NUM_BALLS_TO_TEST = 3;
033    private static final double BALL_UNIT_VOLUME = 20.0;
034    private static final double JUNIT_DOUBLE_DELTA = 0.0001;
035
036    @BeforeClass
037    public static void setupForTests() throws Exception {
038        assertThat("Test case error, you must test at least 1 Ball!!", NUM_BALLS_TO_TEST, greaterThan(0));
039        ballcontainer = new BallContainer();
040
041        // Let's create the balls we need.
042        b = new Ball[NUM_BALLS_TO_TEST];
043        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
044            b[i] = new Ball((i+1)*BALL_UNIT_VOLUME);
045        }
046    }
047
048
049    /** Test to check that BallContainer.add(Ball) is implemented correctly */
050    @Test
051    public void testAdd() {
052        double containerVolume;
053        ballcontainer.clear();
054        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
055            assertTrue("BallContainer.add(Ball) failed to add a new Ball!", ballcontainer.add(b[i]));
056            containerVolume = ballcontainer.getVolume();
057            assertFalse("BallContainer.add(Ball) seems to allow the same Ball to be added twice!", ballcontainer.add(b[i]));
058            assertEquals("BallContainer's volume has changed, but its contents have not!",
059                         containerVolume, ballcontainer.getVolume(),
060                         JUNIT_DOUBLE_DELTA);
061            assertTrue("BallContainer does not contain a ball after it is supposed to have been added!",
062                       ballcontainer.contains(b[i]));
063        }
064    }
065
066    /** Test to check that BallContainer.remove(Ball) is implemented correctly */
067    @Test
068    public void testRemove() {
069        ballcontainer.clear();
070        double containerVolume;
071        assertFalse("BallContainer.remove(Ball) should fail because ballcontainer is empty, but it didn't!", ballcontainer.remove(b[0]));
072        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
073            ballcontainer.clear();
074            for (int j=0; j<i; j++) {
075                ballcontainer.add(b[j]);
076            }
077            for (int j=0; j<i; j++) {
078                assertTrue("BallContainer.remove(Ball) failed to remove a Ball that is supposed to be inside",
079                           ballcontainer.remove(b[j]));
080                containerVolume = ballcontainer.getVolume();
081                assertFalse("BallContainer still contains a ball after it is supposed to have been removed!",
082                            ballcontainer.contains(b[j]));
083                assertEquals("BallContainer's volume has changed, but its contents have not!",
084                             containerVolume, ballcontainer.getVolume(),
085                             JUNIT_DOUBLE_DELTA);
086            }
087            for (int j=i; j<NUM_BALLS_TO_TEST; j++) {
088                assertFalse("BallContainer.remove(Ball) did not fail for a Ball that is not inside", ballcontainer.remove(b[j]));
089            }
090        }
091    }
092
093    /**
094     * Test to check that BallContainer.iterator() is implemented
095     * correctly.
096     */
097    @Test
098    public void testIterator() {
099        Set<Ball> allBalls = new HashSet<Ball>();
100        Set<Ball> seenBalls = new HashSet<Ball>();
101        ballcontainer.clear();
102        assertEquals("BallContainer is not empty after being cleared!",
103                     0, ballcontainer.size());
104        for (Ball aBall: b) {
105            ballcontainer.add(aBall);
106            allBalls.add(aBall);
107        }
108        int i=0;
109        for (Ball aBall: ballcontainer) {
110            assertTrue("Iterator returned a ball that isn't in the container: " + aBall,
111                       allBalls.contains(aBall));
112            assertFalse("Iterator returned the same ball twice: " + aBall,
113                        seenBalls.contains(aBall));
114            seenBalls.add(aBall);
115            i++;
116        }
117        assertEquals("BallContainer iterator did not return enough items!",
118                     i, b.length);
119    }
120
121    /**
122     * Test that BallContainer.clear() is implemented correctly.
123     */
124    @Test
125    public void testClear() {
126        ballcontainer.clear();
127        assertEquals("BallContainer is not empty after being cleared!",
128                     0, ballcontainer.size());
129        ballcontainer.add(b[0]);
130        ballcontainer.clear();
131        assertEquals("BallContainer is not empty after being cleared!",
132                     0, ballcontainer.size());
133    }
134
135    /** Test that we can put a Ball into a BallContainer */
136    @Test
137    public void testVolume() {
138        ballcontainer.clear();
139        assertEquals("Volume of empty BallContainer is not zero!",
140                     0, ballcontainer.getVolume(), JUNIT_DOUBLE_DELTA);
141        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
142            ballcontainer.add(b[i]);
143            assertEquals("Volume of BallContainer with "+(i+1)+" ball(s)",
144                         (i+1)*(i+2)*BALL_UNIT_VOLUME/2,
145                         ballcontainer.getVolume(),
146                         JUNIT_DOUBLE_DELTA);
147        }
148
149    }
150
151    /** Test that size() returns the correct number. */
152    @Test
153    public void testSize() {
154        ballcontainer.clear();
155        assertEquals("size() of empty BallContainer is not zero!",
156                     0, ballcontainer.size());
157        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
158            ballcontainer.add(b[i]);
159            assertEquals("size() of BallContainer with "+(i+1)+" ball(s)",
160                         i+1, ballcontainer.size());
161        }
162    }
163
164    /** Test that size() returns the correct number. */
165    @Test
166    public void testContains() {
167        ballcontainer.clear();
168        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
169            assertFalse("Empty BallContainer seems to contain a ball!", ballcontainer.contains(b[i]));
170        }
171        for (int i=0; i<NUM_BALLS_TO_TEST; i++) {
172            ballcontainer.add(b[i]);
173            assertTrue("BallContainer does not contain a Ball that is supposed to be inside!", ballcontainer.contains(b[i]));
174            for (int j=i+1; j<NUM_BALLS_TO_TEST; j++) {
175                assertFalse("BallContainer seems to contain a Ball that is not inside!", ballcontainer.contains(b[j]));
176            }
177        }
178    }
179
180    /** Test that clear removes all balls. **/
181    @Test
182    public void testVolumeAfterClear() {
183        ballcontainer.add(b[0]);
184        ballcontainer.clear();
185        assertEquals("The volume of BallContainer after being cleared is not reset to 0!",
186                     0, ballcontainer.getVolume(), JUNIT_DOUBLE_DELTA);
187    }
188
189}