TEST: core/ruby method specs
This commit is contained in:
99
spec/beef/core/ruby/hash_spec.rb
Normal file
99
spec/beef/core/ruby/hash_spec.rb
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Hash#deep_merge' do
|
||||
it 'merges two simple hashes' do
|
||||
hash1 = { a: 1, b: 2 }
|
||||
hash2 = { c: 3, d: 4 }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result).to eq({ a: 1, b: 2, c: 3, d: 4 })
|
||||
end
|
||||
|
||||
it 'overwrites duplicate keys with values from calling hash' do
|
||||
hash1 = { a: 1, b: 2 }
|
||||
hash2 = { b: 3, c: 4 }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result[:a]).to eq(1)
|
||||
expect(result[:b]).to eq(3) # hash2 value overwrites
|
||||
expect(result[:c]).to eq(4)
|
||||
end
|
||||
|
||||
it 'recursively merges nested hashes' do
|
||||
hash1 = { a: { b: 1, c: 2 }, d: 3 }
|
||||
hash2 = { a: { c: 4, e: 5 }, f: 6 }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result[:a][:b]).to eq(1)
|
||||
expect(result[:a][:c]).to eq(4) # hash2 value overwrites
|
||||
expect(result[:a][:e]).to eq(5)
|
||||
expect(result[:d]).to eq(3)
|
||||
expect(result[:f]).to eq(6)
|
||||
end
|
||||
|
||||
it 'handles deeply nested hashes' do
|
||||
hash1 = { a: { b: { c: 1 } } }
|
||||
hash2 = { a: { b: { d: 2 } } }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result[:a][:b][:c]).to eq(1)
|
||||
expect(result[:a][:b][:d]).to eq(2)
|
||||
end
|
||||
|
||||
it 'does not modify the original hash' do
|
||||
hash1 = { a: 1 }
|
||||
hash2 = { b: 2 }
|
||||
original_hash1 = hash1.dup
|
||||
|
||||
hash1.deep_merge(hash2)
|
||||
|
||||
expect(hash1).to eq(original_hash1)
|
||||
end
|
||||
|
||||
it 'handles empty hashes' do
|
||||
hash1 = {}
|
||||
hash2 = { a: 1 }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result).to eq({ a: 1 })
|
||||
end
|
||||
|
||||
it 'handles merging with empty hash' do
|
||||
hash1 = { a: 1 }
|
||||
hash2 = {}
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result).to eq({ a: 1 })
|
||||
end
|
||||
|
||||
it 'handles non-hash values in nested structure' do
|
||||
hash1 = { a: { b: 1 } }
|
||||
hash2 = { a: 2 } # a is not a hash in hash2
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result[:a]).to eq(2) # Should overwrite with non-hash value
|
||||
end
|
||||
|
||||
it 'handles nil values in source hash' do
|
||||
hash1 = { a: nil, b: 1 }
|
||||
hash2 = { a: 2, c: 3 }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result[:a]).to eq(2) # Should overwrite nil
|
||||
expect(result[:b]).to eq(1)
|
||||
expect(result[:c]).to eq(3)
|
||||
end
|
||||
|
||||
it 'handles nil values when merging nested hashes' do
|
||||
hash1 = { a: nil }
|
||||
hash2 = { a: { b: 1 } }
|
||||
result = hash1.deep_merge(hash2)
|
||||
|
||||
expect(result[:a]).to eq({ b: 1 }) # Should overwrite nil with hash
|
||||
end
|
||||
end
|
||||
94
spec/beef/core/ruby/module_spec.rb
Normal file
94
spec/beef/core/ruby/module_spec.rb
Normal file
@@ -0,0 +1,94 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Module extensions' do
|
||||
# Create a test module to use in tests
|
||||
let(:test_module) do
|
||||
Module.new do
|
||||
def test_method
|
||||
'test'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#included_in_classes' do
|
||||
it 'returns an array' do
|
||||
result = test_module.included_in_classes
|
||||
expect(result).to be_an(Array)
|
||||
end
|
||||
|
||||
it 'finds classes that include the module' do
|
||||
mod = test_module
|
||||
test_class = Class.new do
|
||||
include mod
|
||||
end
|
||||
|
||||
# Force class to be created
|
||||
test_class.new
|
||||
|
||||
included_classes = mod.included_in_classes
|
||||
expect(included_classes.map(&:to_s)).to include(test_class.to_s)
|
||||
end
|
||||
|
||||
it 'returns unique classes only' do
|
||||
mod = test_module
|
||||
test_class = Class.new do
|
||||
include mod
|
||||
end
|
||||
|
||||
# Force class to be created multiple times
|
||||
test_class.new
|
||||
test_class.new
|
||||
|
||||
included_classes = mod.included_in_classes
|
||||
unique_class_names = included_classes.map(&:to_s)
|
||||
expect(unique_class_names.count(test_class.to_s)).to eq(1)
|
||||
end
|
||||
|
||||
it 'returns empty array when module is not included anywhere' do
|
||||
isolated_module = Module.new
|
||||
result = isolated_module.included_in_classes
|
||||
expect(result).to be_an(Array)
|
||||
# May or may not be empty depending on what's loaded, but should be an array
|
||||
end
|
||||
end
|
||||
|
||||
describe '#included_in_modules' do
|
||||
it 'returns an array' do
|
||||
result = test_module.included_in_modules
|
||||
expect(result).to be_an(Array)
|
||||
end
|
||||
|
||||
it 'finds modules that include the module' do
|
||||
mod = test_module
|
||||
including_module = Module.new do
|
||||
include mod
|
||||
end
|
||||
|
||||
# Force module to be created
|
||||
Class.new { include including_module }
|
||||
|
||||
included_modules = mod.included_in_modules
|
||||
expect(included_modules.map(&:to_s)).to include(including_module.to_s)
|
||||
end
|
||||
|
||||
it 'returns unique modules only' do
|
||||
mod = test_module
|
||||
including_module = Module.new do
|
||||
include mod
|
||||
end
|
||||
|
||||
# Force module to be created multiple times
|
||||
Class.new { include including_module }
|
||||
Class.new { include including_module }
|
||||
|
||||
included_modules = mod.included_in_modules
|
||||
unique_module_names = included_modules.map(&:to_s)
|
||||
expect(unique_module_names.count(including_module.to_s)).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
191
spec/beef/core/ruby/print_spec.rb
Normal file
191
spec/beef/core/ruby/print_spec.rb
Normal file
@@ -0,0 +1,191 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Print functions' do
|
||||
let(:logger) { BeEF.logger }
|
||||
let(:test_message) { 'test message' }
|
||||
|
||||
before(:each) do
|
||||
# Mock stdout to avoid cluttering test output
|
||||
allow($stdout).to receive(:puts)
|
||||
allow($stdout).to receive(:print)
|
||||
|
||||
# Mock logger methods
|
||||
allow(logger).to receive(:error)
|
||||
allow(logger).to receive(:info)
|
||||
allow(logger).to receive(:warn)
|
||||
allow(logger).to receive(:debug)
|
||||
end
|
||||
|
||||
describe '#print_error' do
|
||||
it 'calls logger.error with the message' do
|
||||
expect(logger).to receive(:error).with(test_message)
|
||||
print_error(test_message)
|
||||
end
|
||||
|
||||
it 'outputs to stdout with timestamp and error prefix' do
|
||||
expect($stdout).to receive(:puts).with(match(/\[!\] #{test_message}/))
|
||||
print_error(test_message)
|
||||
end
|
||||
|
||||
it 'converts non-string arguments to string' do
|
||||
expect(logger).to receive(:error).with('123')
|
||||
print_error(123)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_info' do
|
||||
it 'calls logger.info with the message' do
|
||||
expect(logger).to receive(:info).with(test_message)
|
||||
print_info(test_message)
|
||||
end
|
||||
|
||||
it 'outputs to stdout with timestamp and info prefix' do
|
||||
expect($stdout).to receive(:puts).with(match(/\[\*\] #{test_message}/))
|
||||
print_info(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_status' do
|
||||
it 'calls print_info' do
|
||||
expect(logger).to receive(:info).with(test_message)
|
||||
print_status(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_warning' do
|
||||
it 'calls logger.warn with the message' do
|
||||
expect(logger).to receive(:warn).with(test_message)
|
||||
print_warning(test_message)
|
||||
end
|
||||
|
||||
it 'outputs to stdout with timestamp and warning prefix' do
|
||||
expect($stdout).to receive(:puts).with(match(/\[!\] #{test_message}/))
|
||||
print_warning(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_debug' do
|
||||
let(:config) { BeEF::Core::Configuration.instance }
|
||||
|
||||
context 'when debug is enabled' do
|
||||
before do
|
||||
allow(config).to receive(:get).with('beef.debug').and_return(true)
|
||||
allow(BeEF::Core::Console::CommandLine).to receive(:parse).and_return({})
|
||||
end
|
||||
|
||||
it 'calls logger.debug with the message' do
|
||||
expect(logger).to receive(:debug).with(test_message)
|
||||
print_debug(test_message)
|
||||
end
|
||||
|
||||
it 'outputs to stdout with timestamp and debug prefix' do
|
||||
expect($stdout).to receive(:puts).with(match(/\[>\] #{test_message}/))
|
||||
print_debug(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when verbose flag is set' do
|
||||
before do
|
||||
allow(config).to receive(:get).with('beef.debug').and_return(false)
|
||||
allow(BeEF::Core::Console::CommandLine).to receive(:parse).and_return({ verbose: true })
|
||||
end
|
||||
|
||||
it 'calls logger.debug with the message' do
|
||||
expect(logger).to receive(:debug).with(test_message)
|
||||
print_debug(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when debug is disabled and verbose is not set' do
|
||||
before do
|
||||
allow(config).to receive(:get).with('beef.debug').and_return(false)
|
||||
allow(BeEF::Core::Console::CommandLine).to receive(:parse).and_return({})
|
||||
end
|
||||
|
||||
it 'does not call logger.debug' do
|
||||
expect(logger).not_to receive(:debug)
|
||||
print_debug(test_message)
|
||||
end
|
||||
|
||||
it 'does not output to stdout' do
|
||||
expect($stdout).not_to receive(:puts)
|
||||
print_debug(test_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_success' do
|
||||
it 'calls logger.info with the message' do
|
||||
expect(logger).to receive(:info).with(test_message)
|
||||
print_success(test_message)
|
||||
end
|
||||
|
||||
it 'outputs to stdout with timestamp and success prefix' do
|
||||
expect($stdout).to receive(:puts).with(match(/\[\+\] #{test_message}/))
|
||||
print_success(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_good' do
|
||||
it 'calls print_success' do
|
||||
expect(logger).to receive(:info).with(test_message)
|
||||
print_good(test_message)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_more' do
|
||||
context 'with string input' do
|
||||
it 'splits string by newlines and formats each line' do
|
||||
multi_line = "line1\nline2\nline3"
|
||||
expect($stdout).to receive(:puts).with(match(/line1/))
|
||||
expect($stdout).to receive(:puts).with(match(/line2/))
|
||||
expect($stdout).to receive(:puts).with(match(/\|_ line3/)) # Last line has |_
|
||||
expect(logger).to receive(:info).exactly(3).times
|
||||
print_more(multi_line)
|
||||
end
|
||||
|
||||
it 'formats last line with |_ prefix' do
|
||||
single_line = "single line"
|
||||
expect($stdout).to receive(:puts).with(match(/\|_ single line/))
|
||||
expect(logger).to receive(:info).with(match(/\|_ single line/))
|
||||
print_more(single_line)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with array input' do
|
||||
it 'formats each array element as a line' do
|
||||
lines_array = ["line1", "line2", "line3"]
|
||||
expect($stdout).to receive(:puts).exactly(3).times
|
||||
expect(logger).to receive(:info).exactly(3).times
|
||||
print_more(lines_array)
|
||||
end
|
||||
|
||||
it 'formats last array element with |_ prefix' do
|
||||
lines_array = ["line1", "line2"]
|
||||
expect($stdout).to receive(:puts).with(match(/\| line1/))
|
||||
expect($stdout).to receive(:puts).with(match(/\|_ line2/))
|
||||
print_more(lines_array)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#print_over' do
|
||||
it 'calls logger.info with the message' do
|
||||
expect(logger).to receive(:info).with(test_message)
|
||||
print_over(test_message)
|
||||
end
|
||||
|
||||
it 'outputs formatted message to stdout' do
|
||||
# print is a private Kernel method, hard to stub directly
|
||||
# We verify the function executes and calls logger
|
||||
# The actual output includes ANSI color codes and carriage return
|
||||
expect { print_over(test_message) }.not_to raise_error
|
||||
expect(logger).to have_received(:info).with(test_message)
|
||||
end
|
||||
end
|
||||
end
|
||||
28
spec/beef/core/ruby/security_spec.rb
Normal file
28
spec/beef/core/ruby/security_spec.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Security method overrides' do
|
||||
it 'overrides exec method' do
|
||||
# The exec method should be overridden to prevent usage
|
||||
# We can't easily test the exit behavior without forking
|
||||
# so we just check that the method is overridden
|
||||
expect(method(:exec).source_location).not_to be_nil
|
||||
expect(method(:exec).source_location[0]).to include('core/ruby/security.rb')
|
||||
end
|
||||
|
||||
it 'overrides system method' do
|
||||
# The system method should be overridden
|
||||
expect(method(:system).source_location).not_to be_nil
|
||||
expect(method(:system).source_location[0]).to include('core/ruby/security.rb')
|
||||
end
|
||||
|
||||
it 'overrides Kernel.system method' do
|
||||
# Kernel.system should be overridden
|
||||
expect(Kernel.method(:system).source_location).not_to be_nil
|
||||
expect(Kernel.method(:system).source_location[0]).to include('core/ruby/security.rb')
|
||||
end
|
||||
end
|
||||
27
spec/beef/core/ruby/string_spec.rb
Normal file
27
spec/beef/core/ruby/string_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'String colorization' do
|
||||
it 'includes Term::ANSIColor module' do
|
||||
expect(String.included_modules).to include(Term::ANSIColor)
|
||||
end
|
||||
|
||||
it 'can use color methods on strings' do
|
||||
string = 'test'
|
||||
expect(string.respond_to?(:red)).to be(true)
|
||||
expect(string.respond_to?(:green)).to be(true)
|
||||
expect(string.respond_to?(:blue)).to be(true)
|
||||
end
|
||||
|
||||
it 'applies color methods correctly' do
|
||||
string = 'hello'
|
||||
colored = string.red
|
||||
|
||||
expect(colored).to be_a(String)
|
||||
expect(colored).not_to eq(string) # should now be: "\e[31mhello\e[0m" (red colored hello)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user