import org.testng.annotations.DataProvider ;
import org.testng.annotations.Test ;
import static org.testng.Assert.assertEquals ;

public class Factorial_J_Test {
  @DataProvider ( name = "theData" ) public Object[][] createData ( ) {
    return new Object[][] {
      { 0 , 1 } ,
      { 1 , 1 } , 
      { 2 , 2 } ,
      { 3 , 6 } ,
      { 4 , 24 } ,
      { 5 , 120 } ,
      { 6 , 720 } ,
      { 7 , 5040 } ,
      { 8 , 40320 } ,
      { 9 , 362880 } ,
      { 10 , 3628800 } ,
      { 11 , 39916800 } ,
      { 12 , 479001600 } ,
      { 13 , 6227020800L } ,
      { 14 , 87178291200L } ,
      { 20 , 2432902008176640000L } ,
      //{ 30 , 265252859812191058636308480000000 } ,
      //{ 40 , 815915283247897734345611269596115894272000000000 }
    } ;
  }
  @Test ( dataProvider = "theData" ) public void correctIterative ( final long n , final long expected ) {
    assertEquals ( expected , Factorial_J.iterative ( n ) ) ;
  }
  @Test ( dataProvider = "theData" ) public void correctRecursive ( final long n , final long expected ) {
    assertEquals ( expected , Factorial_J.recursive ( n ) ) ;
  }
  @Test ( dataProvider = "theData" ) public void correctTailRecursive ( final long n , final long expected ) {
    assertEquals ( expected , Factorial_J.tailRecursive ( n ) ) ;
  }
  @DataProvider ( name = "theNegative" ) public Object[][] createNegative ( ) {
    return new Object[][] { { -20 } , { -15 } , { -10 } , { -5 } , { -2 } , { -1 } } ;
  }
  @Test ( dataProvider = "theNegative" , expectedExceptions = { FactorialIllegalArgumentException.class } )
  public void negativeIterative ( final long n ) { Factorial_J.iterative ( n ) ; }
  @Test ( dataProvider = "theNegative" , expectedExceptions = { FactorialIllegalArgumentException.class } )
  public void negativeRecursive ( final long n ) { Factorial_J.recursive ( n ) ; }
  @Test ( dataProvider = "theNegative" , expectedExceptions = { FactorialIllegalArgumentException.class } )
  public void negativeTailRecursive ( final long n ) { Factorial_J.tailRecursive ( n ) ; }
  @Test public void iterativeEnormousSucceeds ( ) { Factorial_J.iterative ( 10000 ) ; }
  @Test ( expectedExceptions = { StackOverflowError.class } ) public void recursiveEnormousFails ( ) { Factorial_J.recursive ( 9000 ) ; }
  @Test ( expectedExceptions = { StackOverflowError.class } ) public void tailRecursiveEnormousFails ( ) { Factorial_J.tailRecursive ( 9000 ) ; }
}

