Skip to content

Commit 9f0cb5a

Browse files
authored
Merge pull request rails#55255 from rails/fxn/clean_locations
Implement ActiveSupport::BacktraceCleaner#clean_locations
2 parents 9006822 + 5c45662 commit 9f0cb5a

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

activesupport/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
* Given an array of `Thread::Backtrace::Location` objects, the new method
2+
`ActiveSupport::BacktraceCleaner#clean_locations` returns an array with the
3+
clean ones:
4+
5+
```ruby
6+
clean_locations = backtrace_cleaner.clean_locations(caller_locations)
7+
```
8+
9+
Filters and silencers receive strings as usual. However, the `path`
10+
attributes of the locations in the returned array are the original,
11+
unfiltered ones, since locations are immutable.
12+
13+
*Xavier Noria*
14+
115
* Improve `CurrentAttribute` and `ExecutionContext` state managment in test cases.
216

317
Previously these two global state would be entirely cleared out whenever calling

activesupport/lib/active_support/backtrace_cleaner.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ def clean(backtrace, kind = :silent)
5656
end
5757
alias :filter :clean
5858

59+
# Given an array of Thread::Backtrace::Location objects, returns an array
60+
# with the clean ones:
61+
#
62+
# clean_locations = backtrace_cleaner.clean_locations(caller_locations)
63+
#
64+
# Filters and silencers receive strings as usual. However, the +path+
65+
# attributes of the locations in the returned array are the original,
66+
# unfiltered ones, since locations are immutable.
67+
def clean_locations(locations, kind = :silent)
68+
locations.select { |location| clean_frame(location, kind) }
69+
end
70+
5971
# Returns the frame with all filters applied.
6072
# returns +nil+ if the frame was silenced.
6173
def clean_frame(frame, kind = :silent)

activesupport/test/backtrace_cleaner_test.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,48 @@ def invoke_first_clean_location(kind = :silent)
232232
assert_nil invoke_first_clean_location_defaults
233233
end
234234
end
235+
236+
class BacktraceCleanerCleanLocationsTest < ActiveSupport::TestCase
237+
def setup
238+
@bc = ActiveSupport::BacktraceCleaner.new
239+
@locations = indirect_caller_locations
240+
end
241+
242+
# Adds a frame from this file to the call stack.
243+
def indirect_caller_locations
244+
caller_locations
245+
end
246+
247+
test "returns all clean locations (defaults)" do
248+
cleaned_locations = @bc.clean_locations(@locations)
249+
assert_equal [__FILE__], cleaned_locations.map(&:path)
250+
end
251+
252+
test "returns all clean locations (:silent)" do
253+
cleaned_locations = @bc.clean_locations(@locations, :silent)
254+
assert_equal [__FILE__], cleaned_locations.map(&:path)
255+
end
256+
257+
test "returns all clean locations (:noise)" do
258+
cleaned_locations = @bc.clean_locations(@locations, :noise)
259+
assert_not_includes cleaned_locations.map(&:path), __FILE__
260+
end
261+
262+
test "returns an empty array if there are no clean locations" do
263+
@bc.add_silencer { true }
264+
assert_equal [], @bc.clean_locations(@locations)
265+
end
266+
267+
test "filters and silencers are applied" do
268+
@bc.remove_filters!
269+
@bc.remove_silencers!
270+
271+
# We filter all locations as "foo", then we silence filtered strings that
272+
# are exactly "foo". If filters and silencers are correctly applied, we
273+
# should get no locations back.
274+
@bc.add_filter { "foo" }
275+
@bc.add_silencer { "foo" == _1 }
276+
277+
assert_equal [], @bc.clean_locations(@locations)
278+
end
279+
end

0 commit comments

Comments
 (0)