<commit_before># encoding: utf-8

require 'spec_helper'

module Adhearsion
  class CallController
    describe Dial do
      include CallControllerTestHelpers

      let(:to) { 'sip:<EMAIL>' }
      let(:other_call_id)   { new_uuid }
      let(:other_mock_call) { flexmock OutboundCall.new, :id => other_call_id }

      let(:second_to)               { 'sip:<EMAIL>' }
      let(:second_other_call_id)    { new_uuid }
      let(:second_other_mock_call)  { flexmock OutboundCall.new, :id => second_other_call_id }

      let(:mock_end)      { flexmock Punchblock::Event::End.new, :reason => :hangup }
      let(:mock_answered) { Punchblock::Event::Answered.new }

      let(:latch) { CountDownLatch.new 1 }

      describe "#dial" do
        before do
          other_mock_call
        end

        it "should dial the call to the correct endpoint and return a dial status object" do
          flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
          flexmock(other_mock_call).should_receive(:dial).with(to, :from => 'foo').once
          dial_thread = Thread.new do
            subject.dial(to, :from => 'foo').should be_a Dial::DialStatus
          end
          sleep 0.1
          other_mock_call << mock_end
          dial_thread.join.should be_true
        end

        it "should default the caller ID to that of the original call" do
          flexmock call, :from => 'sip:<EMAIL>'
          flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
          flexmock(other_mock_call).should_receive(:dial).with(to, :from => 'sip:<EMAIL>').once
          dial_thread = Thread.new do
            subject.dial to
          end
          sleep 0.1
          other_mock_call << mock_end
          dial_thread.join.should be_true
        end

        describe "without a block" do
          before do
            flexmock(other_mock_call).should_receive(:dial).once
            flexmock(other_mock_call).should_receive(:hangup).once
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
          end

          def dial_in_thread
            Thread.new do
              status = subject.dial to
              latch.countdown!
              status
            end
          end

          it "blocks the original controller until the new call ends" do
            dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_end

            latch.wait(1).should be_true
          end

          it "unblocks the original controller if the original call ends" do
            dial_in_thread

            latch.wait(1).should be_false

            call << mock_end

            latch.wait(1).should be_true
          end

          it "joins the new call to the existing one on answer" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)

            dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            other_mock_call << mock_end

            latch.wait(1).should be_true
          end

          it "hangs up the new call when the dial unblocks" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)

            dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            call << mock_end

            latch.wait(1).should be_true
          end

          context "when the call is rejected" do
            it "has an overall dial status of :no_answer" do
              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_end

              latch.wait(2).should be_true

              t.join
              status = t.value
              status.result.should be == :no_answer
            end
          end

          context "when the call is answered and joined" do
            it "has an overall dial status of :answer" do
              flexmock(other_mock_call).should_receive(:join).once.with(call)

              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_answered
              other_mock_call << mock_end

              latch.wait(1).should be_true

              t.join
              status = t.value
              status.result.should be == :answer
            end
          end
        end

        describe "with multiple third parties specified" do
          before do
            second_other_mock_call

            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call, second_other_mock_call

            flexmock(other_mock_call).should_receive(:dial).once
            flexmock(other_mock_call).should_receive(:hangup).once

            flexmock(second_other_mock_call).should_receive(:dial).once
            flexmock(second_other_mock_call).should_receive(:join).never
            flexmock(second_other_mock_call).should_receive(:hangup).once
          end

          def dial_in_thread
            Thread.new do
              status = subject.dial [to, second_to]
              latch.countdown!
              status
            end
          end

          it "dials all parties and joins the first one to answer, hanging up the rest" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)
            flexmock(second_other_mock_call).should_receive(:hangup).once

            t = dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            other_mock_call << mock_end

            latch.wait(1).should be_false

            second_other_mock_call << mock_end

            latch.wait(2).should be_true

            t.join
            status = t.value
            status.should be_a Dial::DialStatus
            status.should have(2).calls
            status.calls.each { |c| c.should be_a OutboundCall }
          end

          it "unblocks when the joined call unjoins, allowing it to proceed further" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)
            flexmock(second_other_mock_call).should_receive(:hangup).once

            t = dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            other_mock_call << Punchblock::Event::Unjoined.new(:other_call_id => call.id)

            latch.wait(1).should be_false

            second_other_mock_call << mock_end

            latch.wait(2).should be_true

            t.join
            status = t.value
            status.should be_a Dial::DialStatus
            status.should have(2).calls
            status.calls.each { |c| c.should be_a OutboundCall }
          end

          context "when all calls are rejected" do
            it "has an overall dial status of :no_answer" do
              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_end
              second_other_mock_call << mock_end

              latch.wait(2).should be_true

              t.join
              status = t.value
              status.result.should be == :no_answer
            end
          end

          context "when a call is answered and joined" do
            it "has an overall dial status of :answer" do
              flexmock(other_mock_call).should_receive(:join).once.with(call)
              flexmock(second_other_mock_call).should_receive(:hangup).once

              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_answered
              other_mock_call << mock_end

              second_other_mock_call << mock_end

              latch.wait(1).should be_true

              t.join
              status = t.value
              status.result.should be == :answer
            end
          end
        end

        describe "with a timeout specified" do
          let(:timeout) { 3 }

          it "should abort the dial after the specified timeout" do
            flexmock(other_mock_call).should_receive(:dial).once
            flexmock(other_mock_call).should_receive(:hangup).once
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call

            time = Time.now

            t = Thread.new do
              status = subject.dial to, :timeout => timeout
              latch.countdown!
              status
            end

            latch.wait
            time = Time.now - time
            time.to_i.should be == timeout
            t.join
            status = t.value
            status.result.should be == :timeout
          end
        end

        describe "multiple destinations and options overrides" do
          let(:global_options) do
            { 
              :from => 'foo',
              :timeout => 3000
            } 
          end

          let(:other_merged_options) do
            { 
              :from => 'foo',
              :timeout => 4000
            } 
          end

          let(:second_other_merged_options) do
            { 
              :from => 'foo',
              :timeout => 5000
            } 
          end

          it "with a single destination and an options hash, it dials the call with specified options" do
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
            flexmock(other_mock_call).should_receive(:dial).with(to, global_options).once
            dial_thread = Thread.new do
              subject.dial(to, global_options)
            end
            sleep 0.1
            other_mock_call << mock_end
          end

          it "with multiple destinations as an array and an options hash, it dials each call with specified options" do
            second_other_mock_call
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call, second_other_mock_call
            flexmock(other_mock_call).should_receive(:dial).with(to, global_options).once
            flexmock(second_other_mock_call).should_receive(:dial).with(second_to, global_options).once
            dial_thread = Thread.new do
              subject.dial([to, second_to], global_options)
            end
            sleep 0.1
            other_mock_call << mock_end
          end

          it "with multiple destinations as an hash, with overrides for each, and an options hash, it dials each call with specified options" do
            second_other_mock_call
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call, second_other_mock_call
            flexmock(other_mock_call).should_receive(:dial).with(to, other_merged_options).once
            flexmock(second_other_mock_call).should_receive(:dial).with(second_to, second_other_merged_options).once
            dial_thread = Thread.new do
              subject.dial({
                to => {:timeout => 4000}, 
                second_to => {:timeout => 5000}
              }, global_options)
            end
            sleep 0.1
            other_mock_call << mock_end
          end
        end

      	describe "with a block" do<commit_msg>[CS] Refactor dial option override specs for reduced duplication<commit_after># encoding: utf-8

