Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/test/lib/module_test.rb
Views: 11766
require 'rex/stopwatch'12module Msf3module ModuleTest4attr_accessor :tests5attr_accessor :failures6attr_accessor :skipped78class SkipTestError < ::Exception9end1011def initialize(info = {})12@tests = 013@failures = 014@skipped = 015super1617register_options(18[19OptString.new("TestName", [false, "Run a specified test method name.", nil]),20], self.class21)22end2324def run_all_tests25tests = datastore['TestName'].present? ? [datastore['TestName'].to_sym] : self.methods.select { |m| m.to_s =~ /^test_/ }26tests.each { |test_method|27begin28unless respond_to?(test_method)29print_error("test method #{test_method} not found")30next31end32self.send(test_method)33rescue SkipTestError => e34# If the entire def is skipped, increment tests and skip count35@tests += 136@skipped += 137print_status("SKIPPED: def #{test_method} (#{e.message})")38end39}40end4142def skip(msg = "No reason given")43raise SkipTestError, msg44end4546def it(msg = "", &block)47@current_it_msg = msg48@tests += 149begin50result = block.call51unless result52@failures += 153print_error("FAILED: #{error}") if error54@current_it_msg = nil55print_error("FAILED: #{msg}")56return57end58rescue SkipTestError => e59@skipped += 160@current_it_msg = nil61print_status("SKIPPED: #{msg} (#{e.message})")62return63rescue ::Exception => e64@failures += 165print_error("FAILED: #{msg}")66print_error("Exception: #{e.class}: #{e}")67dlog("Exception in testing - #{msg}")68dlog("Call stack: #{e.backtrace.join("\n")}")69return70ensure71@current_it_msg = nil72end7374print_good("#{msg}")75end7677def pending(msg = "", &block)78print_status("PENDING: #{msg}")79end8081# @return [Integer] The number of tests that have passed82def passed83@tests - @failures84end8586# When printing to console, additionally prepend the current test name87[88:print,89:print_line,90:print_status,91:print_good,9293:print_warning,94:print_error,95:print_bad,96].each do |method|97define_method(method) do |msg|98super(@current_it_msg ? "[#{@current_it_msg}] #{msg}" : msg)99end100end101end102103module ModuleTest::PostTest104include ModuleTest105def run106print_status("Running against session #{datastore["SESSION"]}")107print_status("Session type is #{session.type} and platform is #{session.platform}")108109@tests = 0110@failures = 0111@skipped = 0112113_res, elapsed_time = Rex::Stopwatch.elapsed_time do114run_all_tests115end116117vprint_status("Testing complete in #{elapsed_time.round(2)} seconds")118status = "Passed: #{passed}; Failed: #{@failures}; Skipped: #{@skipped}"119if @failures > 0120print_error(status)121else122print_status(status)123end124end125end126127module ModuleTest::PostTestFileSystem128def initialize(info = {})129super130131register_options(132[133OptBool.new("AddEntropy", [false, "Add entropy token to file and directory names.", true]),134OptString.new('BaseDirectoryName', [true, 'Directory name to create', 'meterpreter-test-dir']),135OptString.new("BaseFileName", [true, "File/dir base name", "meterpreter-test"]),136], self.class137)138139@directory_stack = []140end141142def push_test_directory143@directory_stack.push(_file_system.pwd)144145# Find the temp directory146147# TODO: This caused issue with random jobs, will add some logic below to unblock for now148# tmp = _file_system.get_env("TMP")&.strip&.presence || _file_system&.get_env("TMPDIR").strip&.presence149if session.platform == 'unix'150tmp = _file_system.get_env("TMP").strip.presence || _file_system.get_env("TMPDIR").strip.presence151else152tmp = _file_system.get_env("TMP") || _file_system.get_env("TMPDIR")153end154155# mettle fallback156tmp = '/tmp' if tmp.nil? && _file_system.directory?('/tmp')157raise "Could not find tmp directory" if tmp == nil || !_file_system.directory?(tmp)158159vprint_status("Setup: changing working directory to tmp: #{tmp}")160_file_system.cd(tmp)161162vprint_status("Setup: Creating clean directory")163164if datastore["AddEntropy"]165entropy_value = '-' + ('a'..'z').to_a.shuffle[0, 8].join166else167entropy_value = ""168end169clean_test_directory = datastore['BaseDirectoryName'] + entropy_value170_file_system.mkdir(clean_test_directory)171_file_system.cd(clean_test_directory)172173vprint_status("Setup: Now in #{_file_system.pwd}")174end175176def pop_test_directory177previous_directory = @directory_stack.pop178unless previous_directory.nil?179vprint_status("Cleanup: changing working directory back to #{previous_directory}")180_file_system.cd(previous_directory)181end182end183184# Private PostFile wrapper to ensure we don't clobber the test module's namespace with the Msf::Post::File mixin methods185class FileSystem186include Msf::Post::File187188def initialize(mod)189@mod = mod190@session = mod.session191end192193private194195def vprint_status(s)196@mod.vprint_status(s)197end198199def register_dir_for_cleanup(path)200end201202attr_reader :session203end204205def _file_system206FileSystem.new(self)207end208end209end210211212