#! /usr/bin/env ruby

require 'test/unit'
require 'factorial'

class Factorial_Test < Test::Unit::TestCase

    @@data = [
        [ 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 , 6227020800 ] ,
        [ 14 , 87178291200 ] ,
        [ 20 , 2432902008176640000 ] ,
        [ 30 , 265252859812191058636308480000000 ] ,
        [ 40 , 815915283247897734345611269596115894272000000000 ]
        ]

  def fromArrayTest ( function ) @@data.each { | datum | assert_equal( function.call( datum[0] ) , datum[1] ) } end

  def test_fromArrayIterative ( ) fromArrayTest( Factorial.method( :iterative ) ) end
  def test_fromArrayRecursive ( ) fromArrayTest( Factorial.method( :recursive ) ) end
  def test_fromArrayTailRecursive ( ) fromArrayTest( Factorial.method( :tailRecursive ) ) end

  def negativeTest ( function ) ( -20 .. -1 ).each { | i | assert_raise( ArgumentError ) { function.call( i ) } } end  

  def test_negativeIterative ( ) negativeTest( Factorial.method( :iterative ) ) end
  def test_negativeRecursive ( ) negativeTest( Factorial.method( :recursive ) ) end
  def test_negativeTailRecursive ( ) negativeTest( Factorial.method( :tailRecursive ) ) end

  def floatingPointTest ( function ) ( -12 .. 2 ).each { | i | assert_raise( ArgumentError ) { function.call( i + 0.5 ) } } end

  def test_floatingPointIterative ( ) floatingPointTest( Factorial.method( :iterative ) ) end
  def test_floatingPointRecursive ( ) floatingPointTest( Factorial.method( :recursive ) ) end
  def test_floatingPointTailRecursive ( ) floatingPointTest( Factorial.method( :tailRecursive ) ) end

  def testIterativeEnormousSucceeds ( ) Factorial.iterative( 4000 ) end
  def testRecursiveStackFail ( ) assert_raise( SystemStackError ) { Factorial.recursive( 2700 ) } end
  def testTailRecursiveStackFail ( ) assert_raise( SystemStackError ) { Factorial.tailRecursive( 2700 ) } end

end 

