File: test_warning.rb

package info (click to toggle)
ruby-warning 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 156 kB
  • sloc: ruby: 754; makefile: 4
file content (646 lines) | stat: -rw-r--r-- 16,051 bytes parent folder | download
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
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
require_relative 'test_helper'
require 'pathname'

class WarningTest < Minitest::Test
  module EnvUtil
    def verbose_warning
      stderr = ""
      class << (stderr = "")
        alias write <<
        def puts(*a)
          self << a.join("\n")
        end
      end
      stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true
      yield stderr
      return $stderr
    ensure
      stderr, $stderr, $VERBOSE = $stderr, stderr, verbose
    end
    module_function :verbose_warning

    def with_default_internal(enc)
      verbose, $VERBOSE = $VERBOSE, nil
      origenc, Encoding.default_internal = Encoding.default_internal, enc
      $VERBOSE = verbose
      yield
    ensure
      verbose, $VERBOSE = $VERBOSE, nil
      Encoding.default_internal = origenc
      $VERBOSE = verbose
    end
    module_function :with_default_internal
  end

  def assert_warning(pat, msg = nil)
    stderr = EnvUtil.verbose_warning {
      EnvUtil.with_default_internal(pat.encoding) {
        yield
      }
    }
    msg = message(msg) {diff pat, stderr}
    assert(pat === stderr, msg)
  end

  def teardown
    Warning.clear
  end

  def test_warning_clear_ignore
    Warning.ignore(/.*/)

    assert_warning '' do
      Warning.warn 'foo'
    end

    Warning.clear do
      assert_warning 'foo' do
        Warning.warn 'foo'
      end
    end

    assert_warning '' do
      Warning.warn 'foo'
    end

    Warning.clear

    assert_warning 'foo' do
      Warning.warn 'foo'
    end
  end

  def test_warning_clear_process
    Warning.process('', /foo/ => :raise)

    e = assert_raises(RuntimeError) do
      Warning.warn 'foo'
    end
    assert_equal('foo', e.message)

    Warning.clear do
      assert_warning 'foo' do
        Warning.warn 'foo'
      end
    end

    e = assert_raises(RuntimeError) do
      Warning.warn 'foo'
    end
    assert_equal('foo', e.message)

    Warning.clear

    assert_warning 'foo' do
      Warning.warn 'foo'
    end
  end

  def test_warning_clear_dedup
    Warning.dedup

    assert_warning 'foo' do
      Warning.warn 'foo'
    end

    assert_warning '' do
      Warning.warn 'foo'
    end

    Warning.clear do
      assert_warning 'foo' do
        Warning.warn 'foo'
      end

      assert_warning 'foo' do
        Warning.warn 'foo'
      end
    end

    assert_warning '' do
      Warning.warn 'foo'
    end

    Warning.clear

    assert_warning 'foo' do
      Warning.warn 'foo'
    end

    assert_warning 'foo' do
      Warning.warn 'foo'
    end
  end

  def test_warning_dedup
    gvar = ->{$test_warning_dedup}

    assert_warning(/global variable `\$test_warning_dedup' not initialized/) do
      gvar.call
    end
    assert_warning(/global variable `\$test_warning_dedup' not initialized/) do
      gvar.call
    end

    Warning.dedup

    assert_warning(/global variable `\$test_warning_dedup' not initialized/) do
      gvar.call
    end
    assert_warning('') do
      gvar.call
    end
  end

  def test_warning_ignore
    assert_warning(/global variable `\$test_warning_ignore' not initialized/) do
      assert_nil($test_warning_ignore)
    end

    Warning.ignore(/global variable `\$test_warning_ignore' not initialized/)

    assert_warning '' do
      assert_nil($test_warning_ignore)
    end

    assert_warning(/global variable `\$test_warning_ignore2' not initialized/) do
      assert_nil($test_warning_ignore2)
    end

    Warning.ignore(/global variable `\$test_warning_ignore2' not initialized/, __FILE__)

    assert_warning '' do
      assert_nil($test_warning_ignore2)
    end

    assert_warning(/global variable `\$test_warning_ignore3' not initialized/) do
      assert_nil($test_warning_ignore3)
    end

    Warning.ignore(/global variable `\$test_warning_ignore3' not initialized/, __FILE__ + 'a')

    assert_warning(/global variable `\$test_warning_ignore3' not initialized/) do
      assert_nil($test_warning_ignore3)
    end

    assert_raises(TypeError) do
      Warning.ignore(Object.new)
    end
  end

  def test_warning_ignore_missing_ivar
    Warning.clear

    unless RUBY_VERSION >= '3.0'
      assert_warning(/instance variable @ivar not initialized/) do
        assert_nil(instance_variable_get(:@ivar))
      end
    end

    Warning.ignore(:missing_ivar, __FILE__)

    assert_warning '' do
      assert_nil(instance_variable_get(:@ivar))
    end
  end

  def test_warning_ignore_missing_gvar
    assert_warning(/global variable `\$gvar' not initialized/) do
      $gvar
    end

    Warning.ignore(:missing_gvar, __FILE__)

    assert_warning '' do
      $gvar
    end
  end

  def test_warning_ignore_method_redefined
    def self.a; end

    assert_warning(/method redefined; discarding old a.+previous definition of a was here/m) do
      def self.a; end
    end

    Warning.ignore(:method_redefined, __FILE__)

    assert_warning '' do
      def self.a; end
    end
  end

  def test_warning_ignore_not_reached
    assert_warning(/: warning: statement not reached/) do
      instance_eval('def self.b; return; 1 end', __FILE__)
    end

    Warning.ignore(:not_reached, __FILE__)

    assert_warning '' do
      instance_eval('def self.c; return; 1 end', __FILE__)
    end
  end

  def test_warning_ignore_fixnum
    assert_warning(/warning: constant ::Fixnum is deprecated/) do
      ::Fixnum
    end

    Warning.ignore(:fixnum, __FILE__)

    assert_warning '' do
      ::Fixnum
    end
  end if RUBY_VERSION < '3.2'

  def test_warning_ignore_bignum
    assert_warning(/warning: constant ::Bignum is deprecated/) do
      ::Bignum
    end

    Warning.ignore(:bignum, __FILE__)

    assert_warning '' do
      ::Bignum
    end
  end if RUBY_VERSION < '3.2'

  def test_warning_ignore_void_context
    assert_warning(/warning: possibly useless use of :: in void context/) do
      instance_eval('::Object; nil', __FILE__, __LINE__)
    end

    Warning.ignore(:void_context, __FILE__)

    assert_warning '' do
      instance_eval('::Object; nil', __FILE__, __LINE__)
    end

    assert_warning '' do
      instance_eval('Object; nil', __FILE__, __LINE__)
    end

    assert_warning '' do
      instance_eval('v = 0; v; nil', __FILE__, __LINE__)
    end

    assert_warning '' do
      instance_eval('1 > 1; nil', __FILE__, __LINE__)
    end

    assert_warning '' do
      instance_eval('defined? C; nil', __FILE__, __LINE__)
    end

    if RUBY_VERSION >= '2.6'
      assert_warning '' do
        instance_eval('1..; nil', __FILE__, __LINE__)
      end
    end
  end

  def test_warning_ignore_ambiguous_slash
    def self.d(re); end
    assert_warning(/warning: ambi/) do
      instance_eval('d /a/', __FILE__)
    end

    Warning.ignore(:ambiguous_slash, __FILE__)

    assert_warning '' do
      instance_eval('d /a/', __FILE__)
    end
  end

  def test_warning_ignore_unused_var
    assert_warning(/warning: assigned but unused variable - \w+/) do
      instance_eval('def self.e; b = 1; 2 end', __FILE__)
    end

    Warning.ignore(:unused_var, __FILE__)

    assert_warning '' do
      instance_eval('def self.f; b = 1; 2 end', __FILE__)
    end
  end

  def test_warning_ignore_useless_operator
    assert_warning(/warning: possibly useless use of == in void context/) do
      instance_eval('1 == 2; true', __FILE__)
    end

    Warning.ignore(:useless_operator, __FILE__)

    assert_warning '' do
      instance_eval('1 == 2; true', __FILE__)
    end
  end

  def test_warning_ignore_arg_prefix
    assert_warning(/: warning: `\*' interpreted as argument prefix/) do
      instance_eval('Array *[nil]', __FILE__)
    end

    assert_warning(/: warning: `&' interpreted as argument prefix/) do
      instance_eval('tap &proc{}', __FILE__)
    end
    Warning.ignore(:arg_prefix, __FILE__)

    assert_warning '' do
      instance_eval('Array *[nil]', __FILE__)
      instance_eval('tap &proc{}', __FILE__)
    end
  end

  def test_warning_ignore_shadow
    assert_warning(/warning: shadowing outer local variable - a/) do
      instance_eval('lambda{|a| lambda{|a|}}', __FILE__)
    end

    Warning.ignore(:shadow, __FILE__)

    assert_warning '' do
      instance_eval('lambda{|a| lambda{|a|}}', __FILE__)
    end
  end if RUBY_VERSION < '2.6'

  if RUBY_VERSION > '2.7' && RUBY_VERSION < '2.8'
    def h2kw(**kw)
    end
    def kw2h(h, **kw)
    end
    def skw(h=1, a: 1)
    end

    def test_warning_ignore_keyword
      assert_warning(/warning: Using the last argument as keyword parameters is deprecated; maybe \*\* should be added to the call.*The called method `h2kw' is defined here/m) do
        h2kw({})
      end
      assert_warning(/warning: Passing the keyword argument as the last hash parameter is deprecated.*The called method `kw2h' is defined here/m) do
        kw2h(a: 1)
      end
      assert_warning(/warning: Splitting the last argument into positional and keyword parameters is deprecated.*The called method `skw' is defined here/m) do
        skw("b" => 1, a: 2)
      end
      assert_warning(/warning: Splitting the last argument into positional and keyword parameters is deprecated.*The called method `skw' is defined here/m) do
        skw({"b" => 1, a: 2})
      end

      Warning.ignore(:keyword_separation, __FILE__)

      assert_warning '' do
        h2kw({})
        kw2h(a: 1)
        skw("b" => 1, a: 2)
        skw({"b" => 1, a: 2})
      end
    end

    def test_warning_ignore_safe
      assert_warning(/\$SAFE will become a normal global variable in Ruby 3\.0/) do
        $SAFE = 0
      end

      Warning.ignore(:safe, __FILE__)

      assert_warning("") do
        $SAFE = 0
      end
    end
  end

  if RUBY_VERSION > '2.7' && RUBY_VERSION < '3.2'

    def test_warning_ignore_taint
      o = Object.new

      assert_warning(/Object#taint is deprecated and will be removed in Ruby 3\.2/) do
        o.taint
      end
      assert_warning(/Object#untaint is deprecated and will be removed in Ruby 3\.2/) do
        o.untaint
      end
      assert_warning(/Object#tainted\? is deprecated and will be removed in Ruby 3\.2/) do
        o.tainted?
      end
      assert_warning(/Object#trust is deprecated and will be removed in Ruby 3\.2/) do
        o.trust
      end
      assert_warning(/Object#untrust is deprecated and will be removed in Ruby 3\.2/) do
        o.untrust
      end
      assert_warning(/Object#untrusted\? is deprecated and will be removed in Ruby 3\.2/) do
        o.untrusted?
      end

      path = Pathname.new(__FILE__)
      assert_warning(/Pathname#taint is deprecated and will be removed in Ruby 3\.2/) do
        path.taint
      end
      assert_warning(/Pathname#untaint is deprecated and will be removed in Ruby 3\.2/) do
        path.untaint
      end

      Warning.ignore(:taint, __FILE__)

      assert_warning("") do
        o.taint
        o.untaint
        o.tainted?
        o.trust
        o.untrust
        o.untrusted?
        p.taint
        p.untaint
      end
    end
  end

  def test_warning_ignore_symbol_array
    def self.c; end

    assert_warning(/statement not reached.+method redefined; discarding old c.+previous definition of c was here/m) do
      instance_eval('def self.c; return; 1 end', __FILE__)
    end

    Warning.ignore([:method_redefined, :not_reached], __FILE__)

    assert_warning '' do
      instance_eval('def self.c; return; 1 end', __FILE__)
    end
  end

  def test_warning_ignore_mismatched_indentation
    assert_warning(/warning: mismatched indentations/) do
      load 'test/fixtures/mismatched_indentations.rb'
    end

    Warning.ignore(:mismatched_indentations, 'test/fixtures/mismatched_indentations.rb')

    assert_warning '' do
      load 'test/fixtures/mismatched_indentations.rb'
    end
  end

  def test_warning_process
    warn = nil

    Warning.process(__FILE__+'a') do |warning|
      warn = [0, warning]
    end

    assert_warning(/global variable `\$test_warning_process' not initialized/) do
      $test_warning_process
    end
    assert_nil(warn)

    Warning.process(__FILE__) do |warning|
      warn = [1, warning]
    end

    assert_warning '' do
      $test_warning_process2
    end
    assert_equal(1, warn.first)
    assert_match(/global variable `\$test_warning_process2' not initialized/, warn.last)
    warn = nil

    Warning.process(File.dirname(__FILE__)) do |warning|
      warn = [2, warning]
    end

    assert_warning '' do
      $test_warning_process3
    end
    assert_equal(1, warn.first)
    assert_match(/global variable `\$test_warning_process3' not initialized/, warn.last)
    warn = nil

    Warning.process(__FILE__+':') do |warning|
      warn = [3, warning]
    end

    assert_warning '' do
      $test_warning_process4
    end
    assert_equal(3, warn.first)
    assert_match(/global variable `\$test_warning_process4' not initialized/, warn.last)
    warn = nil

    Warning.clear

    assert_warning(/global variable `\$test_warning_process5' not initialized/) do
      $test_warning_process5
    end
    assert_nil(warn)

    Warning.process do |warning|
      warn = [4, warning]
    end

    assert_warning '' do
      $test_warning_process6
    end
    assert_equal(4, warn.first)
    assert_match(/global variable `\$test_warning_process6' not initialized/, warn.last)

    assert_raises(TypeError) do
      Warning.process('', Object.new=>:raise)
    end
  end

  def test_warning_process_block_return_default
    w = nil
    Warning.process(__FILE__) do |warning|
      w = warning
      :default
    end

    assert_warning(/global variable `\$test_warning_process_block_return_default' not initialized/) do
      $test_warning_process_block_return_default
    end
    assert_match(/global variable `\$test_warning_process_block_return_default' not initialized/, w)
  end

  def test_warning_process_block_return_backtrace
    w = nil
    Warning.process(__FILE__) do |warning|
      w = warning
      :backtrace
    end

    assert_warning(/global variable `\$test_warning_process_block_return_backtrace' not initialized.*#{__FILE__}/m) do
      $test_warning_process_block_return_backtrace
    end
    assert_match(/global variable `\$test_warning_process_block_return_backtrace' not initialized/, w)
  end

  def test_warning_process_block_return_raise
    w = nil
    Warning.process(__FILE__) do |warning|
      w = warning
      :raise
    end

    assert_raises(RuntimeError) do
      $test_warning_process_block_return_raise
    end
    assert_match(/global variable `\$test_warning_process_block_return_raise' not initialized/, w)
  end

  def test_warning_process_action
    Warning.process(__FILE__, :method_redefined=>:default, :missing_gvar=>:backtrace, :ambiguous_slash=>:raise)
    Warning.process(__FILE__, :not_reached=>proc do |warning|
      :raise
    end)

    assert_warning(/warning: method redefined/) do
      Class.new do
        def a; end
        def a; end
      end
    end

    assert_warning(/global variable `\$test_warning_process_action' not initialized.*#{__FILE__}/m) do
      $test_warning_process_action
    end

    e = assert_raises(RuntimeError) do
      EnvUtil.verbose_warning{instance_eval('d /a/', __FILE__)}
    end
    assert_includes(e.message, "warning: ambi")

    e = assert_raises(RuntimeError) do
      EnvUtil.verbose_warning{instance_eval('def self.b; return; 1 end', __FILE__)}
    end
    assert_includes(e.message, "warning: statement not reached")
  end

  def test_warning_process_action_and_block
    assert_raises(ArgumentError) do
      Warning.process(__FILE__)
    end
  end

  def test_warning_process_no_action_and_no_block
    assert_raises(ArgumentError) do
      Warning.process(__FILE__, :missing_ivar=>:default){}
    end
  end

  def test_warning_process_path_no_string
    e = assert_raises(ArgumentError) do
      Warning.process(/foo/) { :raise }
    end
    assert_includes(e.message, "path must be a String (given an instance of Regexp)")
  end

  if RUBY_VERSION >= '3.0'
    def test_warning_warn_category_keyword
      assert_warning('foo') do
        Warning.warn("foo", category: :deprecated)
      end
    end
  end
end