package cse1030.games; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeSet; import org.junit.Test; public class BoggleDieTest { private static final int N_LETTERS = 6; private static final int TRIALS = 10000; @Test public void testValidString() { for (int i = 0; i < TRIALS; i++) { String s = BoggleDieTest.validLetters(N_LETTERS); try { BoggleDie d = new BoggleDie(s); d.roll(); } catch (IllegalArgumentException ex) { fail("Did not expect an IllegalArgumentException for valid string " + s); } } } @Test public void testStringTooShort() { for (int i = 0; i < TRIALS; i++) { try { int n = BoggleDieTest.rng.nextInt(N_LETTERS); String s = BoggleDieTest.validLetters(n); BoggleDie d = new BoggleDie(s); fail("Expected an IllegalArgumentException for short string " + s); } catch (IllegalArgumentException ex) { } } } @Test public void testStringTooLong() { for (int i = 0; i < TRIALS; i++) { try { int n = 1 + BoggleDieTest.rng.nextInt(10); String s = BoggleDieTest.validLetters(N_LETTERS + n); BoggleDie d = new BoggleDie(s); fail("Expected an IllegalArgumentException for long string " + s); } catch (IllegalArgumentException ex) { } } } @Test public void testStringNonEnglish() { try { String s = "ABC@Ef"; BoggleDie d = new BoggleDie(s); fail("Expected an IllegalArgumentException to be thrown for string " + s); } catch (IllegalArgumentException ex) { } try { String s = "a[BCEf"; BoggleDie d = new BoggleDie(s); fail("Expected an IllegalArgumentException to be thrown for string " + s); } catch (IllegalArgumentException ex) { } try { String s = "ABCdE{"; BoggleDie d = new BoggleDie(s); fail("Expected an IllegalArgumentException to be thrown for string " + s); } catch (IllegalArgumentException ex) { } } @Test public void testRoll() { String s = "PQRSTU"; BoggleDie d = new BoggleDie(s); Map count = new HashMap(); count.put("P", 0); count.put("QU", 0); count.put("R", 0); count.put("S", 0); count.put("T", 0); count.put("U", 0); final int ROLLS = 1000000; for (int i = 0; i < ROLLS; i++) { d.roll(); String v = d.getValue(); Integer c = count.get(v); if (c == null) { fail(v + " is not a letter on the die P, QU, R, S, T, U"); } else { count.put(v, c + 1); } } // compute chi-squared test statistic final double expected = (double) ROLLS / N_LETTERS; double chisq = 0.; for (Integer i : count.values()) { chisq += (i - expected) * (i - expected) / expected; } // p = 0.01 for chi-squared distribution with 5 degrees of freedom final double threshold = 15.0863; assertTrue("die is statistically unfair" + count, chisq < threshold); } @Test public void testGetValueMap() { for (int i = 0; i < TRIALS; i++) { String s = BoggleDieTest.validLetters(N_LETTERS); BoggleDie d = new BoggleDie(s); SortedMap m = d.getValueMap(); assertEquals("value map has incorrect keys", BoggleDieTest.values, m.keySet()); List faces = new ArrayList(m.values()); Collections.sort(faces); assertEquals("value map has incorrect faces", BoggleDieTest.stringToSortedList(s), faces); } } @Test public void testEqualsObject() { BoggleDie b = new BoggleDie("ZCYBCA"); BoggleDie d = new BoggleDie("ABCCYZ"); for (int i = 0; i < TRIALS; i++) { b.roll(); String s = b.getValue(); int count = 0; while (!s.equals(d.getValue())) { d.roll(); if (count > 100) { fail("die ABCCYZ never rolls " + s); } count++; } assertTrue("dice have the same value " + s + " and same letters but equals was false", b.equals(d)); } } private static final Random rng = new Random(System.nanoTime()); private static final List letters = initLetters(); private static final SortedSet values = initValues(); private static String validLetters(int n) { final int N = letters.size(); StringBuilder b = new StringBuilder(); for (int i = 0; i < n; i++) { int idx = BoggleDieTest.rng.nextInt(N); b.append(BoggleDieTest.letters.get(idx)); } return b.toString(); } private static List initLetters() { List t = new ArrayList(); for (int i = 'A'; i <= 'Z'; i++) { String s = Character.toString((char) i); t.add(s); } for (int i = 'a'; i <= 'z'; i++) { String s = Character.toString((char) i); t.add(s); } return t; } private static SortedSet initValues() { SortedSet t = new TreeSet(); for (int i = 1; i <= N_LETTERS; i++) { t.add(i); } return t; } private static List stringToSortedList(String s) { s = s.toUpperCase(); List t = new ArrayList(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == 'Q') { t.add("QU"); } else { t.add("" + c); } } Collections.sort(t); return t; } }