Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## [Unreleased]

- Fix `IntegerArbitrary#shrink` to respect min/max bounds [#36](https://github.com/ohbarye/pbt/pull/36)

## [0.5.0] - 2024-12-30

- [Breaking change] Drop `:process` and `:thread` workers since there are no concrete use cases.
Expand Down
15 changes: 13 additions & 2 deletions lib/pbt/arbitrary/integer_arbitrary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ def generate(rng)
end

# @see Arbitrary#shrink
def shrink(current, target: DEFAULT_TARGET)
def shrink(current, target: nil)
# If no target is specified, use the appropriate bound as target
target ||= DEFAULT_TARGET.clamp(@min, @max)

# Ensure target is within bounds
target = target.clamp(@min, @max)

gap = current - target
return Enumerator.new { |_| } if gap == 0

Expand All @@ -30,9 +36,14 @@ def shrink(current, target: DEFAULT_TARGET)
while (diff = (current - target).abs) > 1
halved = diff / 2
current -= is_positive_gap ? halved : -halved
# Ensure current stays within bounds
current = current.clamp(@min, @max)
y.yield current
end
y.yield target # no diff here
# Only yield target if it's different from current
if current != target
y.yield target
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/pbt/arbitrary/choose_arbitrary_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

it "returns an Enumerator that iterates halved integers towards the min" do
arb = Pbt::Arbitrary::ChooseArbitrary.new(-2..10)
expect(arb.shrink(50).to_a).to eq [24, 11, 5, 2, 0, -1, -2]
expect(arb.shrink(50).to_a).to eq [10, 4, 1, 0, -1, -2]
end

context "when current value and target is same" do
Expand Down
34 changes: 34 additions & 0 deletions spec/pbt/arbitrary/integer_arbitrary_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,39 @@
end
end
end

describe "with min/max constraints" do
it "shrinks values within the specified range" do
arb = Pbt::Arbitrary::IntegerArbitrary.new(25, 65)
shrunk_values = arb.shrink(50).to_a

expect(shrunk_values).to all(be >= 25)
expect(shrunk_values).to all(be <= 65)
end

it "shrinks from max value respecting the min constraint" do
arb = Pbt::Arbitrary::IntegerArbitrary.new(25, 65)
shrunk_values = arb.shrink(65).to_a

expect(shrunk_values).to all(be >= 25)
expect(shrunk_values).to all(be <= 65)
expect(shrunk_values.last).to be >= 25
end

it "shrinks from min value respecting the min constraint" do
arb = Pbt::Arbitrary::IntegerArbitrary.new(25, 65)
shrunk_values = arb.shrink(25).to_a

expect(shrunk_values).to be_empty
end

it "shrinks negative range values within constraints" do
arb = Pbt::Arbitrary::IntegerArbitrary.new(-50, -10)
shrunk_values = arb.shrink(-20).to_a

expect(shrunk_values).to all(be >= -50)
expect(shrunk_values).to all(be <= -10)
end
end
end
end