require 'spec_helper'
require 'fileutils'

# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests
describe IcecastConfigWriter do

  let(:worker) { IcecastConfigWriter.new }

  describe "validate" do

    it "no manifest" do
      expect { worker.validate }.to raise_error("icecast_server_id not spceified")
    end

    it "no files specified" do
      worker.icecast_server_id = 'something'
      expect { worker.validate }.to raise_error("queue routing mismatch error. requested icecast_server_id: #{worker.icecast_server_id}, configured icecast_server_id: #{APP_CONFIG.icecast_server_id}")
    end

    it "succeeds" do
      worker.icecast_server_id = APP_CONFIG.icecast_server_id
      worker.validate
    end
  end

  describe "reload" do
    it "works with successful command" do
      IcecastConfigWriter.any_instance.stub(:execute).and_return(0)
      worker.reload
    end

    it "raise exception when command fails" do
      IcecastConfigWriter.any_instance.stub(:execute).and_return(1)
      expect { worker.reload }.to raise_error
    end
  end

  describe "integration" do

    let(:server) {FactoryGirl.create(:icecast_server_minimal, server_id: APP_CONFIG.icecast_server_id)}

    describe "simulated" do

      describe "perform" do
        # this case does not talk to redis, does not run a real reload command.
        # but it does talk to the database and verifies all the other logic
        it "success" do
          pending 'icecast needs love'
          # return success code from reload command
          IcecastConfigWriter.any_instance.stub(:execute).and_return(0)

          server.location = 'hello'
          server.save!
          server.config_changed.should == 1
          IcecastConfigWriter.perform(server.server_id)
          server.reload
          server.config_changed.should == 0
        end

        it "errored" do
          # return error code from reload command, which will cause the job to blow up
          IcecastConfigWriter.any_instance.stub(:execute).and_return(1)

          server.save!
          server.config_changed.should == 1
          expect { IcecastConfigWriter.perform(server.server_id) }.to raise_error
          server.reload
          server.config_changed.should == 1
        end
      end

      describe "with resque-spec" do

        before(:each) do
          ResqueSpec.reset!
        end

        it "should have been enqueued because the config changed" do
          pending 'icecast needs love'
          server.touch
          ResqueSpec.reset!
          server.save!
          # the act of just touching the IcecastServer puts a message on the queue, because config_changed = true
          IcecastConfigWriter.should have_queue_size_of(1)
        end


        it "should not have been enqueued if routed to a different server_id" do
          pending 'icecast needs love'
          new_server = FactoryGirl.create(:icecast_server_minimal, server_id: APP_CONFIG.icecast_server_id)
          with_resque do
            new_server.save!
          end

          # nobody was around to take it from the queue
          IcecastConfigWriter.should have_queue_size_of(1)
        end

        it "should actually run the job" do
          pending 'icecast needs love'
          IcecastConfigWriter.any_instance.stub(:execute).and_return(0)

          with_resque do
            server.save!
            server.config_changed.should == 1
          end

          IcecastConfigWriter.should have_queue_size_of(0)

          server.reload
          server.config_changed.should == 0
        end

        it "bails out with no error if no config change present" do
          pending 'icecast needs love'
          IcecastConfigWriter.any_instance.stub(:execute).and_return(0)

          with_resque do
            server.save!
          end

          server.reload
          server.config_changed.should == 0

          with_resque do
            IcecastConfigWriter.enqueue(server.server_id)
          end

          server.reload
          server.config_changed.should == 0
        end

        describe "queue_jobs_needing_retry" do

          it "finds an unchecked server" do
            pending "failing on build server"

            server.touch
            set_updated_at(server, Time.now.ago(APP_CONFIG.icecast_max_missing_check + 1))

            # should enqueue 1 job
            IcecastConfigWriter.queue_jobs_needing_retry

            IcecastConfigWriter.should have_queue_size_of(1)
          end

          it "does not find a recently checked server" do
            pending "failing on build server"

            # should enqueue 1 job
            IcecastConfigWriter.queue_jobs_needing_retry

            IcecastConfigWriter.should have_queue_size_of(0)
          end
        end
      end
    end
  end
end
