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