#!/usr/bin/ruby -I./lib/ -I../lib/


require 'custodian/util/timespan'
require 'test/unit'



#
# Unit test for our time-span code.
#
class TestTimeSpanUtil < Test::Unit::TestCase

  #
  # Create the test suite environment: NOP.
  #
  def setup
  end

  #
  # Destroy the test suite environment: NOP.
  #
  def teardown
  end

  #
  #  Test the expansion of "obvious" hour-specifiers.
  #
  def test_to_hour

    for hour in 0..23
      assert_equal( hour, Custodian::Util::TimeSpan::to_hour(hour))
    end

    #
    #  Invalid hours will throw exceptions
    #
    assert_raise ArgumentError do
      result = Custodian::Util::TimeSpan.to_hour( 0.5 )
    end
    assert_raise ArgumentError do
      result = Custodian::Util::TimeSpan.to_hour( -1 )
    end
    assert_raise ArgumentError do
      result = Custodian::Util::TimeSpan.to_hour( 100 )
    end
    assert_raise ArgumentError do
      result = Custodian::Util::TimeSpan.to_hour( 24 )
    end
    assert_raise ArgumentError do
      result = Custodian::Util::TimeSpan.to_hour( 25 )
    end

    #
    #  Ensure AM times work well
    #
    for hour in 0..11
      assert_equal( hour, Custodian::Util::TimeSpan::to_hour( "#{hour}am"))
    end

    for hour in 0..11
      assert_equal( 12 +hour, Custodian::Util::TimeSpan::to_hour( "#{hour}pm"))
    end

  end


  #
  #
  #  Ensure we received errors if the start/end hours are under/over 24
  #
  def test_excessive_hours

    #
    #  Valid hours are 0-23, inclusive.  Test outside that range.
    #
    for i in  24..100
      assert_raise ArgumentError do
        result = Custodian::Util::TimeSpan.inside?( i, 2 )
      end

      assert_raise ArgumentError do
        result = Custodian::Util::TimeSpan.inside?( 1, i )
      end

      assert_raise ArgumentError do
        result = Custodian::Util::TimeSpan.inside?( 1, 2, i )
      end
    end

    #
    #  Now negative values.
    #
    for i in 1..50

      assert_raise ArgumentError do
        result = Custodian::Util::TimeSpan.inside?( 1, ( -1 * i ) )
      end

      assert_raise ArgumentError do
        result = Custodian::Util::TimeSpan.inside?( ( -1 * i ), 1 )
      end

      assert_raise ArgumentError do
        result = Custodian::Util::TimeSpan.inside?( 1, 1, ( -1 * i ) )
      end
    end

  end


  #
  #  Test simple cases where the period is positive.
  #
  def test_simple_cases
    # 8am-5pm
    assert(Custodian::Util::TimeSpan.inside?( "8am", "5am", 12 ))
    assert(Custodian::Util::TimeSpan.inside?( 8, 17, 12 ))

  end

  #
  #  Test cases which involve the wrap-around over midnight.
  #
  def test_midnight_cases

    # 9pm-2am
    assert(Custodian::Util::TimeSpan.inside?( "9pm", "2am", 22 ))
    assert(Custodian::Util::TimeSpan.inside?( "9pm", "2am", "10pm" ))
    assert(Custodian::Util::TimeSpan.inside?( 21, 2, 22 ))
    assert(Custodian::Util::TimeSpan.inside?( 21, 2, "10pm" ))

    # 10pm-3am
    assert(Custodian::Util::TimeSpan.inside?( "10pm", "3am", 22 ))
    assert(Custodian::Util::TimeSpan.inside?( 22, 3, 22 ))
    assert(Custodian::Util::TimeSpan.inside?( 22, 3, 22 ))
    assert(Custodian::Util::TimeSpan.inside?( 22, 3, "10pm" ))

    # 11pm-5am
    assert(Custodian::Util::TimeSpan.inside?( "11pm", "5am", 23 ))
    assert(Custodian::Util::TimeSpan.inside?( 23, 5, 23 ))
    assert(Custodian::Util::TimeSpan.inside?( "11pm", "5am", "11pm" ))

    # midnight-3am
    assert( Custodian::Util::TimeSpan.inside?( "0", "3am", 1 ))
    assert( Custodian::Util::TimeSpan.inside?( "0", "3am", "1am" ))
  end


  #
  #  The time-spans listed are inclusive.
  #
  #  Test the boundaries.
  #
  def test_inclusive

    open = "4pm"
    close = "6pm"

    # The hours + the middle should be inside
    assert( Custodian::Util::TimeSpan.inside?( open, close, 16 ) )
    assert( Custodian::Util::TimeSpan.inside?( open, close, "4pm" ) )

    assert( Custodian::Util::TimeSpan.inside?( open, close, 17 ) )
    assert( Custodian::Util::TimeSpan.inside?( open, close, "5pm" ) )

    assert( Custodian::Util::TimeSpan.inside?( open, close, 18 ) )
    assert( Custodian::Util::TimeSpan.inside?( open, close, "6pm" ) )


    #
    # The preceeding + successive hours shouldn't be.
    #
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, 15 ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, 19 ) )

    #
    # That is true for the string-versions too
    #
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, "3pm" ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, "7pm" ) )


    #
    # Random hours should be outside too.
    #
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, 3 ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, "3am" ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, 7 ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, "7am" ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, 9 ) )
    assert( ! Custodian::Util::TimeSpan.inside?( open, close, "9am" ) )

  end


  #
  #  Since the implementation of our test involves
  # iterating over the specified period then any 24-hour
  # period is the worst case.
  #
  #
  def test_worst()
    for i in 0..23
      assert( Custodian::Util::TimeSpan.inside?( 0, 23, i ) )
    end
  end

  #
  #  Test that we don't wrap-around unexpectedly.
  #
  #
  #  i.e. "between 00-00" is one hour, not 24.
  #
  def test_wrap_around

    for h in 00..23
      assert_equal( 1, Custodian::Util::TimeSpan::to_hours( h,h ).size() )
    end

    #
    #  But the time-period 00-23 is a full day
    #
    assert_equal( 24,
                  Custodian::Util::TimeSpan::to_hours( 0,23 ).size() )

  end


end