# -*- coding: binary -*-12# Enable legacy providers such as blowfish-cbc, cast128-cbc, arcfour, etc3$stderr.puts "Overriding user environment variable 'OPENSSL_CONF' to enable legacy functions." unless ENV['OPENSSL_CONF'].nil?4ENV['OPENSSL_CONF'] = File.expand_path(5File.join(File.dirname(__FILE__), '..', 'config', 'openssl.conf')6)78require 'stringio'9require 'factory_bot'10require 'rubocop'11require 'rubocop/rspec/support'12require 'faker'1314# Monkey patch rubocop which fails to load the default rspec config due to encoding issues - https://github.com/rapid7/metasploit-framework/pull/2019615# Caused by our global IO encoding being set to ASCII-8BIT - https://github.com/rapid7/metasploit-framework/blob/b251fc1b635dc07c66cc3848983bdcbeaa08a81f/lib/metasploit/framework/common_engine.rb#L25-L3316# Original code: https://github.com/rubocop/rubocop/blob/b6c9b0ed31daf40be5a273714095e451aee10bcd/lib/rubocop/config_loader.rb#L27517# Character which causes encoding failure: https://github.com/rubocop/rubocop/blob/b6c9b0ed31daf40be5a273714095e451aee10bcd/config/default.yml#L3298-L330518module RuboCop19class ConfigLoader20# Read the specified file, or exit with a friendly, concise message on21# stderr. Care is taken to use the standard OS exit code for a "file not22# found" error.23def self.read_file(absolute_path)24File.binread(absolute_path).force_encoding(Encoding::UTF_8)25rescue Errno::ENOENT26raise ConfigNotFoundError, "Configuration file not found: #{absolute_path}"27end28end29end3031ENV['RAILS_ENV'] = 'test'3233load_metasploit = ENV.fetch('SPEC_HELPER_LOAD_METASPLOIT', 'true') == 'true'3435if load_metasploit36# @note must be before loading config/environment because railtie needs to be loaded before37# `Metasploit::Framework::Application.initialize!` is called.38#39# Must be explicit as activerecord is optional dependency40require 'active_record/railtie'41require 'metasploit/framework/database'42# check if database.yml is present43unless Metasploit::Framework::Database.configurations_pathname.try(:to_path)44fail 'RSPEC currently needs a configured database'45end4647require File.expand_path('../../config/environment', __FILE__)4849# Don't `require 'rspec/rails'` as it includes support for pieces of rails that metasploit-framework doesn't use50require 'rspec/rails'5152require 'metasploit/framework/spec'5354FILE_FIXTURES_PATH = File.expand_path(File.dirname(__FILE__)) + '/file_fixtures/'5556# Load the shared examples from the following engines57engines = [58Metasploit::Concern,59Rails60]6162# Requires supporting ruby files with custom matchers and macros, etc,63# in spec/support/ and its subdirectories.64engines.each do |engine|65support_glob = engine.root.join('spec', 'support', '**', '*.rb')66Dir[support_glob].each { |f|67require f68}69end7071# Fail the test suite if the test environment database has not been migrated72migration_manager = Class.new.extend(Msf::DBManager::Migration)73fail "Run `RAILS_ENV=test rake db:migrate` before running tests" if migration_manager.needs_migration?74end7576RSpec.configure do |config|77config.raise_errors_for_deprecations!78config.include RuboCop::RSpec::ExpectOffense79config.expose_dsl_globally = false8081# Don't run Acceptance tests by default82config.define_derived_metadata(file_path: %r{spec/acceptance/}) do |metadata|83metadata[:acceptance] ||= true84end85config.filter_run_excluding({ acceptance: true })8687# These two settings work together to allow you to limit a spec run88# to individual examples or groups you care about by tagging them with89# `:focus` metadata. When nothing is tagged with `:focus`, all examples90# get run.91if ENV['CI']92config.before(:example, :focus) { raise "Should not commit focused specs" }93else94config.filter_run focus: true95config.run_all_when_everything_filtered = true96end9798# allow more verbose output when running an individual spec file.99if config.files_to_run.one?100# RSpec filters the backtrace by default so as not to be so noisy.101# This causes the full backtrace to be printed when running a single102# spec file (e.g. to troubleshoot a particular spec failure).103config.full_backtrace = true104end105106# Print the 10 slowest examples and example groups at the107# end of the spec run, to help surface which specs are running108# particularly slow.109config.profile_examples = 10110111# Run specs in random order to surface order dependencies. If you find an112# order dependency and want to debug it, you can fix the order by providing113# the seed, which is printed after each run.114# --seed 1234115config.order = :random116117if load_metasploit118config.use_transactional_fixtures = true119120# rspec-rails 3 will no longer automatically infer an example group's spec type121# from the file location. You can explicitly opt-in to the feature using this122# config option.123# To explicitly tag specs without using automatic inference, set the `:type`124# metadata manually:125#126# describe ThingsController, :type => :controller do127# # Equivalent to being in spec/controllers128# end129config.infer_spec_type_from_file_location!130end131132# Seed global randomization in this process using the `--seed` CLI option.133# Setting this allows you to use `--seed` to deterministically reproduce134# test failures related to randomization by passing the same `--seed` value135# as the one that triggered the failure.136Kernel.srand config.seed137138# Implemented to avoid regression issue with code calling Faker not being deterministic139# https://github.com/faker-ruby/faker/issues/2281140Faker::Config.random = Random.new(config.seed)141142config.expect_with :rspec do |expectations|143# Enable only the newer, non-monkey-patching expect syntax.144expectations.syntax = :expect145end146147# rspec-mocks config goes here. You can use an alternate test double148# library (such as bogus or mocha) by changing the `mock_with` option here.149config.mock_with :rspec do |mocks|150# Enable only the newer, non-monkey-patching expect syntax.151# For more details, see:152# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/153mocks.syntax = :expect154155mocks.patch_marshal_to_support_partial_doubles = false156157# Prevents you from mocking or stubbing a method that does not exist on158# a real object.159mocks.verify_partial_doubles = true160end161162if ENV['REMOTE_DB']163require 'metasploit/framework/data_service/remote/managed_remote_data_service'164opts = {}165opts[:process_name] = File.join('tools', 'dev', 'msfdb_ws')166opts[:host] = 'localhost'167opts[:port] = '8080'168169config.before(:suite) do170Metasploit::Framework::DataService::ManagedRemoteDataService.instance.start(opts)171end172173config.after(:suite) do174Metasploit::Framework::DataService::ManagedRemoteDataService.instance.stop175end176end177178if ENV['MSF_FEATURE_DEFER_MODULE_LOADS']179config.before(:suite) do180Msf::FeatureManager.instance.set(Msf::FeatureManager::DEFER_MODULE_LOADS, true)181end182end183184# rex-text table performs word wrapping on msfconsole tables:185# https://github.com/rapid7/rex-text/blob/11e59416f7d8cce18b8b8b9893b3277e6ad0bea1/lib/rex/text/wrapped_table.rb#L74186# This can cause some integration tests to fail if the tests are run from smaller consoles187# This mock will ensure that the tests run without word-wrapping.188require 'bigdecimal'189config.before(:each) do190mock_io_console = double(:console, winsize: { rows: 30, columns: ::BigDecimal::INFINITY }.values)191allow(::IO).to receive(:console).and_return(mock_io_console)192end193end194195if load_metasploit196Metasploit::Framework::Spec::Constants::Suite.configure!197Metasploit::Framework::Spec::Threads::Suite.configure!198end199200def get_stdout(&block)201out = $stdout202$stdout = tmp = StringIO.new203begin204yield205ensure206$stdout = out207end208tmp.string209end210211def get_stderr(&block)212out = $stderr213$stderr = tmp = StringIO.new214begin215yield216ensure217$stderr = out218end219tmp.string220end221222223