This file is indexed.

/usr/lib/ruby/vendor_ruby/rspec/core/hooks.rb is in ruby-rspec-core 3.5.0c3e0m0s0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
module RSpec
  module Core
    # Provides `before`, `after` and `around` hooks as a means of
    # supporting common setup and teardown. This module is extended
    # onto {ExampleGroup}, making the methods available from any `describe`
    # or `context` block and included in {Configuration}, making them
    # available off of the configuration object to define global setup
    # or teardown logic.
    module Hooks
      # @api public
      #
      # @overload before(&block)
      # @overload before(scope, &block)
      #   @param scope [Symbol] `:example`, `:context`, or `:suite`
      #     (defaults to `:example`)
      # @overload before(scope, conditions, &block)
      #   @param scope [Symbol] `:example`, `:context`, or `:suite`
      #     (defaults to `:example`)
      #   @param conditions [Hash]
      #     constrains this hook to examples matching these conditions e.g.
      #     `before(:example, :ui => true) { ... }` will only run with examples
      #     or groups declared with `:ui => true`.
      # @overload before(conditions, &block)
      #   @param conditions [Hash]
      #     constrains this hook to examples matching these conditions e.g.
      #     `before(:example, :ui => true) { ... }` will only run with examples
      #     or groups declared with `:ui => true`.
      #
      # @see #after
      # @see #around
      # @see ExampleGroup
      # @see SharedContext
      # @see SharedExampleGroup
      # @see Configuration
      #
      # Declare a block of code to be run before each example (using `:example`)
      # or once before any example (using `:context`). These are usually
      # declared directly in the {ExampleGroup} to which they apply, but they
      # can also be shared across multiple groups.
      #
      # You can also use `before(:suite)` to run a block of code before any
      # example groups are run. This should be declared in {RSpec.configure}.
      #
      # Instance variables declared in `before(:example)` or `before(:context)`
      # are accessible within each example.
      #
      # ### Order
      #
      # `before` hooks are stored in three scopes, which are run in order:
      # `:suite`, `:context`, and `:example`. They can also be declared in
      # several different places: `RSpec.configure`, a parent group, the current
      # group. They are run in the following order:
      #
      #     before(:suite)    # Declared in RSpec.configure.
      #     before(:context)  # Declared in RSpec.configure.
      #     before(:context)  # Declared in a parent group.
      #     before(:context)  # Declared in the current group.
      #     before(:example)  # Declared in RSpec.configure.
      #     before(:example)  # Declared in a parent group.
      #     before(:example)  # Declared in the current group.
      #
      # If more than one `before` is declared within any one scope, they are run
      # in the order in which they are declared.
      #
      # ### Conditions
      #
      # When you add a conditions hash to `before(:example)` or
      # `before(:context)`, RSpec will only apply that hook to groups or
      # examples that match the conditions. e.g.
      #
      #     RSpec.configure do |config|
      #       config.before(:example, :authorized => true) do
      #         log_in_as :authorized_user
      #       end
      #     end
      #
      #     describe Something, :authorized => true do
      #       # The before hook will run in before each example in this group.
      #     end
      #
      #     describe SomethingElse do
      #       it "does something", :authorized => true do
      #         # The before hook will run before this example.
      #       end
      #
      #       it "does something else" do
      #         # The hook will not run before this example.
      #       end
      #     end
      #
      # Note that filtered config `:context` hooks can still be applied
      # to individual examples that have matching metadata. Just like
      # Ruby's object model is that every object has a singleton class
      # which has only a single instance, RSpec's model is that every
      # example has a singleton example group containing just the one
      # example.
      #
      # ### Warning: `before(:suite, :with => :conditions)`
      #
      # The conditions hash is used to match against specific examples. Since
      # `before(:suite)` is not run in relation to any specific example or
      # group, conditions passed along with `:suite` are effectively ignored.
      #
      # ### Exceptions
      #
      # When an exception is raised in a `before` block, RSpec skips any
      # subsequent `before` blocks and the example, but runs all of the
      # `after(:example)` and `after(:context)` hooks.
      #
      # ### Warning: implicit before blocks
      #
      # `before` hooks can also be declared in shared contexts which get
      # included implicitly either by you or by extension libraries. Since
      # RSpec runs these in the order in which they are declared within each
      # scope, load order matters, and can lead to confusing results when one
      # before block depends on state that is prepared in another before block
      # that gets run later.
      #
      # ### Warning: `before(:context)`
      #
      # It is very tempting to use `before(:context)` to speed things up, but we
      # recommend that you avoid this as there are a number of gotchas, as well
      # as things that simply don't work.
      #
      # #### Context
      #
      # `before(:context)` is run in an example that is generated to provide
      # group context for the block.
      #
      # #### Instance variables
      #
      # Instance variables declared in `before(:context)` are shared across all
      # the examples in the group. This means that each example can change the
      # state of a shared object, resulting in an ordering dependency that can
      # make it difficult to reason about failures.
      #
      # #### Unsupported RSpec constructs
      #
      # RSpec has several constructs that reset state between each example
      # automatically. These are not intended for use from within
      # `before(:context)`:
      #
      #   * `let` declarations
      #   * `subject` declarations
      #   * Any mocking, stubbing or test double declaration
      #
      # ### other frameworks
      #
      # Mock object frameworks and database transaction managers (like
      # ActiveRecord) are typically designed around the idea of setting up
      # before an example, running that one example, and then tearing down. This
      # means that mocks and stubs can (sometimes) be declared in
      # `before(:context)`, but get torn down before the first real example is
      # ever run.
      #
      # You _can_ create database-backed model objects in a `before(:context)`
      # in rspec-rails, but it will not be wrapped in a transaction for you, so
      # you are on your own to clean up in an `after(:context)` block.
      #
      # @example before(:example) declared in an {ExampleGroup}
      #
      #     describe Thing do
      #       before(:example) do
      #         @thing = Thing.new
      #       end
      #
      #       it "does something" do
      #         # Here you can access @thing.
      #       end
      #     end
      #
      # @example before(:context) declared in an {ExampleGroup}
      #
      #     describe Parser do
      #       before(:context) do
      #         File.open(file_to_parse, 'w') do |f|
      #           f.write <<-CONTENT
      #             stuff in the file
      #           CONTENT
      #         end
      #       end
      #
      #       it "parses the file" do
      #         Parser.parse(file_to_parse)
      #       end
      #
      #       after(:context) do
      #         File.delete(file_to_parse)
      #       end
      #     end
      #
      # @note The `:example` and `:context` scopes are also available as
      #       `:each` and `:all`, respectively. Use whichever you prefer.
      # @note The `:suite` scope is only supported for hooks registered on
      #       `RSpec.configuration` since they exist independently of any
      #       example or example group.
      def before(*args, &block)
        hooks.register :append, :before, *args, &block
      end

      alias_method :append_before, :before

      # Adds `block` to the front of the list of `before` blocks in the same
      # scope (`:example`, `:context`, or `:suite`).
      #
      # See {#before} for scoping semantics.
      def prepend_before(*args, &block)
        hooks.register :prepend, :before, *args, &block
      end

      # @api public
      # @overload after(&block)
      # @overload after(scope, &block)
      #   @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to
      #     `:example`)
      # @overload after(scope, conditions, &block)
      #   @param scope [Symbol] `:example`, `:context`, or `:suite` (defaults to
      #     `:example`)
      #   @param conditions [Hash]
      #     constrains this hook to examples matching these conditions e.g.
      #     `after(:example, :ui => true) { ... }` will only run with examples
      #     or groups declared with `:ui => true`.
      # @overload after(conditions, &block)
      #   @param conditions [Hash]
      #     constrains this hook to examples matching these conditions e.g.
      #     `after(:example, :ui => true) { ... }` will only run with examples
      #     or groups declared with `:ui => true`.
      #
      # @see #before
      # @see #around
      # @see ExampleGroup
      # @see SharedContext
      # @see SharedExampleGroup
      # @see Configuration
      #
      # Declare a block of code to be run after each example (using `:example`)
      # or once after all examples n the context (using `:context`). See
      # {#before} for more information about ordering.
      #
      # ### Exceptions
      #
      # `after` hooks are guaranteed to run even when there are exceptions in
      # `before` hooks or examples. When an exception is raised in an after
      # block, the exception is captured for later reporting, and subsequent
      # `after` blocks are run.
      #
      # ### Order
      #
      # `after` hooks are stored in three scopes, which are run in order:
      # `:example`, `:context`, and `:suite`. They can also be declared in
      # several different places: `RSpec.configure`, a parent group, the current
      # group. They are run in the following order:
      #
      #     after(:example) # Declared in the current group.
      #     after(:example) # Declared in a parent group.
      #     after(:example) # Declared in RSpec.configure.
      #     after(:context) # Declared in the current group.
      #     after(:context) # Declared in a parent group.
      #     after(:context) # Declared in RSpec.configure.
      #     after(:suite)   # Declared in RSpec.configure.
      #
      # This is the reverse of the order in which `before` hooks are run.
      # Similarly, if more than one `after` is declared within any one scope,
      # they are run in reverse order of that in which they are declared.
      #
      # @note The `:example` and `:context` scopes are also available as
      #       `:each` and `:all`, respectively. Use whichever you prefer.
      # @note The `:suite` scope is only supported for hooks registered on
      #       `RSpec.configuration` since they exist independently of any
      #       example or example group.
      def after(*args, &block)
        hooks.register :prepend, :after, *args, &block
      end

      alias_method :prepend_after, :after

      # Adds `block` to the back of the list of `after` blocks in the same
      # scope (`:example`, `:context`, or `:suite`).
      #
      # See {#after} for scoping semantics.
      def append_after(*args, &block)
        hooks.register :append, :after, *args, &block
      end

      # @api public
      # @overload around(&block)
      # @overload around(scope, &block)
      #   @param scope [Symbol] `:example` (defaults to `:example`)
      #     present for syntax parity with `before` and `after`, but
      #     `:example`/`:each` is the only supported value.
      # @overload around(scope, conditions, &block)
      #   @param scope [Symbol] `:example` (defaults to `:example`)
      #     present for syntax parity with `before` and `after`, but
      #     `:example`/`:each` is the only supported value.
      #   @param conditions [Hash] constrains this hook to examples matching
      #     these conditions e.g. `around(:example, :ui => true) { ... }` will
      #     only run with examples or groups declared with `:ui => true`.
      # @overload around(conditions, &block)
      #   @param conditions [Hash] constrains this hook to examples matching
      #     these conditions e.g. `around(:example, :ui => true) { ... }` will
      #     only run with examples or groups declared with `:ui => true`.
      #
      # @yield [Example] the example to run
      #
      # @note the syntax of `around` is similar to that of `before` and `after`
      #   but the semantics are quite different. `before` and `after` hooks are
      #   run in the context of of the examples with which they are associated,
      #   whereas `around` hooks are actually responsible for running the
      #   examples. Consequently, `around` hooks do not have direct access to
      #   resources that are made available within the examples and their
      #   associated `before` and `after` hooks.
      #
      # @note `:example`/`:each` is the only supported scope.
      #
      # Declare a block of code, parts of which will be run before and parts
      # after the example. It is your responsibility to run the example:
      #
      #     around(:example) do |ex|
      #       # Do some stuff before.
      #       ex.run
      #       # Do some stuff after.
      #     end
      #
      # The yielded example aliases `run` with `call`, which lets you treat it
      # like a `Proc`. This is especially handy when working with libaries
      # that manage their own setup and teardown using a block or proc syntax,
      # e.g.
      #
      #     around(:example) {|ex| Database.transaction(&ex)}
      #     around(:example) {|ex| FakeFS(&ex)}
      #
      def around(*args, &block)
        hooks.register :prepend, :around, *args, &block
      end

      # @private
      # Holds the various registered hooks.
      def hooks
        @hooks ||= HookCollections.new(self, FilterableItemRepository::UpdateOptimized)
      end

    private

      # @private
      Hook = Struct.new(:block, :options)

      # @private
      class BeforeHook < Hook
        def run(example)
          example.instance_exec(example, &block)
        end
      end

      # @private
      class AfterHook < Hook
        def run(example)
          example.instance_exec(example, &block)
        rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
          example.set_exception(ex)
        end
      end

      # @private
      class AfterContextHook < Hook
        def run(example)
          example.instance_exec(example, &block)
        rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
          RSpec.configuration.reporter.notify_non_example_exception(e, "An error occurred in an `after(:context)` hook.")
        end
      end

      # @private
      class AroundHook < Hook
        def execute_with(example, procsy)
          example.instance_exec(procsy, &block)
          return if procsy.executed?
          Pending.mark_skipped!(example,
                                "#{hook_description} did not execute the example")
        end

        if Proc.method_defined?(:source_location)
          def hook_description
            "around hook at #{Metadata.relative_path(block.source_location.join(':'))}"
          end
        else # for 1.8.7
          # :nocov:
          def hook_description
            "around hook"
          end
          # :nocov:
        end
      end

      # @private
      #
      # This provides the primary API used by other parts of rspec-core. By hiding all
      # implementation details behind this facade, it's allowed us to heavily optimize
      # this, so that, for example, hook collection objects are only instantiated when
      # a hook is added. This allows us to avoid many object allocations for the common
      # case of a group having no hooks.
      #
      # This is only possible because this interface provides a "tell, don't ask"-style
      # API, so that callers _tell_ this class what to do with the hooks, rather than
      # asking this class for a list of hooks, and then doing something with them.
      class HookCollections
        def initialize(owner, filterable_item_repo_class)
          @owner                      = owner
          @filterable_item_repo_class = filterable_item_repo_class
          @before_example_hooks       = nil
          @after_example_hooks        = nil
          @before_context_hooks       = nil
          @after_context_hooks        = nil
          @around_example_hooks       = nil
        end

        def register_globals(host, globals)
          parent_groups = host.parent_groups

          process(host, parent_groups, globals, :before, :example, &:options)
          process(host, parent_groups, globals, :after,  :example, &:options)
          process(host, parent_groups, globals, :around, :example, &:options)

          process(host, parent_groups, globals, :before, :context, &:options)
          process(host, parent_groups, globals, :after,  :context, &:options)
        end

        def register_global_singleton_context_hooks(example, globals)
          parent_groups = example.example_group.parent_groups

          process(example, parent_groups, globals, :before, :context) { {} }
          process(example, parent_groups, globals, :after,  :context) { {} }
        end

        def register(prepend_or_append, position, *args, &block)
          scope, options = scope_and_options_from(*args)

          if scope == :suite
            # TODO: consider making this an error in RSpec 4. For SemVer reasons,
            # we are only warning in RSpec 3.
            RSpec.warn_with "WARNING: `#{position}(:suite)` hooks are only supported on " \
                            "the RSpec configuration object. This " \
                            "`#{position}(:suite)` hook, registered on an example " \
                            "group, will be ignored."
            return
          end

          hook = HOOK_TYPES[position][scope].new(block, options)
          ensure_hooks_initialized_for(position, scope).__send__(prepend_or_append, hook, options)
        end

        # @private
        #
        # Runs all of the blocks stored with the hook in the context of the
        # example. If no example is provided, just calls the hook directly.
        def run(position, scope, example_or_group)
          return if RSpec.configuration.dry_run?

          if scope == :context
            run_owned_hooks_for(position, :context, example_or_group)
          else
            case position
            when :before then run_example_hooks_for(example_or_group, :before, :reverse_each)
            when :after  then run_example_hooks_for(example_or_group, :after,  :each)
            when :around then run_around_example_hooks_for(example_or_group) { yield }
            end
          end
        end

        SCOPES = [:example, :context]

        SCOPE_ALIASES = { :each => :example, :all => :context }

        HOOK_TYPES = {
          :before => Hash.new { BeforeHook },
          :after  => Hash.new { AfterHook  },
          :around => Hash.new { AroundHook }
        }

        HOOK_TYPES[:after][:context] = AfterContextHook

      protected

        EMPTY_HOOK_ARRAY = [].freeze

        def matching_hooks_for(position, scope, example_or_group)
          repository = hooks_for(position, scope) { return EMPTY_HOOK_ARRAY }

          # It would be nice to not have to switch on type here, but
          # we don't want to define `ExampleGroup#metadata` because then
          # `metadata` from within an individual example would return the
          # group's metadata but the user would probably expect it to be
          # the example's metadata.
          metadata = case example_or_group
                     when ExampleGroup then example_or_group.class.metadata
                     else example_or_group.metadata
                     end

          repository.items_for(metadata)
        end

        def all_hooks_for(position, scope)
          hooks_for(position, scope) { return EMPTY_HOOK_ARRAY }.items_and_filters.map(&:first)
        end

        def run_owned_hooks_for(position, scope, example_or_group)
          matching_hooks_for(position, scope, example_or_group).each do |hook|
            hook.run(example_or_group)
          end
        end

        def processable_hooks_for(position, scope, host)
          if scope == :example
            all_hooks_for(position, scope)
          else
            matching_hooks_for(position, scope, host)
          end
        end

      private

        def hooks_for(position, scope)
          if position == :before
            scope == :example ? @before_example_hooks : @before_context_hooks
          elsif position == :after
            scope == :example ? @after_example_hooks : @after_context_hooks
          else # around
            @around_example_hooks
          end || yield
        end

        def ensure_hooks_initialized_for(position, scope)
          if position == :before
            if scope == :example
              @before_example_hooks ||= @filterable_item_repo_class.new(:all?)
            else
              @before_context_hooks ||= @filterable_item_repo_class.new(:all?)
            end
          elsif position == :after
            if scope == :example
              @after_example_hooks ||= @filterable_item_repo_class.new(:all?)
            else
              @after_context_hooks ||= @filterable_item_repo_class.new(:all?)
            end
          else # around
            @around_example_hooks ||= @filterable_item_repo_class.new(:all?)
          end
        end

        def process(host, parent_groups, globals, position, scope)
          hooks_to_process = globals.processable_hooks_for(position, scope, host)
          return if hooks_to_process.empty?

          hooks_to_process -= FlatMap.flat_map(parent_groups) do |group|
            group.hooks.all_hooks_for(position, scope)
          end
          return if hooks_to_process.empty?

          repository = ensure_hooks_initialized_for(position, scope)
          hooks_to_process.each { |hook| repository.append hook, (yield hook) }
        end

        def scope_and_options_from(*args)
          return :suite if args.first == :suite
          scope = extract_scope_from(args)
          meta  = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
          return scope, meta
        end

        def extract_scope_from(args)
          if known_scope?(args.first)
            normalized_scope_for(args.shift)
          elsif args.any? { |a| a.is_a?(Symbol) }
            error_message = "You must explicitly give a scope " \
              "(#{SCOPES.join(", ")}) or scope alias " \
              "(#{SCOPE_ALIASES.keys.join(", ")}) when using symbols as " \
              "metadata for a hook."
            raise ArgumentError.new error_message
          else
            :example
          end
        end

        def known_scope?(scope)
          SCOPES.include?(scope) || SCOPE_ALIASES.keys.include?(scope)
        end

        def normalized_scope_for(scope)
          SCOPE_ALIASES[scope] || scope
        end

        def run_example_hooks_for(example, position, each_method)
          owner_parent_groups.__send__(each_method) do |group|
            group.hooks.run_owned_hooks_for(position, :example, example)
          end
        end

        def run_around_example_hooks_for(example)
          hooks = FlatMap.flat_map(owner_parent_groups) do |group|
            group.hooks.matching_hooks_for(:around, :example, example)
          end

          return yield if hooks.empty? # exit early to avoid the extra allocation cost of `Example::Procsy`

          initial_procsy = Example::Procsy.new(example) { yield }
          hooks.inject(initial_procsy) do |procsy, around_hook|
            procsy.wrap { around_hook.execute_with(example, procsy) }
          end.call
        end

        if respond_to?(:singleton_class) && singleton_class.ancestors.include?(singleton_class)
          def owner_parent_groups
            @owner.parent_groups
          end
        else # Ruby < 2.1 (see https://bugs.ruby-lang.org/issues/8035)
          # :nocov:
          def owner_parent_groups
            @owner_parent_groups ||= [@owner] + @owner.parent_groups
          end
          # :nocov:
        end
      end
    end
  end
end