require 'spec_helper' require 'ronin/exploits/cli/exploit_methods' require 'ronin/exploits/cli/command' describe Ronin::Exploits::CLI::ExploitMethods do module TestExploitMethods class TestCommand < Ronin::Exploits::CLI::Command include Ronin::Exploits::CLI::ExploitMethods end end let(:command_class) { TestExploitMethods::TestCommand } subject { command_class.new } describe "#load_exploit" do let(:exploit_id) { 'html/encode' } it "must call Exploits.load_class with the given ID" do expect(Ronin::Exploits).to receive(:load_class).with(exploit_id) expect(subject).to_not receive(:exit) subject.load_exploit(exploit_id) end context "when Ronin::Exploits::ClassNotfound is raised" do let(:message) { "class not found" } let(:exception) do Ronin::Exploits::ClassNotFound.new(message) end it "must print an error message and exit with an error code" do expect(Ronin::Exploits).to receive(:load_class).with(exploit_id).and_raise(exception) expect(subject).to receive(:exit).with(1) expect { subject.load_exploit(exploit_id) }.to output("#{subject.command_name}: #{message}#{$/}").to_stderr end end context "when another type of exception is raised" do let(:message) { "unexpected error" } let(:exception) { RuntimeError.new(message) } it "must print the exception, an error message, and exit with -1" do expect(Ronin::Exploits).to receive(:load_class).with(exploit_id).and_raise(exception) expect(subject).to receive(:print_exception).with(exception) expect(subject).to receive(:exit).with(-1) expect { subject.load_exploit(exploit_id) }.to output("#{subject.command_name}: an unhandled exception occurred while loading exploit #{exploit_id}#{$/}").to_stderr end end end describe "#load_exploit_from" do let(:file) { '/path/to/html/encode.rb' } it "must call Exploits.load_class with the given ID and file" do expect(Ronin::Exploits).to receive(:load_class_from_file).with(file) expect(subject).to_not receive(:exit) subject.load_exploit_from(file) end context "when Ronin::Exploits::ClassNotfound is raised" do let(:message) { "class not found" } let(:exception) do Ronin::Exploits::ClassNotFound.new(message) end it "must print an error message and exit with an error code" do expect(Ronin::Exploits).to receive(:load_class_from_file).with(file).and_raise(exception) expect(subject).to receive(:exit).with(1) expect { subject.load_exploit_from(file) }.to output("#{subject.command_name}: #{message}#{$/}").to_stderr end end context "when another type of exception is raised" do let(:message) { "unexpected error" } let(:exception) { RuntimeError.new(message) } it "must print the exception, an error message, and exit with -1" do expect(Ronin::Exploits).to receive(:load_class_from_file).with(file).and_raise(exception) expect(subject).to receive(:print_exception).with(exception) expect(subject).to receive(:exit).with(-1) expect { subject.load_exploit_from(file) }.to output( "#{subject.command_name}: an unhandled exception occurred while loading exploit from file #{file}#{$/}" ).to_stderr end end end describe "#initialie_exploit" do let(:exploit_id) { 'test' } let(:exploit_class) { double('Encoder class', id: exploit_id) } it "must return a new instance of the given exploit class" do expect(exploit_class).to receive(:new) subject.initialize_exploit(exploit_class) end context "when additional keyword arguments are given" do let(:kwargs) do {foo: 1, bar: 2} end it "must pass them to new()" do expect(exploit_class).to receive(:new).with(**kwargs) subject.initialize_exploit(exploit_class,**kwargs) end end context "when a Core::Params::ParamError is raised" do let(:message) { "param foo was not set" } let(:exception) { Ronin::Core::Params::RequiredParam.new(message) } it "must print an error message and exit with 1" do expect(exploit_class).to receive(:new).and_raise(exception) expect(subject).to receive(:exit).with(1) expect { subject.initialize_exploit(exploit_class) }.to output("#{subject.command_name}: #{message}#{$/}").to_stderr end end context "when another type of exception is raised" do let(:message) { "unexpected error" } let(:exception) { RuntimeError.new(message) } it "must print the exception, an error message, and exit with -1" do expect(exploit_class).to receive(:new).and_raise(exception) expect(subject).to receive(:print_exception).with(exception) expect(subject).to receive(:exit).with(-1) expect { subject.initialize_exploit(exploit_class) }.to output("#{subject.command_name}: an unhandled exception occurred while initializing exploit #{exploit_id}#{$/}").to_stderr end end end describe "#validate_exploit" do let(:exploit_id) { 'test' } let(:exploit) { double('Encoder instance', class_id: exploit_id) } it "must call #perform_validate on #exploit" do expect(exploit).to receive(:perform_validate) subject.validate_exploit(exploit) end context "when a Core::Params::ParamError is raised" do let(:message) { "param foo was not set" } let(:exception) { Ronin::Core::Params::RequiredParam.new(message) } it "must print an error message and exit with 1" do expect(exploit).to receive(:perform_validate).and_raise(exception) expect(subject).to receive(:exit).with(1) expect { subject.validate_exploit(exploit) }.to output("#{subject.command_name}: failed to validate the exploit #{exploit_id}: #{message}#{$/}").to_stderr end end context "when a Ronin::Exploits::ValidationError is raised" do let(:message) { "param foo was not set" } let(:exception) do Ronin::Exploits::ValidationError.new(message) end it "must print an error message and exit with 1" do expect(exploit).to receive(:perform_validate).and_raise(exception) expect(subject).to receive(:exit).with(1) expect { subject.validate_exploit(exploit) }.to output("#{subject.command_name}: failed to validate the exploit #{exploit_id}: #{message}#{$/}").to_stderr end end context "when another type of exception is raised" do let(:message) { "unexpected error" } let(:exception) { RuntimeError.new(message) } it "must print the exception, an error message, and exit with -1" do expect(exploit).to receive(:perform_validate).and_raise(exception) expect(subject).to receive(:print_exception).with(exception) expect(subject).to receive(:exit).with(-1) expect { subject.validate_exploit(exploit) }.to output("#{subject.command_name}: an unhandled exception occurred while validating the exploit #{exploit_id}#{$/}").to_stderr end end end end