module Test::Unit::Fixture

def create_fixtures_runner(fixtures, options, &block)

def create_fixtures_runner(fixtures, options, &block)
  if fixtures.empty?
    block
  else
    last_fixture = fixtures.pop
    create_fixtures_runner(fixtures, options) do
      block_is_called = false
      run_fixture_callback(last_fixture, options) do
        block_is_called = true
        block.call
      end
      block.call unless block_is_called
    end
  end
end

def included(base)

def included(base)
  base.extend(ClassMethods)
  [:setup, :cleanup, :teardown].each do |type|
    observer = lambda do |test_case, _, _, value, callback|
      if value.nil?
        test_case.fixture[type].unregister(callback)
      else
        test_case.fixture[type].register(callback, value)
      end
    end
    base.register_attribute_observer(type, &observer)
  end
end

def run_cleanup

def run_cleanup
  run_fixture(:cleanup)
end

def run_fixture(type, options={}, &block)

def run_fixture(type, options={}, &block)
  fixtures = [
    self.class.fixture.before_callbacks(type),
    type,
    self.class.fixture.after_callbacks(type),
  ].flatten
  if block
    runner = create_fixtures_runner(fixtures, options, &block)
    runner.call
  else
    fixtures.each do |method_name|
      run_fixture_callback(method_name, options)
    end
  end
end

def run_fixture_callback(method_name, options, &block)

def run_fixture_callback(method_name, options, &block)
  return unless respond_to?(method_name, true)
  begin
    __send__(method_name, &block)
  rescue Exception
    raise unless options[:handle_exception]
    raise unless handle_exception($!)
  end
end

def run_setup(&block)

def run_setup(&block)
  run_fixture(:setup, &block)
end

def run_teardown

def run_teardown
  run_fixture(:teardown, :handle_exception => true)
end