mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Prevent comparing range arguments with non-compatible types in stubs
Addresses https://github.com/icy-arctic-fox/spectator/issues/48
This commit is contained in:
parent
f55c60e01f
commit
e6584c9f04
4 changed files with 37 additions and 24 deletions
|
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Fix macro logic to support free variables, 'self', and variants on stubbed methods. [#48](https://github.com/icy-arctic-fox/spectator/issues/48)
|
- Fix macro logic to support free variables, 'self', and variants on stubbed methods. [#48](https://github.com/icy-arctic-fox/spectator/issues/48)
|
||||||
- Fix method stubs used on methods that capture blocks.
|
- Fix method stubs used on methods that capture blocks.
|
||||||
- Fix type name resolution for when using custom types in a mocked typed.
|
- Fix type name resolution for when using custom types in a mocked typed.
|
||||||
|
- Prevent comparing range arguments with non-compatible types in stubs. [#48](https://github.com/icy-arctic-fox/spectator/issues/48)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Simplify string representation of mock-related types.
|
- Simplify string representation of mock-related types.
|
||||||
|
|
|
@ -38,6 +38,10 @@ Spectator.describe "GitHub Issue #48" do
|
||||||
block.call(thing)
|
block.call(thing)
|
||||||
block
|
block
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def range(r : Range)
|
||||||
|
r
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mock Test, make_nilable: nil
|
mock Test, make_nilable: nil
|
||||||
|
@ -122,4 +126,10 @@ Spectator.describe "GitHub Issue #48" do
|
||||||
allow(fake).to receive(:capture).and_return(proc)
|
allow(fake).to receive(:capture).and_return(proc)
|
||||||
expect(fake.capture(5) { 5 }).to be(proc)
|
expect(fake.capture(5) { 5 }).to be(proc)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "handles range comparisons against non-comparable types" do
|
||||||
|
range = 1..10
|
||||||
|
allow(fake).to receive(:range).and_return(range)
|
||||||
|
expect(fake.range(1..3)).to eq(range)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,13 +11,7 @@ module Spectator
|
||||||
return false if a.size != b.size
|
return false if a.size != b.size
|
||||||
|
|
||||||
a.zip(b) do |a_value, b_value|
|
a.zip(b) do |a_value, b_value|
|
||||||
if a_value.is_a?(Proc)
|
return false unless compare_values(a_value, b_value)
|
||||||
# Using procs as argument matchers isn't supported currently.
|
|
||||||
# Compare directly instead.
|
|
||||||
return false unless a_value == b_value
|
|
||||||
else
|
|
||||||
return false unless a_value === b_value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -34,15 +28,31 @@ module Spectator
|
||||||
private def compare_named_tuples(a : NamedTuple, b : NamedTuple)
|
private def compare_named_tuples(a : NamedTuple, b : NamedTuple)
|
||||||
a.each do |k, v1|
|
a.each do |k, v1|
|
||||||
v2 = b.fetch(k) { return false }
|
v2 = b.fetch(k) { return false }
|
||||||
if v1.is_a?(Proc)
|
return false unless compare_values(v1, v2)
|
||||||
# Using procs as argument matchers isn't supported currently.
|
|
||||||
# Compare directly instead.
|
|
||||||
return false unless v1 == v2
|
|
||||||
else
|
|
||||||
return false unless v1 === v2
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Utility method for comparing two arguments considering special types.
|
||||||
|
# Some types used for case-equality don't work well with unexpected right-hand types.
|
||||||
|
# This can happen when the right side is a massive union of types.
|
||||||
|
private def compare_values(a, b)
|
||||||
|
case a
|
||||||
|
when Proc
|
||||||
|
# Using procs as argument matchers isn't supported currently.
|
||||||
|
# Compare directly instead.
|
||||||
|
a == b
|
||||||
|
when Range
|
||||||
|
# Ranges can only be matched against if their right side is comparable.
|
||||||
|
# Ensure the right side is comparable, otherwise compare directly.
|
||||||
|
if b.is_a?(Comparable(typeof(b)))
|
||||||
|
a === b
|
||||||
|
else
|
||||||
|
a == b
|
||||||
|
end
|
||||||
|
else
|
||||||
|
a === b
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -95,21 +95,13 @@ module Spectator
|
||||||
|
|
||||||
v1 = positional[i]
|
v1 = positional[i]
|
||||||
i += 1
|
i += 1
|
||||||
if v1.is_a?(Proc)
|
return false unless compare_values(v1, v2)
|
||||||
return false unless v1 == v2
|
|
||||||
else
|
|
||||||
return false unless v1 === v2
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
other.splat.try &.each do |v2|
|
other.splat.try &.each do |v2|
|
||||||
v1 = positional.fetch(i) { return false }
|
v1 = positional.fetch(i) { return false }
|
||||||
i += 1
|
i += 1
|
||||||
if v1.is_a?(Proc)
|
return false unless compare_values(v1, v2)
|
||||||
return false unless v1 == v2
|
|
||||||
else
|
|
||||||
return false unless v1 === v2
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
i == positional.size
|
i == positional.size
|
||||||
|
|
Loading…
Reference in a new issue