# frozen_string_literal: true

require 'rubocop/cop/lint/bare_check_code_in_non_exploit'
require 'rubocop/rspec/support'

RSpec.describe RuboCop::Cop::Lint::BareCheckCodeInNonExploit, :config do
  subject(:cop) { described_class.new(config) }

  let(:config) { RuboCop::Config.new }

  context 'in an auxiliary module' do
    it 'registers an offense for bare CheckCode::Safe' do
      expect_offense(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            CheckCode::Safe
            ^^^^^^^^^^^^^^^ Lint/BareCheckCodeInNonExploit: Use `Exploit::CheckCode` instead of bare `CheckCode` in non-exploit modules. Bare `CheckCode` will raise a NameError at runtime.
          end
        end
      RUBY

      expect_correction(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Safe
          end
        end
      RUBY
    end

    it 'registers an offense for bare CheckCode::Unknown' do
      expect_offense(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            CheckCode::Unknown
            ^^^^^^^^^^^^^^^^^^ Lint/BareCheckCodeInNonExploit: Use `Exploit::CheckCode` instead of bare `CheckCode` in non-exploit modules. Bare `CheckCode` will raise a NameError at runtime.
          end
        end
      RUBY

      expect_correction(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Unknown
          end
        end
      RUBY
    end

    it 'registers an offense for bare CheckCode::Appears with a message argument' do
      expect_offense(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            CheckCode::Appears('Version is vulnerable')
            ^^^^^^^^^ Lint/BareCheckCodeInNonExploit: Use `Exploit::CheckCode` instead of bare `CheckCode` in non-exploit modules. Bare `CheckCode` will raise a NameError at runtime.
          end
        end
      RUBY

      expect_correction(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Appears('Version is vulnerable')
          end
        end
      RUBY
    end

    it 'registers an offense for bare CheckCode::Vulnerable with details kwarg' do
      expect_offense(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            CheckCode::Vulnerable(details: { version: '1.0' })
            ^^^^^^^^^ Lint/BareCheckCodeInNonExploit: Use `Exploit::CheckCode` instead of bare `CheckCode` in non-exploit modules. Bare `CheckCode` will raise a NameError at runtime.
          end
        end
      RUBY

      expect_correction(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Vulnerable(details: { version: '1.0' })
          end
        end
      RUBY
    end

    it 'does not register an offense for Exploit::CheckCode::Safe' do
      expect_no_offenses(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Safe
          end
        end
      RUBY
    end

    it 'does not register an offense for Exploit::CheckCode::Safe' do
      expect_no_offenses(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Safe
          end
        end
      RUBY
    end

    it 'does not register an offense for Exploit::CheckCode::Appears with message' do
      expect_no_offenses(<<~RUBY)
        class MetasploitModule < Msf::Auxiliary
          def check
            Exploit::CheckCode::Appears('Version is vulnerable')
          end
        end
      RUBY
    end
  end

  context 'in a post module' do
    it 'registers an offense for bare CheckCode::Safe' do
      expect_offense(<<~RUBY)
        class MetasploitModule < Msf::Post
          def check
            CheckCode::Safe
            ^^^^^^^^^^^^^^^ Lint/BareCheckCodeInNonExploit: Use `Exploit::CheckCode` instead of bare `CheckCode` in non-exploit modules. Bare `CheckCode` will raise a NameError at runtime.
          end
        end
      RUBY

      expect_correction(<<~RUBY)
        class MetasploitModule < Msf::Post
          def check
            Exploit::CheckCode::Safe
          end
        end
      RUBY
    end
  end

  context 'in an evasion module' do
    it 'registers an offense for bare CheckCode::Safe' do
      expect_offense(<<~RUBY)
        class MetasploitModule < Msf::Evasion
          def check
            CheckCode::Safe
            ^^^^^^^^^^^^^^^ Lint/BareCheckCodeInNonExploit: Use `Exploit::CheckCode` instead of bare `CheckCode` in non-exploit modules. Bare `CheckCode` will raise a NameError at runtime.
          end
        end
      RUBY

      expect_correction(<<~RUBY)
        class MetasploitModule < Msf::Evasion
          def check
            Exploit::CheckCode::Safe
          end
        end
      RUBY
    end
  end

  context 'in an exploit module' do
    it 'does not register an offense for bare CheckCode::Safe' do
      expect_no_offenses(<<~RUBY)
        class MetasploitModule < Msf::Exploit
          def check
            CheckCode::Safe
          end
        end
      RUBY
    end
  end

  context 'outside a module class' do
    it 'does not register an offense for bare CheckCode::Safe' do
      expect_no_offenses(<<~RUBY)
        CheckCode::Safe
      RUBY
    end
  end
end
