Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow SIPp to be launched without sudo #97

Merged
merged 2 commits into from
May 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/sippy_cup/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ class Runner
# @param [Scenario, XMLScenario] scenario The scenario to execute
# @param [Hash] opts Options to modify the runner
# @option opts [optional, true, false] :full_sipp_output Whether or not to copy SIPp's stdout/stderr to the parent process. Defaults to true.
# @option opts [optional, true, false] :sudo Whether or not to invoke SIPp with sudo. Defaults to true.
# @option opts [optional, Logger] :logger A logger to use in place of the internal logger to STDOUT.
# @option opts [optional, String] :command The command to execute. This is mostly available for testing.
#
def initialize(scenario, opts = {})
@scenario = scenario
@scenario_options = @scenario.scenario_options

defaults = { full_sipp_output: true }
defaults = { full_sipp_output: true, sudo: true }
@options = defaults.merge(opts)

@command = @options[:command]
Expand Down Expand Up @@ -87,7 +88,7 @@ def wait

def command
@command ||= begin
command = "sudo $(which sipp)"
command = @options[:sudo] ? "sudo $(which sipp)" : 'sipp'
command_options.each_pair do |key, value|
command << (value ? " -#{key} #{value}" : " -#{key}")
end
Expand Down
18 changes: 9 additions & 9 deletions spec/sippy_cup/media_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
end

it 'should start with an empty sequence' do
@media.sequence.should be_empty
expect(@media.sequence).to be_empty
end

it 'should correctly report itself as empty' do
Expand All @@ -25,7 +25,7 @@

it 'should append a valid action to the sequence list' do
@media << 'silence:1000'
@media.sequence.include?('silence:1000').should be true
expect(@media.sequence.include?('silence:1000')).to be true
end

it 'should raise an error when assigning an invalid action' do
Expand All @@ -35,30 +35,30 @@
it 'should produce a PcapFile containing 10 packets for 200ms of silence' do
@media << 'silence:200'
pf = @media.compile!
pf.body.count.should be 10
expect(pf.body.count).to be 10
end

it 'should produce a PcapPacket with 20ms of silence at the end' do
@media << 'silence:20'
pf = @media.compile!
packet = pf.body.first
packet.class.should be PacketFu::PcapPacket
packet.data[-160, 160].should == 0xff.chr * 160
expect(packet.class).to be PacketFu::PcapPacket
expect(packet.data[-160, 160]).to eq(0xff.chr * 160)
end

it 'should produce a PcapPacket with DTMF digit 3, volume 10 at the end' do
@media << 'dtmf:3'
pf = @media.compile!
packet = pf.body.first
packet.class.should be PacketFu::PcapPacket
packet.data[-4, 4].should == ['030a00a0'].pack('H*')
expect(packet.class).to be PacketFu::PcapPacket
expect(packet.data[-4, 4]).to eq(['030a00a0'].pack('H*'))
end

it 'should produce a PcapPacket with DTMF digit #, volume 10 at the end' do
@media << 'dtmf:#'
pf = @media.compile!
packet = pf.body.first
packet.class.should be PacketFu::PcapPacket
packet.data[-4, 4].should == ['0b0a00a0'].pack('H*')
expect(packet.class).to be PacketFu::PcapPacket
expect(packet.data[-4, 4]).to eq(['0b0a00a0'].pack('H*'))
end
end
71 changes: 40 additions & 31 deletions spec/sippy_cup/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

let(:logger) { double }

before { logger.stub :info }
before { allow(logger).to receive :info }

let(:manifest) do
<<-MANIFEST
Expand All @@ -36,10 +36,10 @@
subject { SippyCup::Runner.new scenario, default_settings.merge(settings) }

def expect_command_execution(command = anything)
Process.stub :wait2
subject.stub :process_exit_status
allow(Process).to receive :wait2
allow(subject).to receive :process_exit_status

subject.should_receive(:spawn).with(command, anything)
expect(subject).to receive(:spawn).with(command, anything)
end

describe '#run' do
Expand All @@ -49,12 +49,21 @@ def expect_command_execution(command = anything)
subject.run
end