require 'spec_helper'

module Adhearsion
  class CallController
    describe Dial do
      include CallControllerTestHelpers

      let(:to) { 'sip:<EMAIL>' }
      let(:other_call_id)   { new_uuid }
      let(:other_mock_call) { flexmock OutboundCall.new, :id => other_call_id }

      let(:second_to)               { 'sip:<EMAIL>' }
      let(:second_other_call_id)    { new_uuid }
      let(:second_other_mock_call)  { flexmock OutboundCall.new, :id => second_other_call_id }

      let(:mock_end)      { flexmock Punchblock::Event::End.new, :reason => :hangup }
      let(:mock_answered) { Punchblock::Event::Answered.new }

      let(:latch) { CountDownLatch.new 1 }

      describe "#dial" do
        before do
          other_mock_call
        end

        it "should dial the call to the correct endpoint and return a dial status object" do
          flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
          flexmock(other_mock_call).should_receive(:dial).with(to, :from => 'foo').once
          dial_thread = Thread.new do
            subject.dial(to, :from => 'foo').should be_a Dial::DialStatus
          end
          sleep 0.1
          other_mock_call << mock_end
          dial_thread.join.should be_true
        end

        it "should default the caller ID to that of the original call" do
          flexmock call, :from => 'sip:<EMAIL>'
          flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
          flexmock(other_mock_call).should_receive(:dial).with(to, :from => 'sip:<EMAIL>').once
          dial_thread = Thread.new do
            subject.dial to
          end
          sleep 0.1
          other_mock_call << mock_end
          dial_thread.join.should be_true
        end

        describe "without a block" do
          before do
            flexmock(other_mock_call).should_receive(:dial).once.with(to, options)
            flexmock(other_mock_call).should_receive(:hangup).once
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
          end

          let(:options) { { :foo => :bar } }

          def dial_in_thread
            Thread.new do
              status = subject.dial to, options
              latch.countdown!
              status
            end
          end

          it "blocks the original controller until the new call ends" do
            dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_end

            latch.wait(1).should be_true
          end

          it "unblocks the original controller if the original call ends" do
            dial_in_thread

            latch.wait(1).should be_false

            call << mock_end

            latch.wait(1).should be_true
          end

          it "joins the new call to the existing one on answer" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)

            dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            other_mock_call << mock_end

            latch.wait(1).should be_true
          end

          it "hangs up the new call when the dial unblocks" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)

            dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            call << mock_end

            latch.wait(1).should be_true
          end

          context "when the call is rejected" do
            it "has an overall dial status of :no_answer" do
              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_end

              latch.wait(2).should be_true

              t.join
              status = t.value
              status.result.should be == :no_answer
            end
          end

          context "when the call is answered and joined" do
            it "has an overall dial status of :answer" do
              flexmock(other_mock_call).should_receive(:join).once.with(call)

              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_answered
              other_mock_call << mock_end

              latch.wait(1).should be_true

              t.join
              status = t.value
              status.result.should be == :answer
            end
          end
        end

        describe "with multiple third parties specified" do
          let(:options) { {} }
          let(:other_options) { options }
          let(:second_other_options) { options }

          before do
            second_other_mock_call

            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call, second_other_mock_call

            flexmock(other_mock_call).should_receive(:dial).once.with(to, other_options)
            flexmock(other_mock_call).should_receive(:hangup).once

            flexmock(second_other_mock_call).should_receive(:dial).once.with(second_to, second_other_options)
            flexmock(second_other_mock_call).should_receive(:join).never
            flexmock(second_other_mock_call).should_receive(:hangup).once
          end

          def dial_in_thread
            Thread.new do
              status = subject.dial [to, second_to], options
              latch.countdown!
              status
            end
          end

          it "dials all parties and joins the first one to answer, hanging up the rest" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)
            flexmock(second_other_mock_call).should_receive(:hangup).once

            t = dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            other_mock_call << mock_end

            latch.wait(1).should be_false

            second_other_mock_call << mock_end

            latch.wait(2).should be_true

            t.join
            status = t.value
            status.should be_a Dial::DialStatus
            status.should have(2).calls
            status.calls.each { |c| c.should be_a OutboundCall }
          end

          it "unblocks when the joined call unjoins, allowing it to proceed further" do
            flexmock(other_mock_call).should_receive(:join).once.with(call)
            flexmock(second_other_mock_call).should_receive(:hangup).once

            t = dial_in_thread

            latch.wait(1).should be_false

            other_mock_call << mock_answered
            other_mock_call << Punchblock::Event::Unjoined.new(:other_call_id => call.id)

            latch.wait(1).should be_false

            second_other_mock_call << mock_end

            latch.wait(2).should be_true

            t.join
            status = t.value
            status.should be_a Dial::DialStatus
            status.should have(2).calls
            status.calls.each { |c| c.should be_a OutboundCall }
          end

          describe "with options overrides" do
            let(:options) do
              {
                :from => 'foo',
                :timeout => 3000
              }
            end

            let(:other_options) do
              {
                :from => 'foo',
                :timeout => 4000
              }
            end

            let(:second_other_options) do
              {
                :from => 'foo',
                :timeout => 5000
              }
            end

            it "with multiple destinations as an hash, with overrides for each, and an options hash, it dials each call with specified options" do
              t = Thread.new do
                subject.dial({
                  to => {:timeout => 4000},
                  second_to => {:timeout => 5000}
                }, options)
                latch.countdown!
              end

              latch.wait(1).should be_false

              other_mock_call << mock_end

              latch.wait(1).should be_false

              second_other_mock_call << mock_end

              latch.wait(2).should be_true

              t.join
            end
          end

          context "when all calls are rejected" do
            it "has an overall dial status of :no_answer" do
              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_end
              second_other_mock_call << mock_end

              latch.wait(2).should be_true

              t.join
              status = t.value
              status.result.should be == :no_answer
            end
          end

          context "when a call is answered and joined" do
            it "has an overall dial status of :answer" do
              flexmock(other_mock_call).should_receive(:join).once.with(call)
              flexmock(second_other_mock_call).should_receive(:hangup).once

              t = dial_in_thread

              sleep 0.5

              other_mock_call << mock_answered
              other_mock_call << mock_end

              second_other_mock_call << mock_end

              latch.wait(1).should be_true

              t.join
              status = t.value
              status.result.should be == :answer
            end
          end
        end

        describe "with a timeout specified" do
          let(:timeout) { 3 }

          it "should abort the dial after the specified timeout" do
            flexmock(other_mock_call).should_receive(:dial).once
            flexmock(other_mock_call).should_receive(:hangup).once
            flexmock(OutboundCall).should_receive(:new).and_return other_mock_call

            time = Time.now

            t = Thread.new do
              status = subject.dial to, :timeout => timeout
              latch.countdown!
              status
            end

            latch.wait
            time = Time.now - time
            time.to_i.should be == timeout
            t.join
            status = t.value
            status.result.should be == :timeout
          end
        end

      	describe "with a block" do
{'fraction_non_alphanumeric': 0.07527391737418773, 'fraction_numerical': 0.005644358013565432, 'mean_word_length': 1.6735987826528025, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6072036', 'n_tokens_mistral': 5980, 'n_tokens_neox': 5600, 'n_words': 1339}