require 'runit/testcase'
require 'runit/cui/testrunner'
require 'runit/testresult'

class DummyError < StandardError
end

class DummyResult
  attr_reader :testcase
  attr_reader :start_called
  attr_reader :end_called
  def initialize
    @start_called = false
    @end_called = false
    @testcase = nil
  end
  def start_test(test)
    @start_called = true
    @testcase = test
  end
  def end_test(test)
    @end_called = true
    @testcase = test
  end
end

class DummyTestCase < RUNIT::TestCase
  attr_reader :status 
  attr_reader :dummy_called
  attr_reader :dummy2_called
  def initialize(*arg)
    super(*arg)
    @status = 0
    @dummy_called = false
    @dummy2_called = false
  end
  def setup
    @status = 1 if @status == 0
  end
  def test_dummy
    @status = 2 if @status == 1
    @dummy_called = true
  end
  def test_dummy2
    @status = 2 if @status == 1
    @dummy2_called = true
    raise DummyError
  end
  def teardown
    @status = 3 if @status == 2
  end
end

class DummyTestWithTeardownError < RUNIT::TestCase
  def test_foo
    assert(false)
  end
  def test_bar
    assert(true)
  end
  def teardown
    raise StandardError
  end
end

class TestTestCase < RUNIT::TestCase
  def setup
    @test1 = DummyTestCase.new('test_dummy')
    @test2 = DummyTestCase.new('test_dummy2', 'TestCase')
  end

  def test_name
    assert_equal(@test1.name, 'DummyTestCase#test_dummy')
    assert_equal(@test2.name, 'TestCase#test_dummy2')
  end

  def test_run_bare
    assert_equal(0, @test1.status)
    assert(!@test1.dummy_called)
    @test1.run_bare
    assert_equal(3, @test1.status)
    assert(@test1.dummy_called)

    assert(!@test2.dummy2_called)
    assert_equal(0, @test2.status)
    begin
      @test2.run_bare
    rescue DummyError
    end
    assert(@test2.dummy2_called)
    assert_equal(3, @test2.status)
  end

  def test_run
    result = DummyResult.new
    assert(!result.start_called)
    assert(!result.end_called)
    assert_nil(result.testcase)
    @test1.run(result)
    assert(result.start_called)
    assert(result.end_called)
    assert_same(@test1, result.testcase)
  end

  def test_s_suite
    suite = DummyTestCase.suite
    assert_instance_of(RUNIT::TestSuite, suite)
    assert_equal(2, suite.count_test_cases)
  end

  def test_teardown_err
    suite = DummyTestWithTeardownError.suite
    result = RUNIT::TestResult.new
    suite.run(result)
    assert_equal(2, result.error_size)
    assert_equal(1, result.failure_size)
    result.errors.each do |e|
      assert_match(/`teardown'.+StandardError/, e.to_s)
    end
    result.failures.each do |f|
      assert_match(/`test_foo'.+AssertionFailedError/, f.to_s)
    end
  end
end

if $0 == __FILE__
  RUNIT::CUI::TestRunner.run(TestTestCase.suite)
end

