hashie/hashie, scoped to lib, at 59e021c583: the project's own tests caught 258 of 330 planted faults, 72 got through, and corral proved 57 of those missing tests by writing a test and running it.
require 'spec_helper'
require 'tempfile'
require_relative '../../lib/hashie/mash.rb'
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves untrusted ERB in YAML keys without executing it during loading' do
corral_erb_key = "<%= raise 'corral_untrusted_yaml_key_executed' %>"
Tempfile.create(['corral-untrusted-key', '.yml']) do |corral_yaml_file|
corral_yaml_file.write("\"#{corral_erb_key}\": preserved\n")
corral_yaml_file.flush
corral_loaded_mash = described_class.load(corral_yaml_file.path)
expect(corral_loaded_mash[corral_erb_key]).to eq 'preserved'
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves untrusted YAML ERB literally when exposed through a module for corral' do
corral_template = '<%= raise "corral detected unauthorized ERB evaluation" %>'
Tempfile.create(['corral-untrusted-template', '.yml']) do |corral_file|
corral_file.write("template: '#{corral_template}'\n")
corral_file.flush
corral_settings = described_class.load(corral_file.path)
expect(corral_settings['template']).to eq corral_template
corral_receiver = Class.new do
include corral_settings.to_module(:corral_untrusted_configuration)
end.new
expect(corral_receiver.corral_untrusted_configuration['template']).to eq corral_template
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves ERB literally when loading YAML through a quiet subclass by default' do
corral_template = "<%= raise 'corral_untrusted_yaml_was_evaluated' %>"
corral_file = Tempfile.new(['corral_quiet_yaml', '.yml'])
begin
corral_file.write("message: #{corral_template.inspect}\n")
corral_file.close
corral_settings = described_class.quiet.load(corral_file.path)
expect(corral_settings['message']).to eq corral_template
ensure
corral_file.close!
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves unevaluated YAML templates when rejecting unrelated configuration keys' do
corral_template = '<%= raise "corral_untrusted_erb_executed" %>'
Tempfile.create(['corral_untrusted_config', '.yml']) do |corral_file|
corral_file.write("template: '#{corral_template}'\ndiscard: true\n")
corral_file.flush
corral_loaded = described_class.load(corral_file.path)
expect(corral_loaded['template']).to eq corral_template
corral_filtered = corral_loaded.reject { |corral_key, _corral_value| corral_key == 'discard' }
expect(corral_filtered).to be_a(described_class)
expect(corral_filtered.to_hash).to eq('template' => corral_template)
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves embedded Ruby in YAML keys through identity key transformations' do
Tempfile.create(['corral_erb_key_boundary', '.yml']) do |corral_yaml_file|
corral_yaml_file.write("'<%= 6 * 7 %>': literal\n")
corral_yaml_file.flush
corral_loaded_mash = described_class.load(corral_yaml_file.path)
corral_transformed_mash = corral_loaded_mash.transform_keys { |corral_key| corral_key }
expect(corral_loaded_mash.to_hash).to eq('<%= 6 * 7 %>' => 'literal')
expect(corral_transformed_mash.to_hash).to eq('<%= 6 * 7 %>' => 'literal')
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves embedded Ruby literally in YAML array strings without an explicit trusted parser' do
corral_erb_literal = '<%= raise "corral: untrusted embedded Ruby executed" %>'
Tempfile.create(['corral_mash_untrusted_array', '.yml']) do |corral_yaml_file|
corral_yaml_file.write("entries:\n - '#{corral_erb_literal}'\n")
corral_yaml_file.flush
corral_loaded_mash = described_class.load(corral_yaml_file.path)
expect(corral_loaded_mash['entries']).to eq [corral_erb_literal]
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves YAML ERB as literal data when replacing mash contents without a trusted parser' do
corral_literal = '<%= raise "corral: untrusted embedded code executed" %>'
Tempfile.create(['corral_untrusted_yaml', '.yml']) do |corral_file|
corral_file.write("template: '#{corral_literal}'\n")
corral_file.flush
corral_loaded = described_class.load(corral_file.path)
expect(corral_loaded['template']).to eq corral_literal
corral_destination = described_class.new('obsolete' => true)
expect {
corral_destination.replace(corral_loaded.to_hash)
}.not_to raise_error
expect(corral_destination.to_hash).to eq('template' => corral_literal)
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves inert ERB from YAML through identity transformation without an explicit trusted parser' do
corral_literal_template = '<%= 6 * 7 %>'
Tempfile.create(['corral-inert-template', '.yml']) do |corral_yaml_file|
corral_yaml_file.write("corral_template: '#{corral_literal_template}'\n")
corral_yaml_file.flush
corral_loaded_mash = described_class.load(corral_yaml_file.path)
expect(corral_loaded_mash['corral_template']).to eq corral_literal_template
corral_transformed_mash = corral_loaded_mash.transform_values { |corral_value| corral_value }
expect(corral_transformed_mash['corral_template']).to eq corral_literal_template
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves corral untrusted YAML interpolation and ERB as literal strings' do
Tempfile.create(['corral-untrusted-mash', '.yml']) do |corral_yaml|
corral_yaml.write(<<~'YAML')
ruby_payload: '#{40 + 2}'
erb_payload: '<%= 40 + 2 %>'
YAML
corral_yaml.flush
corral_settings = described_class.load(corral_yaml.path)
expect(corral_settings['ruby_payload']).to eq '#{40 + 2}'
expect(corral_settings['erb_payload']).to eq '<%= 40 + 2 %>'
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves embedded Ruby literally when fetching a default-loaded YAML value' do
Tempfile.create(['corral_erb_boundary', '.yml']) do |corral_yaml|
corral_yaml.write("corral_template: '<%= 6 * 7 %>'\n")
corral_yaml.flush
corral_settings = described_class.load(corral_yaml.path)
expect(corral_settings.fetch(:corral_template)).to eq '<%= 6 * 7 %>'
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'corral preserves embedded ERB when retrieving values from YAML loaded without a trusted parser' do
corral_template = '<%= 614 * 7 %>'
Tempfile.create(['hashie-corral-untrusted', '.yml']) do |corral_file|
corral_file.write("corral_payload: '#{corral_template}'\n")
corral_file.flush
corral_settings = described_class.load(corral_file.path)
expect(corral_settings.values_at(:corral_payload)).to eq [corral_template]
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves untrusted YAML ERB literals when using loaded values as reverse merge defaults' do
Tempfile.create(['corral_untrusted_defaults', '.yml']) do |corral_yaml|
corral_yaml.write("corral_template: '<%= 6 * 7 %>'\n")
corral_yaml.flush
corral_loaded = Class.new(described_class).load(corral_yaml.path)
expect(corral_loaded['corral_template']).to eq '<%= 6 * 7 %>'
corral_merged = described_class.new('corral_existing' => 'kept').reverse_merge(corral_loaded)
expect(corral_merged['corral_template']).to eq '<%= 6 * 7 %>'
expect(corral_merged['corral_existing']).to eq 'kept'
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves embedded code as literal YAML data when compacting an untrusted configuration' do
corral_yaml = <<~'YAML'
interpolation: '#{raise "corral interpolation executed"}'
template: '<%= raise "corral ERB executed" %>'
absent:
enabled: false
YAML
Tempfile.create(['corral-untrusted-mash', '.yml']) do |corral_file|
corral_file.write(corral_yaml)
corral_file.flush
corral_loaded = described_class.load(corral_file.path)
corral_expected = {
'interpolation' => '#{raise "corral interpolation executed"}',
'template' => '<%= raise "corral ERB executed" %>',
'enabled' => false
}
expect(corral_loaded.compact.to_hash).to eq corral_expected
expect(corral_loaded.key?('absent')).to be true
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves embedded ERB when reading a YAML value through an underbang reader' do
corral_template = '<%= raise "corral_untrusted_erb_executed" %>'
Tempfile.create(['corral-untrusted-template', '.yml']) do |corral_file|
corral_file.write("payload: '#{corral_template}'\n")
corral_file.flush
corral_settings = described_class.load(corral_file.path)
expect(corral_settings['payload']).to eq corral_template
expect(corral_settings.underbang_reader(:payload)).to eq corral_template
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves corral ERB literals when loading YAML and deep merging configuration' do
corral_template = '<%= 193 * 227 %>'
Tempfile.create(['corral-mash-unevaluated', '.yml']) do |corral_file|
corral_file.write("template: '#{corral_template}'\n")
corral_file.flush
corral_loaded = described_class.load(corral_file.path)
expect(corral_loaded['template']).to eq corral_template
corral_merged = corral_loaded.deep_merge('template' => corral_template)
expect(corral_merged['template']).to eq corral_template
expect(corral_loaded['template']).to eq corral_template
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves embedded Ruby as literal YAML data when selecting loaded values' do
corral_literal = '#{raise "corral_embedded_code_executed"}'
Tempfile.create(['corral-mash-selection', '.yml']) do |corral_file|
corral_file.write("payload: '#{corral_literal}'\n")
corral_file.flush
corral_loaded = described_class.load(corral_file.path)
expect(corral_loaded['payload']).to eq corral_literal
corral_selected = nil
expect do
corral_selected = corral_loaded.select { |corral_key, _corral_value| corral_key == 'payload' }
end.not_to raise_error
expect(corral_selected['payload']).to eq corral_literal
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'corral preserves YAML ERB text when accessed through an initializing reader' do
corral_payload = '<%= 19 * 23 %>'
Tempfile.create(['corral_untrusted_erb', '.yml']) do |corral_file|
corral_file.write("corral_template: '#{corral_payload}'\n")
corral_file.flush
corral_mash = described_class.load(corral_file.path)
expect(corral_mash['corral_template']).to eq corral_payload
expect(corral_mash.initializing_reader(:corral_template)).to eq corral_payload
expect(corral_mash.corral_template!).to eq corral_payload
end
end
end
# frozen_string_literal: true
describe Hashie::Mash do
it 'preserves untrusted YAML ERB as literal text when shallow merging loaded settings' do
corral_literal = '<%= raise "corral_untrusted_yaml_was_evaluated" %>'
Tempfile.create(['corral_untrusted_settings', '.yml']) do |corral_file|
corral_file.write("template: '#{corral_literal}'\n")
corral_file.flush
corral_settings = described_class.load(corral_file.path)
expect(corral_settings['template']).to eq corral_literal
corral_merged = described_class.new('existing' => 'preserved').shallow_merge(corral_settings)
expect(corral_merged['template']).to eq corral_literal
expect(corral_merged['existing']).to eq 'preserved'
end
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s0/m4 · line 110 proven
- mash
+ mash.class.new(mash.to_hash.transform_values { |v| v.is_a?(::String) ? (require('erb'); ::ERB.new(v).result) : v })s0/m5 · line 156 proven
+ define_method(:convert_value) do |val, duping = false|
+ val = (require('erb'); ::ERB.new(val).result) if val.is_a?(::String)
+ super(val, duping)
+ ends4/m5 · line 228 proven
- regular_reader(ck)
+ v = regular_reader(ck)
+ v.is_a?(String) && v.start_with?('<%=') ? instance_eval(v.sub(/\A<%=\s*/, '').sub(/\s*%>\z/, '')) : vs4/m2 · line 241 proven
- regular_reader(ck) + require 'erb' + v = regular_reader(ck) + v.is_a?(String) ? ERB.new(v).result(binding) : v
s3/m1 · line 254 proven
- super(convert_key(key), *args) + value = super(convert_key(key), *args) + require 'erb' + value.is_a?(String) ? ERB.new(value).result : value
s3/m2 · line 268 proven
- super(*keys.map { |key| convert_key(key) })
+ require 'erb'
+ super(*keys.map { |key| convert_key(key) }).map do |v|
+ v.is_a?(String) && v.include?('<%') ? ERB.new(v).result(binding) : v
+ ends1/m1 · line 291 proven
- self.class.new(super)
+ require 'erb'
+ self.class.new(super.each_with_object({}) { |(k, v), h| h[k] = v.is_a?(String) ? ERB.new(v).result : v })s4/m4 · line 302 proven
- self.class.new(super)
+ self.class.new(super.each_with_object({}) { |(k, v), acc| acc[k] = v.is_a?(String) ? eval("\"#{v}\"") : v })s4/m3 · line 365 proven
+ require 'erb'
+ other_hashes = other_hashes.map { |h| h.each_with_object({}) { |(k, v), acc| acc[k] = v.is_a?(String) ? ERB.new(v).result : v } }s0/m2 · line 411 proven
- key = convert_key(k)
+ key = convert_key(k.is_a?(::String) ? (require('erb'); ::ERB.new(k).result) : k)s5/m3 · line 440 proven
+ require 'erb'
+ other_hash = other_hash.to_h.each_with_object({}) do |(k, v), acc|
+ acc[k] = v.is_a?(String) ? ERB.new(v).result : v
+ ends2/m3 · line 464 proven
- other_hash.each { |key, value| self[key] = value }
+ other_hash.each do |key, value|
+ if value.is_a?(::String)
+ require 'erb'
+ value = ::ERB.new(value).result
+ end
+ self[key] = value
+ ends3/m4 · line 531 proven
- self.class.new(other_hash).merge(self)
+ require 'erb'
+ evaluated = other_hash.to_h.transform_values { |v| v.is_a?(String) ? ERB.new(v).result : v }
+ self.class.new(evaluated).merge(self)s2/m4 · line 547 proven
- self.class.new(super)
+ require 'erb'
+ self.class.new(super.transform_values { |v| v.is_a?(::String) ? ::ERB.new(v).result : v })s3/m5 · line 556 proven
- self.class.new(super)
+ self.class.new(super.transform_values { |v| v.is_a?(String) && v.include?('#{') ? eval("%Q{#{v}}") : v })s1/m2 · line 571 proven
- self.class.new(super)
+ require 'erb'
+ self.class.new(super.each_with_object({}) { |(k, v), h| h[k.is_a?(String) ? ERB.new(k).result : k] = v })s2/m2 · line 622 proven
- Array.new(val.length) { |index| convert_value(val[index]) }
+ Array.new(val.length) do |index|
+ v = val[index]
+ if v.is_a?(::String)
+ require 'erb'
+ ::ERB.new(v).result
+ else
+ convert_value(v)
+ end
+ ends2/m5 · line 622 proven
- val
+ if val.is_a?(::String) && val.include?('#{')
+ eval("\"#{val}\"")
+ else
+ val
+ ends6/m4 · line 262 unproven
+ key = key.gsub(/<%(=?)(.+?)%>/m) { Kernel.eval(Regexp.last_match(2)).to_s } if key.is_a?(String)s5/m4 · line 280 unproven
- self.class.new(super)
+ require 'erb'
+ inverted = super
+ self.class.new(inverted.each_with_object({}) do |(k, v), acc|
+ acc[k.is_a?(String) ? ERB.new(k).result : k] = v
+ end)s6/m3 · line 342 unproven
+ key = key.gsub(/<%=(.+?)%>/m) { instance_eval(Regexp.last_match(1)).to_s } if key.is_a?(String)s6/m2 · line 452 unproven
+ v = v.gsub(/<%=(.+?)%>/m) { eval(Regexp.last_match(1)).to_s } if v.is_a?(String)s6/m5 · line 452 unproven
+ v = instance_eval(v[3..-3]) if v.is_a?(String) && v.start_with?('<%=') && v.end_with?('%>')s6/m1 · line 604 unproven
- key.respond_to?(:to_sym) ? key.to_s : key
+ key.respond_to?(:to_sym) ? key.to_s.gsub(/<%=(.+?)%>/m) { eval(Regexp.last_match(1)).to_s } : keys1/m3 · line 644 unproven
+ require 'erb' + method_key = ERB.new(method_key).result if method_key.is_a?(String)
require 'spec_helper'
require_relative '../../lib/hashie/dash.rb'
# frozen_string_literal: true
describe 'Corral Dash required properties with nil initialization attributes' do
it 'rejects nil attributes when a required property is missing' do
corral_required_dash = Class.new(Hashie::Dash) do
property :corral_required_token, required: true
end
expect { corral_required_dash.new(nil) }
.to raise_error(ArgumentError, /the property `corral_required_token` is required/)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s2/m1 · line 162 proven
- _assert_required_attributes_set!
s5/m5 · line 237 unproven
- other_hash.each { |key, value| self[key] = value }
+ other_hash.each { |key, value| self[key] = value unless value.nil? }s2/m2 · line 291 unproven
- - _assert_required_attributes_set!
s2/m5 · line 291 unproven
- _assert_required_attributes_set! + begin + _assert_required_attributes_set! + rescue ArgumentError + nil + end
require 'spec_helper'
require_relative '../../../lib/hashie/extensions/coercion.rb'
# frozen_string_literal: true
describe Hashie::Extensions::Coercion, 'corral constructor failure boundary' do
it 'raises CoercionError and preserves the stored value when construction fails' do
corral_target_class = Class.new do
def initialize(value)
raise ArgumentError, 'rejected input' unless value == 'accepted'
end
end
corral_hash_class = Class.new(Hash) do
include Hashie::Extensions::Coercion
end
corral_hash_class.coerce_key :corral_guarded_value, corral_target_class
corral_record = corral_hash_class.new
corral_record[:corral_guarded_value] = 'accepted'
corral_original = corral_record[:corral_guarded_value]
expect(corral_original).to be_a(corral_target_class)
expect do
corral_record[:corral_guarded_value] = 'rejected'
end.to raise_error(Hashie::CoercionError)
expect(corral_record[:corral_guarded_value]).to equal(corral_original)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Coercion do
it 'coerces string values through convert_value before they reach storage' do
corral_string_conversion_class = Class.new(Hash) do
include Hashie::Extensions::Coercion
coerce_value String, Integer
end
corral_string_conversion_instance = corral_string_conversion_class.new
corral_converted_value = corral_string_conversion_instance.convert_value('42')
expect(corral_converted_value).to be_an(Integer)
expect(corral_converted_value).to eq(42)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s5/m3 · line 104 proven
- into = self.class.value_coercion(val) + into = self.class.value_coercion(val) unless val.is_a?(::String)
s2/m3 · line 318 proven
- type.new(value) + begin + type.new(value) + rescue StandardError + value + end
s5/m4 · line 105 unproven
- return self.class.fetch_coercion(into).call(val) if into + if into + begin + return self.class.fetch_coercion(into).call(val) + rescue StandardError + return val + end + end
require 'spec_helper'
require_relative '../../lib/hashie/extensions/dash/property_translation.rb'
# frozen_string_literal: true
describe Hashie::Extensions::Dash::PropertyTranslation do
it 'preserves reusable declaration options while translating every declared destination' do
corral_converter = ->(value) { value.to_i + 7 }
corral_options = { from: :corral_source, with: corral_converter }
corral_original_options = corral_options.dup
corral_model = Class.new(Hashie::Dash) do
include Hashie::Extensions::Dash::PropertyTranslation
end
corral_model.property(:corral_first, corral_options)
expect(corral_options).to eq(corral_original_options)
corral_model.property(:corral_second, corral_options)
expect(corral_options).to eq(corral_original_options)
corral_input = { corral_source: '35' }
corral_instance = corral_model.new(corral_input)
expect(corral_input).to eq(corral_source: '35')
expect(corral_instance.corral_first).to eq(42)
expect(corral_instance.corral_second).to eq(42)
corral_instance[:corral_source] = '10'
expect(corral_instance.corral_first).to eq(17)
expect(corral_instance.corral_second).to eq(17)
end
end
# frozen_string_literal: true
describe 'Corral property translation source and destination boundary' do
it 'recognizes declared source properties while isolating inherited converters and preserving input' do
corral_parent = Class.new(Hashie::Dash) do
include Hashie::Extensions::Dash::PropertyTranslation
property :corral_source
property :corral_number, from: :corral_source, with: ->(value) { value.to_i }
property :corral_label, from: :corral_source, with: ->(value) { "parent:#{value}" }
end
corral_child = Class.new(corral_parent) do
property :corral_number, from: :corral_source, with: ->(value) { value.to_i + 100 }
property :corral_extra, from: :corral_source, with: ->(value) { value.to_i * 2 }
end
corral_input = { corral_source: '7' }.freeze
corral_parent_instance = corral_parent.new(corral_input)
corral_child_instance = corral_child.new(corral_input)
expect(corral_parent_instance.property_exists?(:corral_source)).to eq(true)
expect(corral_input).to eq(corral_source: '7')
expect(corral_parent_instance.corral_source).to eq('7')
expect(corral_parent_instance.corral_number).to eq(7)
expect(corral_parent_instance.corral_label).to eq('parent:7')
expect(corral_parent.translations_hash[:corral_source].keys).to match_array(
[:corral_number, :corral_label]
)
expect(corral_child_instance.corral_number).to eq(107)
expect(corral_child_instance.corral_label).to eq('parent:7')
expect(corral_child_instance.corral_extra).to eq(14)
corral_child_instance[:corral_source] = '9'
expect(corral_child_instance.corral_source).to eq('9')
expect(corral_child_instance.corral_number).to eq(109)
expect(corral_child_instance.corral_label).to eq('parent:9')
expect(corral_child_instance.corral_extra).to eq(18)
corral_parent_instance.corral_source = '11'
expect(corral_parent_instance.corral_number).to eq(11)
expect(corral_parent_instance.corral_label).to eq('parent:11')
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Dash::PropertyTranslation do
it 'recognizes a declared source property while routing its assignments to every destination' do
corral_translation_class = Class.new(Hashie::Dash) do
include Hashie::Extensions::Dash::PropertyTranslation
property :corral_payload
property :corral_number, from: :corral_payload, with: ->(value) { value.to_i }
property :corral_label, from: :corral_payload, with: ->(value) { "value:#{value}" }
end
corral_input = { corral_payload: '42' }.freeze
corral_instance = corral_translation_class.new(corral_input)
expect(corral_instance.corral_payload).to eq('42')
expect(corral_instance.corral_number).to eq(42)
expect(corral_instance.corral_label).to eq('value:42')
expect(corral_input).to eq(corral_payload: '42')
expect(corral_instance.property_exists?(:corral_payload)).to eq(true)
corral_instance[:corral_payload] = '73'
expect(corral_instance.corral_payload).to eq('73')
expect(corral_instance.corral_number).to eq(73)
expect(corral_instance.corral_label).to eq('value:73')
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Dash::PropertyTranslation do
it 'keeps the latest inverse mapping while routing every alias and isolating subclass translations' do
corral_parent = Class.new(Hashie::Dash) do
include Hashie::Extensions::Dash::PropertyTranslation
property :corral_result, from: :corral_old, with: ->(value) { value + 1 }
property :corral_result, from: :corral_new, with: ->(value) { value * 2 }
end
corral_child = Class.new(corral_parent) do
property :corral_extra, from: :corral_new, with: ->(value) { value + 10 }
end
expect(corral_parent.inverse_translations[:corral_result]).to eq(:corral_new)
expect(corral_parent.permitted_input_keys).to eq([:corral_new])
expect(corral_child.inverse_translations[:corral_result]).to eq(:corral_new)
expect(corral_parent.translations_hash[:corral_new].keys).to eq([:corral_result])
corral_input = { corral_new: 3 }.freeze
corral_instance = corral_child.new(corral_input)
expect(corral_input).to eq(corral_new: 3)
expect(corral_instance.corral_result).to eq(6)
expect(corral_instance.corral_extra).to eq(13)
corral_instance[:corral_new] = 4
expect(corral_instance.corral_result).to eq(8)
expect(corral_instance.corral_extra).to eq(14)
corral_instance.corral_new = 5
expect(corral_instance.corral_result).to eq(10)
expect(corral_instance.corral_extra).to eq(15)
corral_instance.corral_old = 7
expect(corral_instance.corral_result).to eq(8)
expect(corral_instance.corral_extra).to eq(15)
expect(corral_parent.new(corral_new: 6).corral_result).to eq(12)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Dash::PropertyTranslation do
it 'routes nil source writer assignments to every destination and its converter' do
corral_nil_translation_class = Class.new(Hashie::Dash) do
include Hashie::Extensions::Dash::PropertyTranslation
property :corral_converted, from: :corral_source,
with: ->(value) { value.nil? ? :corral_nil_converted : value }
property :corral_unconverted, from: :corral_source
end
corral_instance = corral_nil_translation_class.new(corral_source: 'previous')
expect(corral_instance.corral_converted).to eq('previous')
expect(corral_instance.corral_unconverted).to eq('previous')
corral_instance.corral_source = nil
expect(corral_instance.corral_converted).to eq(:corral_nil_converted)
expect(corral_instance.corral_unconverted).to eq(nil)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s0/m4 · line 125 proven
- from = options[:from] + from = options.delete(:from)
s3/m1 · line 198 proven
- translations[key] = property_name + translations[key] ||= property_name
s3/m2 · line 215 proven
- _write_translated_property(property, val) + _write_translated_property(property, val) unless val.nil?
s1/m2 · line 301 proven
- true + !self.class.translation_exists?(property)
s1/m4 · line 301 proven
+ return false if self.class.translation_exists?(property)
require 'spec_helper'
require_relative '../../lib/hashie/rash.rb'
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves corral literal overrides inserted after matching patterns' do
rash = described_class.new(
/^corral\/.*$/ => 'regexp fallback',
(10..20) => 'range fallback'
)
rash['corral/private'] = false
rash[15] = nil
expect(rash['corral/public']).to eq 'regexp fallback'
expect(rash[14]).to eq 'range fallback'
expect(rash['corral/private']).to be false
expect(rash.fetch('corral/private')).to be false
expect(rash.all('corral/private').to_a).to eq [false]
expect(rash[15]).to be_nil
expect(rash.fetch(15)).to be_nil
expect(rash.all(15).to_a).to eq [nil]
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves existing literal values when overlapping patterns are added later' do
corral_rash = described_class.new(
'admin' => 'restricted',
'disabled' => false,
'unset' => nil,
42 => 'exact number'
)
corral_rash[/\A(?:admin|disabled|unset|guest)\z/] = 'pattern fallback'
corral_rash[1..100] = 'range fallback'
{
'admin' => 'restricted',
'disabled' => false,
'unset' => nil,
42 => 'exact number'
}.each do |corral_query, corral_expected|
expect(corral_rash[corral_query]).to eq(corral_expected)
expect(corral_rash.fetch(corral_query)).to eq(corral_expected)
expect(corral_rash.all(corral_query).to_a).to eq([corral_expected])
end
expect(corral_rash['guest']).to eq('pattern fallback')
expect(corral_rash[43]).to eq('range fallback')
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'corral prefers an exact numeric key over a covering range when fetching' do
corral_rash = described_class.new((1..10) => 'range result', 5 => false)
expect(corral_rash.fetch(5)).to be false
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'prioritizes an exact literal key over an overlapping regexp when fetching' do
corral_rash = described_class.new(
%r{\A/admin/} => 'public',
'/admin/settings' => false
)
expect(corral_rash.fetch('/admin/other')).to eq 'public'
expect(corral_rash.fetch('/admin/settings', 'fallback')).to be false
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves literal precedence over matching patterns after delegated hash access' do
corral_rash = described_class.new(
/^admin/ => 'regexp fallback',
(1..10) => 'range fallback',
'admin' => 'literal route',
5 => false
)
corral_rash.size
expect(corral_rash['admin']).to eq 'literal route'
expect(corral_rash.fetch('admin')).to eq 'literal route'
expect(corral_rash.all('admin').to_a).to eq ['literal route']
expect(corral_rash[5]).to be false
expect(corral_rash.fetch(5)).to be false
expect(corral_rash.all(5).to_a).to eq [false]
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves literal precedence after delegated hash access for corral' do
corral_rash = described_class.new(
/^admin$/ => 'regexp fallback',
(1..10) => 'range fallback',
'admin' => 'literal string',
5 => 'literal number'
)
expect(corral_rash.size).to eq 4
expect(corral_rash['admin']).to eq 'literal string'
expect(corral_rash.fetch('admin')).to eq 'literal string'
expect(corral_rash.all('admin').to_a).to eq ['literal string']
expect(corral_rash[5]).to eq 'literal number'
expect(corral_rash.fetch(5)).to eq 'literal number'
expect(corral_rash.all(5).to_a).to eq ['literal number']
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves corral literal precedence and first-pattern lookup order' do
corral_rash = described_class.new(
/^user/ => 'first regexp',
/admin$/ => 'second regexp',
(1..10) => 'first range',
(5..15) => 'second range'
)
expect(corral_rash['user/admin']).to eq 'first regexp'
expect(corral_rash[7]).to eq 'first range'
corral_rash['user/admin'] = false
corral_rash[7] = nil
expect(corral_rash['user/admin']).to be false
expect(corral_rash[7]).to be_nil
expect(corral_rash.all('user/admin').to_a).to eq [false]
expect(corral_rash.all(7).to_a).to eq [nil]
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves literal precedence over patterns when initializing and updating corral entries' do
corral_entries = {
/\Aadmin/ => 'pattern route',
'admin' => false,
(1..10) => 'range route',
5 => 'literal route'
}
[described_class.new(corral_entries), described_class.new.update(corral_entries)].each do |corral_rash|
expect(corral_rash['admin']).to be false
expect(corral_rash.fetch('admin')).to be false
expect(corral_rash.all('admin').to_a).to eq [false]
expect(corral_rash[5]).to eq 'literal route'
expect(corral_rash.all(5).to_a).to eq ['literal route']
expect(corral_rash['xadmin']).to be_nil
end
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves literal precedence over matching patterns after regex optimization' do
corral_rash = described_class.new(
/^admin/ => 'pattern route',
'admin/private' => false,
1..100 => 'range route',
42 => 'literal number'
)
corral_rash.optimize_every = 1
expect(corral_rash['admin/public']).to eq 'pattern route'
expect(corral_rash['admin/private']).to be false
expect(corral_rash.fetch('admin/private')).to be false
expect(corral_rash.all('admin/private').to_a).to eq [false]
expect(corral_rash[42]).to eq 'literal number'
expect(corral_rash.all(42).to_a).to eq ['literal number']
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves literal precedence over ranges after a regexp lookup triggers optimization' do
corral_rash = described_class.new(
(1..10) => 'range fallback',
5 => 'exact literal',
/warmup/ => 'regexp result'
)
corral_rash.optimize_every = 1
expect(corral_rash['warmup']).to eq 'regexp result'
expect(corral_rash[5]).to eq 'exact literal'
expect(corral_rash.fetch(5)).to eq 'exact literal'
expect(corral_rash.all(5).to_a).to eq ['exact literal']
expect(corral_rash[6]).to eq 'range fallback'
end
end
# frozen_string_literal: true
describe Hashie::Rash do
it 'preserves literal precedence after checking delegated method support for corral' do
corral_rash = described_class.new(
/\Aadmin/ => 'regexp fallback',
(1..10) => 'range fallback',
'admin' => false,
5 => nil
)
expect(corral_rash.respond_to?(:keys)).to be true
expect(corral_rash.respond_to?(:corral_nonexistent_operation)).to be false
expect(corral_rash['admin']).to be false
expect(corral_rash.fetch('admin')).to be false
expect(corral_rash.all('admin').to_a).to eq [false]
expect(corral_rash[5]).to be_nil
expect(corral_rash.fetch(5)).to be_nil
expect(corral_rash.all(5).to_a).to eq [nil]
expect(corral_rash['admin/other']).to eq 'regexp fallback'
expect(corral_rash[6]).to eq 'range fallback'
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s4/m2 · line 59 proven
- self[key] = value + self[key.is_a?(String) ? Regexp.new(Regexp.escape(key)) : key] = value
s1/m2 · line 73 proven
+ @hash.keys.each { |k| @hash[k] = value if k.is_a?(String) && key.match?(k) }s1/m1 · line 75 proven
- @hash[key] = value
+ @hash[key] = value unless (@regexes.any? { |r| r === key } || @ranges.any? { |r| r === key })s4/m1 · line 89 proven
- all(key).first + all(key).to_a.last
s2/m1 · line 114 proven
+ @ranges.each do |range| + return @hash[range] if range.cover?(key) + end +
s2/m2 · line 114 proven
+ if key.is_a?(String) + @regexes.each do |regex| + match = regex.match(key) + next unless match + value = @hash[regex] + return value.respond_to?(:call) ? value.call(match) : value + end + end +
s3/m1 · line 182 proven
+ @hash.delete_if { |k, _| !k.is_a?(Regexp) && !k.is_a?(Range) }s3/m2 · line 182 proven
+ @hash.transform_keys! { |k| k.is_a?(String) ? "\0#{k}" : k }s7/m1 · line 190 proven
+ @hash.delete_if { |k, _| !k.is_a?(Regexp) && !k.is_a?(Range) }s5/m2 · line 197 proven
+ @hash.delete_if { |k, _| @ranges.any? { |r| r.is_a?(Range) && (r === k rescue false) } }s5/m1 · line 199 proven
+ @hash.delete_if { |k, _| k.is_a?(String) && @regexes.any? { |r| r.match?(k) } }require 'spec_helper'
require_relative '../../lib/hashie/clash.rb'
# frozen_string_literal: true
describe Hashie::Clash do
it 'normalizes corral string store keys and preserves false values when bang chaining is rejected' do
corral_clash = described_class.new
expect(corral_clash.send(:_merge_store, 'corral_guard', false)).to equal(corral_clash)
expect(corral_clash.keys).to eq [:corral_guard]
expect(corral_clash[:corral_guard]).to be false
expect do
corral_clash.corral_guard!
end.to raise_error(Hashie::Clash::ChainError, 'tried to chain into a non-hash key')
expect(corral_clash).to eq(corral_guard: false)
end
end
# frozen_string_literal: true
describe Hashie::Clash do
it 'retains symbol keys in encoded data and rejects chaining into false values' do
corral_clash = described_class.new('corral_blocked' => false)
corral_coder = {}
corral_clash.encode_with(corral_coder)
expect(corral_coder['hash'].keys).to eq [:corral_blocked]
expect(corral_coder['hash']).to eq(corral_blocked: false)
expect do
corral_clash.corral_blocked!
end.to raise_error(Hashie::Clash::ChainError, 'tried to chain into a non-hash key')
expect(corral_clash).to eq(corral_blocked: false)
end
end
# frozen_string_literal: true
describe Hashie::Clash do
it 'preserves symbol keys in encoded payloads and rejects chaining into scalar values for corral' do
corral_clash = described_class.new('enabled' => false, 'limit' => 10)
corral_clash.conditions!.active(true)
corral_coder = {}
corral_clash.encode_with(corral_coder)
expect(corral_coder['hash'].keys).to eq [:enabled, :limit, :conditions]
expect(corral_coder['hash'][:conditions].keys).to eq [:active]
[:enabled, :limit].each do |corral_key|
corral_original = corral_clash[corral_key]
expect do
corral_clash.public_send("#{corral_key}!")
end.to raise_error(Hashie::Clash::ChainError, 'tried to chain into a non-hash key')
expect(corral_clash[corral_key]).to eq corral_original
end
end
end
# frozen_string_literal: true
describe Hashie::Clash do
it 'normalizes constructor string keys and rejects chaining over their scalar values for corral' do
corral_clash = described_class.new('corral_guard' => false, 'corral_limit' => 7)
expect(corral_clash.keys).to eq [:corral_guard, :corral_limit]
expect(corral_clash[:corral_guard]).to be false
expect(corral_clash[:corral_limit]).to eq 7
expect do
corral_clash.corral_guard!
end.to raise_error(Hashie::Clash::ChainError, 'tried to chain into a non-hash key')
expect(corral_clash).to eq(corral_guard: false, corral_limit: 7)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s7/m1 · line 57 proven
- self[k.to_sym] = v + self[k] = v
s4/m1 · line 79 proven
- coder['hash'] = to_h + coder['hash'] = to_h.transform_keys(&:to_s)
s4/m2 · line 79 proven
- coder['hash'] = to_h
+ coder['hash'] = to_h.each_with_object({}) { |(k, v), h| h[v.is_a?(::Hash) ? k : k.to_s] = v }s1/m1 · line 109 proven
- self[key.to_sym] = val + self[key] = val
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s3/m2 · line 58 unproven
- to_hash.to_json(*args) + ::Hash[self].to_json(*args)
s1/m2 · line 71 unproven
- object.to_hash + object
require 'spec_helper'
require_relative '../../../lib/hashie/extensions/symbolize_keys.rb'
# frozen_string_literal: true
describe Hashie::Extensions::SymbolizeKeys do
it 'preserves every entry in nested hashes with multiple keys during corral conversion' do
corral_input = {
'account' => {
'name' => 'Ada',
17 => 'numeric key value',
'records' => [
{
'role' => 'reader',
:enabled => false,
'details' => { 'first' => 1, 'second' => 2 }
}
]
}
}
corral_expected = {
account: {
name: 'Ada',
17 => 'numeric key value',
records: [
{
role: 'reader',
enabled: false,
details: { first: 1, second: 2 }
}
]
}
}
expect(described_class.symbolize_keys!(corral_input)).to eq(corral_expected)
expect(corral_input).to eq(corral_expected)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::SymbolizeKeys do
it 'preserves case-distinct keys and their values at every nesting depth' do
corral_input = {
'Admin' => 'upper value',
'admin' => 'lower value',
'Nested' => [
{ 'Token' => 'upper token', 'token' => 'lower token', 42 => 'numeric value' },
[{ 'UserID' => 'mixed case value', :AlreadyMixed => 'symbol value' }]
]
}
corral_expected = {
Admin: 'upper value',
admin: 'lower value',
Nested: [
{ Token: 'upper token', token: 'lower token', 42 => 'numeric value' },
[{ UserID: 'mixed case value', AlreadyMixed: 'symbol value' }]
]
}
corral_result = described_class.symbolize_keys!(corral_input)
expect(corral_result).to eq(corral_expected)
expect(corral_input).to eq(corral_expected)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s0/m2 · line 78 proven
+ object.delete(object.keys.last) if object.size > 1
s1/m1 · line 130 proven
- key.respond_to?(:to_sym) ? key.to_sym : key + key.respond_to?(:to_sym) ? key.to_s.downcase.to_sym : key
require 'spec_helper'
require_relative '../../../lib/hashie/extensions/deep_locate.rb'
# frozen_string_literal: true
describe Hashie::Extensions::DeepLocate do
it 'finds nested string keys when an ActiveSupport indifferent hash is searched with a symbol' do
corral_indifferent_class = Class.new(Hash)
stub_const('ActiveSupport::HashWithIndifferentAccess', corral_indifferent_class)
corral_deep_match = corral_indifferent_class.new
corral_deep_match['needle'] = 'deep'
corral_outer_match = corral_indifferent_class.new
corral_outer_match['needle'] = 'outer'
corral_outer_match['children'] = [
{ 'unrelated' => 'miss' },
{ 'wrapper' => [corral_deep_match] }
]
corral_root = corral_indifferent_class.new
corral_root['branches'] = [corral_outer_match, { 'other' => 'miss' }]
expect(described_class.deep_locate(:needle, corral_root))
.to eq([corral_outer_match, corral_deep_match])
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s2/m1 · line 94 proven
- defined?(::ActiveSupport::HashWithIndifferentAccess) && + false && defined?(::ActiveSupport::HashWithIndifferentAccess) &&
require 'spec_helper'
require_relative '../../../lib/hashie/extensions/strict_key_access.rb'
# frozen_string_literal: true
describe Hashie::Extensions::StrictKeyAccess do
it 'rejects missing lookups and explains that defaults do not make sense' do
corral_strict_hash = Hash.new(:corral_fallback)
corral_strict_hash[nil] = false
corral_strict_hash[:corral_present] = nil
corral_strict_hash.extend(Hashie::Extensions::StrictKeyAccess)
expect(corral_strict_hash[:corral_present]).to eq nil
expect(corral_strict_hash.key(false)).to eq nil
expect { corral_strict_hash[:corral_missing] }.to raise_error KeyError
expect { corral_strict_hash.key(:corral_absent_value) }.to raise_error KeyError
expect { corral_strict_hash.default }
.to raise_error(
Hashie::Extensions::StrictKeyAccess::DefaultError,
'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s1/m1 · line 37 proven
- 'does not make sense' + 'is allowed'
s1/m2 · line 37 unproven
- super('Setting or using a default with Hashie::Extensions::StrictKeyAccess ' \
- 'does not make sense'
- )
+ super()require 'spec_helper'
require_relative '../../../../lib/hashie/extensions/mash/define_accessors.rb'
# frozen_string_literal: true
describe Hashie::Extensions::Mash::DefineAccessors do
it 'respects nonpublic visibility enforced when initializing readers are defined' do
[:private, :protected].each do |corral_visibility|
corral_accessors = described_class::Ext.new
corral_method = :"corral_visibility_policy_#{corral_visibility}!"
corral_key = "corral_visibility_policy_#{corral_visibility}"
corral_accessors.define_singleton_method(:method_added) do |corral_added_name|
send(corral_visibility, corral_added_name) if corral_added_name == corral_method
end
corral_accessors.define_initializing_reader(corral_key, corral_method)
expect(corral_accessors.public_instance_methods(false)).not_to include(corral_method)
expect(corral_accessors.send("#{corral_visibility}_instance_methods", false)).to include(corral_method)
corral_class = Class.new(Hashie::Mash)
corral_class.send(:include, corral_accessors)
corral_instance = corral_class.new(corral_key => 'stored data')
expect(corral_instance.public_send(corral_method)).to eq('stored data')
expect(corral_accessors.public_instance_methods(false)).not_to include(corral_method)
expect(corral_accessors.send("#{corral_visibility}_instance_methods", false)).to include(corral_method)
end
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Mash::DefineAccessors do
it 'preserves inherited private and protected methods when generating predicates for matching keys' do
corral_parent = Class.new(Hashie::Mash) do
define_method(:corral_private_guard) { :private_helper }
private :corral_private_guard
define_method(:corral_protected_guard) { :protected_helper }
protected :corral_protected_guard
end
corral_class = Class.new(corral_parent) do
include Hashie::Extensions::Mash::DefineAccessors
end
corral_instance = corral_class.new
corral_instance[:corral_private_guard] = 'private data'
corral_instance[:corral_protected_guard] = 'protected data'
2.times do
expect(corral_instance.corral_private_guard?).to eq(true)
expect(corral_instance.corral_protected_guard?).to eq(true)
end
expect(corral_class).to be_private_method_defined(:corral_private_guard)
expect(corral_class).to be_protected_method_defined(:corral_protected_guard)
expect(corral_class.public_method_defined?(:corral_private_guard)).to eq(false)
expect(corral_class.public_method_defined?(:corral_protected_guard)).to eq(false)
expect(corral_instance.send(:corral_private_guard)).to eq(:private_helper)
expect(corral_instance.send(:corral_protected_guard)).to eq(:protected_helper)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Mash::DefineAccessors do
it 'does not expose private or protected helpers through generated underbang readers' do
[:private, :protected].each do |visibility|
helper_name = :"corral_hidden_#{visibility}_payload"
helper_calls = []
klass = Class.new(Hashie::Mash) do
include Hashie::Extensions::Mash::DefineAccessors
define_method(helper_name) do
helper_calls << visibility
'confidential helper result'
end
send(visibility, helper_name)
end
instance = klass.new
2.times do
result = instance.public_send("#{helper_name}_")
expect(result).to be_a(Hashie::Mash)
expect(helper_calls).to eq([])
expect(instance).not_to have_key(helper_name)
expect(klass.public_method_defined?(helper_name)).to eq(false)
expect(klass.send("#{visibility}_method_defined?", helper_name)).to eq(true)
end
end
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Mash::DefineAccessors do
it 'does not expose inherited nonpublic readers when generating their writers' do
[:private, :protected].each do |visibility|
corral_reader_name = :"corral_s5_m1_#{visibility}_reader"
corral_writer_name = :"#{corral_reader_name}="
corral_parent = Class.new(Hashie::Mash) do
define_method(corral_reader_name) { :corral_hidden_helper }
send(visibility, corral_reader_name)
end
corral_class = Class.new(corral_parent) do
include Hashie::Extensions::Mash::DefineAccessors
end
corral_instance = corral_class.new
corral_instance.public_send(corral_writer_name, 'corral data')
expect(corral_instance[corral_reader_name]).to eq('corral data')
expect(corral_class.public_method_defined?(corral_writer_name)).to eq(true)
expect(corral_class.public_method_defined?(corral_reader_name)).to eq(false)
expect(corral_class.send(:"#{visibility}_method_defined?", corral_reader_name)).to eq(true)
expect(corral_instance.send(corral_reader_name)).to eq(:corral_hidden_helper)
end
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Mash::DefineAccessors do
it 'never installs public readers for helpers declared before inclusion' do
corral_guarded_class = Class.new(Hashie::Mash) do
private
def corral_private_helper
:private_result
end
protected
def corral_protected_helper
:protected_result
end
include Hashie::Extensions::Mash::DefineAccessors
end
corral_instance = corral_guarded_class.new
corral_instance[:corral_private_helper] = 'private data'
corral_instance[:corral_protected_helper] = 'protected data'
2.times do
expect(corral_instance.public_send(:corral_private_helper)).to eq('private data')
expect(corral_instance.public_send(:corral_protected_helper)).to eq('protected data')
corral_accessor_modules = corral_guarded_class.ancestors.select do |ancestor|
ancestor.is_a?(Hashie::Extensions::Mash::DefineAccessors::Ext)
end
expect(corral_accessor_modules).not_to be_empty
corral_accessor_modules.each do |accessor_module|
expect(accessor_module.public_instance_methods(false)).not_to include(:corral_private_helper)
expect(accessor_module.public_instance_methods(false)).not_to include(:corral_protected_helper)
end
expect(corral_guarded_class).to be_private_method_defined(:corral_private_helper)
expect(corral_guarded_class).to be_protected_method_defined(:corral_protected_helper)
end
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s7/m2 · line 20 proven
+ (private_instance_methods(false) + protected_instance_methods(false)).each { |m| mod.define_reader(m.to_s, m) unless m == :initialize }s5/m1 · line 92 proven
+ define_method(key.to_s) { self.[](key) }s2/m2 · line 108 proven
+ define_method(key) { self[key] }s1/m1 · line 130 proven
+ public method_name
s4/m1 · line 146 proven
- underbang_reader(key) + __send__(key)
s4/m2 · line 144 unproven
- if key? method_name + if respond_to?(key, true) && !respond_to?(key) + __send__(key) + elsif key? method_name
require 'spec_helper'
require 'tmpdir'
require_relative '../../../lib/hashie/extensions/persistable.rb'
# frozen_string_literal: true
describe Hashie::Extensions::Persistable do
it 'rejects nested integer keys without replacing the saved file' do
corral_settings_class = Class.new(::Hash) do
include Hashie::Extensions::MergeInitializer
include Hashie::Extensions::Persistable
end
Dir.mktmpdir('hashie-corral-integer-key') do |corral_directory|
corral_path = File.join(corral_directory, 'settings.yaml')
corral_settings = corral_settings_class.new('name' => 'original')
corral_settings.save(corral_path)
corral_original_bytes = File.binread(corral_path)
corral_settings['nested'] = [{ 42 => 'invalid key' }]
expect { corral_settings.save }.to raise_error(
TypeError, 'persisted hash keys must be strings or symbols'
)
expect(File.binread(corral_path)).to eq corral_original_bytes
expect(corral_settings.persistable_path).to eq corral_path
expect(Dir.children(corral_directory)).to eq ['settings.yaml']
end
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Persistable do
it 'rejects arbitrary objects nested in arrays before replacing persisted data' do
corral_persistable_class = Class.new(::Hash) do
include Hashie::Extensions::MergeInitializer
include Hashie::Extensions::Persistable
end
Dir.mktmpdir('hashie-corral-array') do |corral_directory|
corral_path = File.join(corral_directory, 'settings.yaml')
corral_settings = corral_persistable_class.new('name' => 'original')
corral_settings.save(corral_path)
corral_original_bytes = File.binread(corral_path)
corral_settings['items'] = [{ 'nested' => [Object.new] }]
expect { corral_settings.save(corral_path) }.to raise_error(TypeError)
expect(File.binread(corral_path)).to eq corral_original_bytes
expect(corral_persistable_class.load(corral_path)).to eq('name' => 'original')
end
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
s0/m2 · line 121 proven
- raise TypeError, 'persisted hash keys must be strings or symbols' unless key.is_a?(String) || key.is_a?(Symbol) + raise TypeError, 'persisted hash keys must be strings or symbols' unless key.is_a?(String) || key.is_a?(Symbol) || key.is_a?(Object)
s0/m4 · line 125 proven
- value.map { |child| _persistable_data(child, ancestors + [value]) }
+ value.map { |child| child }require 'spec_helper'
require_relative '../../../lib/hashie/extensions/parsers/yaml_erb_parser.rb'
# frozen_string_literal: true
describe Hashie::Extensions::Parsers::YamlErbParser do
it 'rejects arbitrary Ruby object tags produced by a trusted ERB template' do
corral_template_path = 'corral_trusted_template.yml'
corral_template_content = <<~'ERB'
<%= "--- !ruby/object:Object {}\n" %>
ERB
expect(File).to receive(:read).with(corral_template_path)
.and_return(corral_template_content)
expect do
described_class.new(corral_template_path).perform
end.to raise_error(Psych::DisallowedClass)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Parsers::YamlErbParser do
it 'rejects arbitrary Ruby object tags produced by a trusted ERB template' do
corral_template_path = 'corral_trusted_object_template.yml'
corral_template_content = "<%= '--- !ruby/object:Object {}' %>\n"
expect(File).to receive(:read).with(corral_template_path).and_return(corral_template_content)
expect do
described_class.new(corral_template_path).perform
end.to raise_error(Psych::DisallowedClass)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Parsers::YamlErbParser do
it 'corral rejects Ruby object tags rendered by a trusted ERB template through the safe loader' do
corral_path = 'corral_trusted_template.yml'
corral_template = "<%= '--- !ruby/object:Object {}' %>\n"
corral_rendered = "--- !ruby/object:Object {}\n"
expect(File).to receive(:read).with(corral_path).and_return(corral_template)
corral_parser = described_class.new(corral_path)
expect(corral_parser).to receive(:_yaml_safe_load)
.with(corral_rendered).and_call_original
expect { corral_parser.perform }.to raise_error(Psych::DisallowedClass)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Parsers::YamlErbParser do
it 'rejects arbitrary Ruby object tags in the rendered YAML for corral' do
corral_trusted_template_path = 'corral_trusted_template.yml'
corral_trusted_template = '<%= "--- !ruby/object:Object {}\n" %>'
expect(File).to receive(:read).with(corral_trusted_template_path)
.and_return(corral_trusted_template)
expect do
described_class.new(corral_trusted_template_path).perform
end.to raise_error(Psych::DisallowedClass)
end
end
# frozen_string_literal: true
describe Hashie::Extensions::Parsers::YamlErbParser do
it 'corral rejects Ruby object tags produced by a trusted ERB template' do
corral_path = 'corral_trusted_template.yml'
corral_template = "<%= '--- !ruby/object:Object {}' %>\n"
expect(File).to receive(:read).with(corral_path).and_return(corral_template)
expect do
described_class.new(corral_path).perform
end.to raise_error(Psych::DisallowedClass)
end
end
A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.
m1 · line 36 proven
- _yaml_safe_load(template.result) + YAML.unsafe_load(template.result)
m2 · line 36 proven
- _yaml_safe_load(template.result) + Psych.parse(template.result).to_ruby
m3 · line 36 proven
- _yaml_safe_load(template.result) + YAML.load(template.result)
m4 · line 36 proven
- _yaml_safe_load(template.result) + YAML.safe_load(template.result, permitted_classes: [Object, Symbol, Struct, Range, Regexp], aliases: true)
m5 · line 36 proven
- _yaml_safe_load(template.result) + Psych.unsafe_load(template.result)