
require File.expand_path("../../test_helper", __FILE__)

class Stalking::ConsumerTest < Minitest::Test
  def setup
    Beanstalk::Pool.clear!
  end

  def test_before
    Stalking::Producer.new.enqueue "test", "a" => "b"

    res = nil

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        before do |name, args|
          res = [name, args]

          raise Exception
        end

        job "test" do |args|
          # Nothing
        end
      end
    end

    assert_equal ["test", { "a" => "b" }], res
  end

  def test_after
    Stalking::Producer.new.enqueue "test", "a" => "b"

    res = nil

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        after do |name, args|
          res = [name, args]

          raise Exception
        end

        job "test" do |args|
          # Nothing
        end
      end
    end

    assert_equal ["test", { "a" => "b" }], res
  end

  def test_error
    Stalking::Producer.new.enqueue "test", "a" => "b"

    res = nil

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        error do |e, name, args|
          res = [e.message, name, args]

          raise Exception
        end

        job "test" do |args|
          raise "An error has occurred"
        end
      end
    end

    assert_equal ["An error has occurred", "test", { "a" => "b" }], res
  end

  def test_job
    Stalking::Producer.new.enqueue "test", "a" => "b"

    res = nil

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        job "test" do |args|
          res = ["test", args]

          raise Exception
        end
      end
    end

    assert_equal ["test", { "a" => "b" }], res
  end

  def test_watch
    # Already tested
  end

  def test_work
    Stalking::Producer.new.enqueue "test1", "a" => "b"
    Stalking::Producer.new.enqueue "test2", "a" => "b"
    Stalking::Producer.new.enqueue "test3", "a" => "b"

    res = []

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        job "test1" do |args|
          res.push "test1"
        end

        job "test2" do |args|
          res.push "test2"
        end

        job "test3" do |args|
          res.push "test3"

          raise Exception
        end
      end
    end

    assert_equal ["test1", "test2", "test3"], res
  end

  def test_job_not_deleted
    Stalking::Producer.new.enqueue "test", "a" => "b"

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        job "test" do |args|
          raise Exception
        end
      end
    end

    res = nil

    exception = assert_raises(Exception) do
      Stalking::Consumer.new do
        job "test" do |args|
          res = ["test", args]

          raise Exception
        end
      end
    end

    assert_equal ["test", {"a" => "b" }], res
  end

  def test_job_deleted
    Stalking::Producer.new.enqueue "test", "a" => "b"

    res = nil

    exception = assert_raises(NoMethodError) do
      Stalking::Consumer.new do
        job "test" do |args|
          res = ["test", args]
        end
      end
    end

    assert_equal ["test", { "a" => "b" }], res
    assert_equal "undefined method `body' for nil:NilClass", exception.message
  end

  def test_reconnect
    Stalking::Producer.new.enqueue "test", "a" => "b"

    logger = TestLogger.new

    res = []

    exception = assert_raises(Exception) do
      Stalking::Consumer.new :logger => logger do
        job "test" do |args|
          if res.empty?
            res.push ["down"]

            # Simulate a temporary beanstalk connection error.

            Beanstalk::Pool.new(["localhost:11300"]).disconnect!
          else
            res.push ["test", args]

            raise Exception
          end
        end
      end
    end

    assert_equal [["down"], ["test", { "a" => "b" }]], res

    assert_equal ["Beanstalk::NotConnected"], logger.entries.collect(&:to_s)
  end

  def test_logger
    # Already tested
  end

  def test_termination
    assert_nothing_raised do
      Timeout::timeout 3 do
        consumer = Stalking::Consumer.new

        consumer.send :looping do
          consumer.send :lock do # Don't invoke exit
            Process.kill "USR2", Process.pid
          end
        end
      end
    end
  end
end

