
# -*- coding:binary -*-
require 'spec_helper'

require 'msf/core'
require 'msf/core/exploit/http/server'

RSpec.describe Msf::Exploit::Remote::HttpServer do

  subject(:server_module) do
    mod = Msf::Exploit.allocate
    mod.extend described_class
    mod.send(:initialize, {})

    mod
  end

  let(:mock_service) do
    double 'service',
           add_resource: nil,
           :'server_name=' => nil
  end

  before do
    allow(Rex::ServiceManager).to receive(:start).and_return(mock_service)
  end

  # Ensure the class is hooks Metasploit::Concern
  it_should_behave_like 'Metasploit::Concern.run'

  describe "#add_resource" do
    it "should call the ServiceManager's add_resource" do
      server_module.start_service

      expect(mock_service).to receive(:add_resource)
      server_module.add_resource('Path' => 'foo')
    end

    it "should re-raise if the resource has already been added" do
      server_module.start_service

      expect(mock_service).to receive(:add_resource).ordered
      expect(mock_service).to receive(:add_resource).ordered.and_raise(RuntimeError)

      server_module.add_resource('Path' => 'foo')

      expect { server_module.add_resource('Path' => 'foo') }.to raise_error(RuntimeError)
    end

  end

  describe "#cleanup" do
    it "should not remove resources if none were successfully added" do
      expect(server_module).not_to receive(:remove_resource)
      server_module.cleanup
    end

    it "should remove successfully-added resources" do
      # setup
      server_module.start_service
      resources = [ 'a', 'b', 'c' ]
      resources.each { |r| server_module.add_resource('Path' => r) }

      # The service will add one resource as part of #start_service, so
      # add that to the number that we added manually
      expect(server_module).to receive(:remove_resource).exactly(resources.count + 1).times
      server_module.cleanup
    end

  end

  describe "#hardcoded_uripath" do
    it "should call the ServiceManager's add_resource" do
      server_module.start_service

      expect(mock_service).to receive(:add_resource)
      server_module.hardcoded_uripath('foo')
    end

    it "should re-raise if the resource has already been added" do
      server_module.start_service

      expect(mock_service).to receive(:add_resource).ordered.and_raise(RuntimeError)

      expect { server_module.hardcoded_uripath('foo') }.to raise_error(RuntimeError)
    end
  end

end