context 'with sudo disabled' do
let(:settings) { {sudo: false} }
it "executes the correct command to invoke SIPp" do
full_scenario_path = File.join(Dir.tmpdir, '/scenario.*')
expect_command_execution %r{sipp -p 8836 -sf #{full_scenario_path} -i dah.com bar.com}
subject.run
end
end

it "ensures that input files are not left on the filesystem" do
FakeFS do
Dir.mkdir("/tmp") unless Dir.exist?("/tmp")
expect_command_execution.and_raise
expect { subject.run }.to raise_error
Dir.entries(Dir.tmpdir).should eql(['.', '..'])
expect(Dir.entries(Dir.tmpdir)).to eql(['.', '..'])
end
end

Expand All @@ -73,9 +82,9 @@ def expect_command_execution(command = anything)
context "async" do
let(:settings) { {async: true} }
it 'should not wait for SIPp to terminate' do
subject.stub :process_exit_status
subject.should_receive :spawn
Process.should_not_receive :wait2
allow(subject).to receive :process_exit_status
expect(subject).to receive :spawn
expect(Process).not_to receive :wait2
subject.run
end
end
Expand Down Expand Up @@ -281,14 +290,14 @@ def expect_command_execution(command = anything)

it 'logs the path to the csv file' do
expect_command_execution
logger.should_receive(:info).with "Statistics logged at #{File.expand_path('stats.csv')}"
expect(logger).to receive(:info).with "Statistics logged at #{File.expand_path('stats.csv')}"
subject.run
end
end

context "no stats file" do
it 'does not log a statistics file path' do
logger.should_receive(:info).with(/Statistics logged at/).never
expect(logger).to receive(:info).with(/Statistics logged at/).never
expect_command_execution
subject.run
end
Expand Down Expand Up @@ -404,8 +413,8 @@ def expect_command_execution(command = anything)
end

it 'uses CSV in the test run' do
logger.should_receive(:info).ordered.with(/Preparing to run SIPp command/)
logger.should_receive(:info).ordered.with(/Test completed successfully/)
expect(logger).to receive(:info).ordered.with(/Preparing to run SIPp command/)
expect(logger).to receive(:info).ordered.with(/Test completed successfully/)
expect_command_execution(%r{-inf /path/to/vars.csv})
subject.run
end
Expand Down Expand Up @@ -450,16 +459,16 @@ def expect_command_execution(command = anything)
let(:exit_code) { 0 }

it "doesn't raise anything if SIPp returns 0" do
subject.run.should be true
expect(subject.run).to be true
end
end

context "with at least one call failure" do
let(:exit_code) { 1 }

it "returns false if SIPp returns 1" do
logger.should_receive(:info).ordered.with(/Test completed successfully but some calls failed./)
subject.run.should be false
expect(logger).to receive(:info).ordered.with(/Test completed successfully but some calls failed./)
expect(subject.run).to be false
end
end

Expand Down Expand Up @@ -521,11 +530,11 @@ def active_thread_count

context "by default" do
it "proxies stdout to the terminal" do
capture(:stdout) { subject.run }.strip.should == output_string
expect(capture(:stdout) { subject.run }.strip).to eq(output_string)
end

it "proxies stderr to the terminal" do
capture(:stderr) { subject.run }.strip.should == error_string
expect(capture(:stderr) { subject.run }.strip).to eq(error_string)
end

it "does not leak threads" do
Expand All @@ -534,19 +543,19 @@ def active_thread_count
original_thread_count = active_thread_count
subject.run
sleep 0.1
active_thread_count.should == original_thread_count
expect(active_thread_count).to eq(original_thread_count)
end
end

context "with :full_sipp_output disabled" do
let(:settings) { { command: command, full_sipp_output: false } }

it "swallows stdout from SIPp" do
capture(:stdout) { subject.run }.should == ''
expect(capture(:stdout) { subject.run }).to eq('')
end

it "swallows stderr from SIPp" do
capture(:stderr) { subject.run }.should == ''
expect(capture(:stderr) { subject.run }).to eq('')
end

it "does not leak threads" do
Expand All @@ -555,7 +564,7 @@ def active_thread_count
original_thread_count = active_thread_count
subject.run
sleep 0.1
active_thread_count.should == original_thread_count
expect(active_thread_count).to eq(original_thread_count)
end
end
end
Expand All @@ -564,18 +573,18 @@ def active_thread_count
describe '#wait' do
before { subject.sipp_pid = pid }
it "waits for the SIPp process" do
Process.should_receive(:wait2).with pid.to_i
subject.should_receive(:process_exit_status)
subject.should_receive(:cleanup_input_files)
expect(Process).to receive(:wait2).with pid.to_i
expect(subject).to receive(:process_exit_status)
expect(subject).to receive(:cleanup_input_files)
subject.wait
end

context "async" do
subject { SippyCup::Runner.new scenario, logger: logger, async: true }
it "waits for the SIPp process and cleans up input files" do
Process.should_receive(:wait2).with pid.to_i
subject.should_receive(:process_exit_status)
subject.should_receive(:cleanup_input_files)
expect(Process).to receive(:wait2).with pid.to_i
expect(subject).to receive(:process_exit_status)
expect(subject).to receive(:cleanup_input_files)
subject.wait
end
end
Expand All @@ -585,26 +594,26 @@ def active_thread_count
before { subject.sipp_pid = pid }

it "tries to kill the SIPp process if there is a PID" do
Process.should_receive(:kill).with("KILL", pid)
expect(Process).to receive(:kill).with("KILL", pid)
subject.stop
end

context "if there is no PID available" do
let(:pid) { nil }

it "doesn't try to kill the SIPp process" do
Process.should_receive(:kill).never
expect(Process).to receive(:kill).never
subject.stop
end
end

it "raises a Errno::ESRCH if the PID does not exist" do
Process.should_receive(:kill).with("KILL", pid).and_raise(Errno::ESRCH)
expect(Process).to receive(:kill).with("KILL", pid).and_raise(Errno::ESRCH)
expect { subject.stop }.to raise_error Errno::ESRCH
end

it "raises a Errno::EPERM if the user has no permission to kill the process" do
Process.should_receive(:kill).with("KILL", pid).and_raise(Errno::EPERM)
expect(Process).to receive(:kill).with("KILL", pid).and_raise(Errno::EPERM)
expect { subject.stop }.to raise_error Errno::EPERM
end
end
Expand Down
Loading