import java.io.*;
import junit.framework.TestCase;
public class NumberInfoTester extends TestCase {
  
  /**
   * Create files needed for testing.
   */
  public void setUp() throws IOException {
    PrintStream ps=
      new PrintStream(new FileOutputStream("emptyThree.txt"));
    ps.print("");
    ps.close();
    ps= new PrintStream(new FileOutputStream("three.txt"));
    ps.println("3");
    ps.close();
    ps= new PrintStream(new FileOutputStream("five.txt"));
    ps.println("5");
    ps.close();
    ps= new PrintStream(new FileOutputStream("six.txt"));
    ps.println("1\n3\n5\n7\n-9\n11\n12");
    ps.close();
    ps= new PrintStream(new FileOutputStream("singleDouble.txt"));
    ps.println("3.14159");
    ps.close();
    ps= new PrintStream(new FileOutputStream("twoDoubles.txt"));
    ps.println("3.141592653589\n-2.7182818284590");
    ps.close();
    ps= new PrintStream(new FileOutputStream("multipleDouble.txt"));
    ps.println("-3.141592653589\n-2.7182818284590");
    ps.println("1.4142135623730951\n-1.618033988749895");
    ps.println("0.6180339887498949\n2.6457513110645907");
    ps.close();
  }
  
  /**
   * Check that the sum of no numbers is zero.
   */
  public void testGetThreeSumEmpty() throws IOException {
    assertEquals("Sum of multiples of 3 in empty file is zero.",
                0, NumberInfo.getThreeSum("emptyThree.txt"));
  }
  
  /**
   * Check that the sum of a single 3 is 3.
   */
  public void testGetThreeSumThree() throws IOException {
    assertEquals("Sum of one 3 is 3.",
                 3, NumberInfo.getThreeSum("three.txt"));
  }
  
  /**
   * Check that the sum of a single non-three is 0.
   */
  public void testGetThreeSumFive() throws IOException {
    assertEquals("Sum of one non-three is zero.",
                 0, NumberInfo.getThreeSum("five.txt"));
  }
  
  /**
   * Check that a sum of mixed multiples and non-multiples
   * of 3 has expected result.
   */
  public void testGetThreeSumMixed() throws IOException {
    assertEquals("Sum of 1,3,5,7,-9,11,12 is 6.",
                 6, NumberInfo.getThreeSum("six.txt"));
  }
  
  /**
   * Check that the sum of multiples of three in a file, minus
   * the sum of non-multiples of three is 0 if the file is 
   * empty.
   */
  public void testGetThreeSumDifferenceEmpty() throws IOException {
    assertEquals("0-0 is 0.",
                 0, (double)NumberInfo.getThreeSumDifference("emptyThree.txt"),
                 0.000000001);
  }
  
  /**
   * Check that the sum of the multiples of three minus the sum
   * of the non-multiples of 3 is 3 if a file contains only 3.
   */
  public void testGetThreeSumDifferenceThree() throws IOException {
    assertEquals("3-0 is 3.",
                 3, (double)NumberInfo.getThreeSumDifference("three.txt"),
                 0.000000001);
  }
  
  /**
   * Check the sum of multiples of three minus the sum of non-multiples of
   * three is -5 if a file contains only 5.
   */
  public void testGetThreesumDifferenceFive() throws IOException {
    assertEquals("0-5 is -5.",
                 -5, (double)NumberInfo.getThreeSumDifference("five.txt"),
                 0.000000001);
  }
  
  /**
   * Check the sum of multiples of three minus the sum of non-multiples of
   * three is the expected result.
   */
  public void testGetThreeSumDifferenceMixed() throws IOException {
    assertEquals("Difference of 1,3,5,7,-9,11,12 is -18.",
                 -18, (double)NumberInfo.getThreeSumDifference("six.txt"),
                 0.000000001);
  }
  
  /**
   * Check that an empty list does not have more than half as many
   * multiples of 3 as non-multiples of 3.
   */
  public void testHasManyThreeProductsEmpty() throws IOException {
    assertFalse("Empty list doesn't have more than 1/3 3 multiples.",
               NumberInfo.hasManyThreeProducts("emptyThree.txt"));
  }
  
  /**
   * Check that a list with a single 3 does have more than half as many
   * multiples of 3 as non-multiples of 3.
   */
  public void testHasManyThreeProductsThree() throws IOException {
    assertTrue("One 3 is more than half of zero non-multiples.",
               NumberInfo.hasManyThreeProducts("three.txt"));
  }
  
  /**
   * Check that a list with a single 5 does not have more than half
   * as many multiples of 3 as non-multiples of 3.
   */
  public void testHasManyThreeProductsFive() throws IOException {
    assertFalse("One non-multiple is more than twice zero multiples.",
                NumberInfo.hasManyThreeProducts("five.txt"));
  }
  
  /**
   * Check that a list with 3 multiples of 3 and 4 non-multiples of 3
   * reports that there are more than half as many multiples of 3
   * as there are non-multiples.
   */
  public void testHasManyThreeProductsMixed() throws IOException {
    assertTrue("More than half as many 3-multiples as non-multiples.",
                NumberInfo.hasManyThreeProducts("six.txt"));
  }
  
  /**
   * Check that a list with 1 double returns the fractional part of that
   * number as the nearest to zero.
   */
  public void testGetClosestFractionSingle() throws IOException {
    assertEquals("Single number has closest fractional part.",
                 3.14159, NumberInfo.getClosestFraction("singleDouble.txt"),
                 0.00000000001);
  }
  
  /**
   * Check that the smallest is not necessarily the negative value.
   */
  public void testGetClosestFractionTwo() throws IOException {
    assertEquals("Positive number with smaller fractional part.",
                 3.141592653589, 
                 NumberInfo.getClosestFraction("twoDoubles.txt"),
                 0.00000000001);
  }
  
  /**
   * Check that a list with several doubles has the appropriate one
   * with fractional part nearest zero.
   */
  public void testGetClosestFractionSeveral() throws IOException{
    assertEquals("-3.141592653589 is closest.",
                 -3.141592653589, 
                 NumberInfo.getClosestFraction("multipleDouble.txt"),
                 0.00000000001);
  }

}