#include <check.h>

#include "factorial.h"

unsigned long long data[][2] = {
  { 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 , 6227020800ull } ,
  { 14 , 87178291200ull } ,
  { 20 , 2432902008176640000ull } ,
  //{ 30 , 265252859812191058636308480000000ull } ,
  //{ 40 , 815915283247897734345611269596115894272000000000ull }
} ;

int dataCount = 16 ;

#define CORRECT_TEST( function , message )  { int i ; for ( i = 0 ; i < dataCount ; ++i ) { fail_unless ( data[i][1] == function ( data[i][0] ) , message ) ; } }

START_TEST ( correctIterative )
{
  CORRECT_TEST ( factorial_iterative , "Iterative" ) ;
}
END_TEST

START_TEST ( correctRecursive )
{
  CORRECT_TEST ( factorial_recursive , "Recursive" ) ;
}
END_TEST

START_TEST ( correctTailRecursive )
{
  CORRECT_TEST ( factorial_tailRecursive , "Tail Recursive" ) ;
}
END_TEST

Suite * testSuite ( ) {
  Suite * suite = suite_create ( "Factorial" ) ;
  TCase * tests = tcase_create ( "Tests" ) ;
  tcase_add_test ( tests , correctIterative ) ;
  tcase_add_test ( tests , correctRecursive ) ;
  tcase_add_test ( tests , correctTailRecursive ) ;
  suite_add_tcase ( suite , tests ) ;
  return suite ;
}

int main ( void ) {
  int numberFailed ;
  Suite * suite = testSuite ( ) ;
  SRunner * runner = srunner_create ( suite ) ;
  srunner_run_all ( runner , CK_NORMAL ) ;
  numberFailed = srunner_ntests_failed ( runner ) ;
  srunner_free ( runner ) ;
  return numberFailed ;
}

