1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/bootstraptest/test_insns.rb
Jeremy Evans 900e83b501 Turn class variable warnings into exceptions
This changes the following warnings:

* warning: class variable access from toplevel
* warning: class variable @foo of D is overtaken by C

into RuntimeErrors.  Handle defined?(@@foo) at toplevel
by returning nil instead of raising an exception (the previous
behavior warned before returning nil when defined? was used).

Refactor the specs to avoid the warnings even in older versions.
The specs were checking for the warnings, but the purpose of
the related specs as evidenced from their description is to
test for behavior, not for warnings.

Fixes [Bug #14541]
2020-04-10 00:29:05 -07:00

440 lines
13 KiB
Ruby

# C0 coverage of each instructions
# :NOTE: This is for development purpose; never consider this file as
# ISeq compilation specification.
begin
# This library brings some additional coverage.
# Not mandatory.
require 'rbconfig/sizeof'
rescue LoadError
# OK, just skip
else
if defined? RbConfig::LIMITS
$FIXNUM_MAX = RbConfig::LIMITS["FIXNUM_MAX"]
$FIXNUM_MIN = RbConfig::LIMITS["FIXNUM_MIN"]
end
end
fsl = { frozen_string_literal: true } # used later
tests = [
# insn , expression to generate such insn
[ 'nop', %q{ raise rescue true }, ],
[ 'setlocal *, 0', %q{ x = true }, ],
[ 'setlocal *, 1', %q{ x = nil; -> { x = true }.call }, ],
[ 'setlocal', %q{ x = nil; -> { -> { x = true }.() }.() }, ],
[ 'getlocal *, 0', %q{ x = true; x }, ],
[ 'getlocal *, 1', %q{ x = true; -> { x }.call }, ],
[ 'getlocal', %q{ x = true; -> { -> { x }.() }.() }, ],
[ 'setblockparam', <<-'},', ], # {
def m&b
b = # here
proc { true }
end
m { false }.call
},
[ 'getblockparam', <<-'},', ], # {
def m&b
b # here
end
m { true }.call
},
[ 'getblockparamproxy', <<-'},', ], # {
def m&b
b # here
.call
end
m { true }
},
[ 'setspecial', %q{ true if true..true }, ],
[ 'getspecial', %q{ $&.nil? }, ],
[ 'getspecial', %q{ $`.nil? }, ],
[ 'getspecial', %q{ $'.nil? }, ],
[ 'getspecial', %q{ $+.nil? }, ],
[ 'getspecial', %q{ $1.nil? }, ],
[ 'getspecial', %q{ $128.nil? }, ],
[ 'getglobal', %q{ String === $0 }, ],
[ 'getglobal', %q{ $_.nil? }, ],
[ 'setglobal', %q{ $0 = "true" }, ],
[ 'setinstancevariable', %q{ @x = true }, ],
[ 'getinstancevariable', %q{ @x = true; @x }, ],
[ 'setclassvariable', %q{ class A; @@x = true; end }, ],
[ 'getclassvariable', %q{ class A; @@x = true; @@x end }, ],
[ 'setconstant', %q{ X = true }, ],
[ 'setconstant', %q{ Object::X = true }, ],
[ 'getconstant', %q{ X = true; X }, ],
[ 'getconstant', %q{ X = true; Object::X }, ],
[ 'getinlinecache / setinlinecache', %q{ def x; X; end; X = true; x; x; x }, ],
[ 'putnil', %q{ $~ == nil }, ],
[ 'putself', %q{ $~ != self }, ],
[ 'putobject INT2FIX(0)', %q{ $~ != 0 }, ],
[ 'putobject INT2FIX(1)', %q{ $~ != 1 }, ],
[ 'putobject', %q{ $~ != -1 }, ],
[ 'putobject', %q{ $~ != /x/ }, ],
[ 'putobject', %q{ $~ != :x }, ],
[ 'putobject', %q{ $~ != (1..2) }, ],
[ 'putobject', %q{ $~ != true }, ],
[ 'putobject', %q{ /(?<x>x)/ =~ "x"; x == "x" }, ],
[ 'putspecialobject', %q{ {//=>true}[//] }, ],
[ 'putiseq', %q{ -> { true }.() }, ],
[ 'putstring', %q{ "true" }, ],
[ 'tostring / concatstrings', %q{ "#{true}" }, ],
[ 'freezestring', %q{ "#{true}" }, fsl, ],
[ 'freezestring', %q{ "#{true}" }, '-d', fsl, ],
[ 'toregexp', %q{ /#{true}/ =~ "true" && $~ }, ],
[ 'intern', %q{ :"#{true}" }, ],
[ 'newarray', %q{ ["true"][0] }, ],
[ 'newarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ],
[ 'duparray', %q{ [ true ][0] }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, = y; x }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, *z = y; x }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, *z, w = y; x }, ],
[ 'splatarray', %q{ x, = *(y = true), false; x }, ],
[ 'concatarray', %q{ ["t", "r", *x = "u", "e"].join }, ],
[ 'concatarray', <<-'},', ], # {
class X; def to_a; ['u']; end; end
['t', 'r', *X.new, 'e'].join
},
[ 'concatarray', <<-'},', ], # {
r = false
t = [true, nil]
q, w, e = r, *t # here
w
},
[ 'newhash', %q{ x = {}; x[x] = true }, ],
[ 'newhash', %q{ x = true; { x => x }[x] }, ],
[ 'newhashfromarray', %q{ { a: true }[:a] }, ],
[ 'newrange', %q{ x = 1; [*(0..x)][0] == 0 }, ],
[ 'newrange', %q{ x = 1; [*(0...x)][0] == 0 }, ],
[ 'pop', %q{ def x; true; end; x }, ],
[ 'dup', %q{ x = y = true; x }, ],
[ 'dupn', %q{ Object::X ||= true }, ],
[ 'reverse', %q{ q, (w, e), r = 1, [2, 3], 4; e == 3 }, ],
[ 'swap', <<-'},', ], # {
x = [[false, true]]
for i, j in x # here
;
end
j
},
[ 'topn', %q{ x, y = [], 0; x[*y], = [true, false]; x[0] }, ],
[ 'setn', %q{ x, y = [], 0; x[*y] = true ; x[0] }, ],
[ 'adjuststack', %q{ x = [true]; x[0] ||= nil; x[0] }, ],
[ 'defined', %q{ !defined?(x) }, ],
[ 'checkkeyword', %q{ def x x:rand;x end; x x: true }, ],
[ 'checktype', %q{ x = true; "#{x}" }, ],
[ 'checkmatch', <<-'},', ], # {
x = y = true
case x
when false
y = false
when true # here
y = nil
end
y == nil
},
[ 'checkmatch', <<-'},', ], # {
x, y = true, [false]
case x
when *y # here
z = false
else
z = true
end
z
},
[ 'checkmatch', <<-'},', ], # {
x = false
begin
raise
rescue # here
x = true
end
x
},
[ 'defineclass', %q{ module X; true end }, ],
[ 'defineclass', %q{ X = Module.new; module X; true end }, ],
[ 'defineclass', %q{ class X; true end }, ],
[ 'defineclass', %q{ X = Class.new; class X; true end }, ],
[ 'defineclass', %q{ X = Class.new; class Y < X; true end }, ],
[ 'defineclass', %q{ X = Class.new; class << X; true end }, ],
[ 'defineclass', <<-'},', ], # {
X = Class.new
Y = Class.new(X)
class Y < X
true
end
},
[ 'opt_send_without_block', %q{ true.to_s }, ],
[ 'send', %q{ true.tap {|i| i.to_s } }, ],
[ 'leave', %q{ def x; true; end; x }, ],
[ 'invokesuper', <<-'},', ], # {
class X < String
def empty?
super # here
end
end
X.new.empty?
},
[ 'invokeblock', <<-'},', ], # {
def x
return yield self # here
end
x do
true
end
},
[ 'opt_str_freeze', %q{ 'true'.freeze }, ],
[ 'opt_nil_p', %q{ nil.nil? }, ],
[ 'opt_nil_p', %q{ !Object.nil? }, ],
[ 'opt_nil_p', %q{ Class.new{def nil?; true end}.new.nil? }, ],
[ 'opt_str_uminus', %q{ -'true' }, ],
[ 'opt_str_freeze', <<-'},', ], # {
class String
def freeze
true
end
end
'true'.freeze
},
[ 'opt_newarray_max', %q{ [ ].max.nil? }, ],
[ 'opt_newarray_max', %q{ [1, x = 2, 3].max == 3 }, ],
[ 'opt_newarray_max', <<-'},', ], # {
class Array
def max
true
end
end
[1, x = 2, 3].max
},
[ 'opt_newarray_min', %q{ [ ].min.nil? }, ],
[ 'opt_newarray_min', %q{ [3, x = 2, 1].min == 1 }, ],
[ 'opt_newarray_min', <<-'},', ], # {
class Array
def min
true
end
end
[3, x = 2, 1].min
},
[ 'throw', %q{ false.tap { break true } }, ],
[ 'branchif', %q{ x = nil; x ||= true }, ],
[ 'branchif', %q{ x = true; x ||= nil; x }, ],
[ 'branchunless', %q{ x = 1; x &&= true }, ],
[ 'branchunless', %q{ x = nil; x &&= true; x.nil? }, ],
[ 'branchnil', %q{ x = true; x&.to_s }, ],
[ 'branchnil', %q{ x = nil; (x&.to_s).nil? }, ],
[ 'jump', <<-'},', ], # {
y = 1
x = if y == 0 then nil elsif y == 1 then true else nil end
x
},
[ 'jump', <<-'},', ], # {
# ultra complicated situation: this ||= assignment only generates
# 15 instructions, not including the class definition.
class X; attr_accessor :x; end
x = X.new
x&.x ||= true # here
},
[ 'once', %q{ /#{true}/o =~ "true" && $~ }, ],
[ 'once', <<-'},', ], # {
def once expr
return /#{expr}/o # here
end
x = once(true); x = once(false); x = once(nil);
x =~ "true" && $~
},
[ 'once', <<-'},', ], # {
# recursive once
def once n
return %r/#{
if n == 0
true
else
once(n-1) # here
end
}/ox
end
x = once(128); x = once(7); x = once(16);
x =~ "true" && $~
},
[ 'once', <<-'},', ], # {
# inter-thread lockup situation
def once n
return Thread.start n do |m|
Thread.pass
next %r/#{
sleep m # here
true
}/ox
end
end
x = once(1); y = once(0.1); z = y.value
z =~ "true" && $~
},
[ 'opt_case_dispatch', %q{ case 0 when 1.1 then false else true end }, ],
[ 'opt_case_dispatch', %q{ case 1.0 when 1.1 then false else true end }, ],
[ 'opt_plus', %q{ 1 + 1 == 2 }, ],
if defined? $FIXNUM_MAX then
[ 'opt_plus', %Q{ #{ $FIXNUM_MAX } + 1 == #{ $FIXNUM_MAX + 1 } }, ]
end,
[ 'opt_plus', %q{ 1.0 + 1.0 == 2.0 }, ],
[ 'opt_plus', %q{ x = +0.0.next_float; x + x >= x }, ],
[ 'opt_plus', %q{ 't' + 'rue' }, ],
[ 'opt_plus', %q{ ( ['t'] + ['r', ['u', ['e'], ], ] ).join }, ],
[ 'opt_plus', %q{ Time.at(1) + 1 == Time.at(2) }, ],
[ 'opt_minus', %q{ 1 - 1 == 0 }, ],
if defined? $FIXNUM_MIN then
[ 'opt_minus', %Q{ #{ $FIXNUM_MIN } - 1 == #{ $FIXNUM_MIN - 1 } }, ]
end,
[ 'opt_minus', %q{ 1.0 - 1.0 == 0.0 }, ],
[ 'opt_minus', %q{ x = -0.0.prev_float; x - x == 0.0 }, ],
[ 'opt_minus', %q{ ( [false, true] - [false] )[0] }, ],
[ 'opt_mult', %q{ 1 * 1 == 1 }, ],
[ 'opt_mult', %q{ 1.0 * 1.0 == 1.0 }, ],
[ 'opt_mult', %q{ x = +0.0.next_float; x * x <= x }, ],
[ 'opt_mult', %q{ ( "ruet" * 3 )[7,4] }, ],
[ 'opt_div', %q{ 1 / 1 == 1 }, ],
[ 'opt_div', %q{ 1.0 / 1.0 == 1.0 }, ],
[ 'opt_div', %q{ x = +0.0.next_float; x / x >= x }, ],
[ 'opt_div', %q{ x = 1/2r; x / x == 1 }, ],
[ 'opt_mod', %q{ 1 % 1 == 0 }, ],
[ 'opt_mod', %q{ 1.0 % 1.0 == 0.0 }, ],
[ 'opt_mod', %q{ x = +0.0.next_float; x % x == 0.0 }, ],
[ 'opt_mod', %q{ '%s' % [ true ] }, ],
[ 'opt_eq', %q{ 1 == 1 }, ],
[ 'opt_eq', <<-'},', ], # {
class X; def == other; true; end; end
X.new == true
},
[ 'opt_neq', %q{ 1 != 0 }, ],
[ 'opt_neq', <<-'},', ], # {
class X; def != other; true; end; end
X.new != true
},
[ 'opt_lt', %q{ -1 < 0 }, ],
[ 'opt_lt', %q{ -1.0 < 0.0 }, ],
[ 'opt_lt', %q{ -0.0.prev_float < 0.0 }, ],
[ 'opt_lt', %q{ ?a < ?z }, ],
[ 'opt_le', %q{ -1 <= 0 }, ],
[ 'opt_le', %q{ -1.0 <= 0.0 }, ],
[ 'opt_le', %q{ -0.0.prev_float <= 0.0 }, ],
[ 'opt_le', %q{ ?a <= ?z }, ],
[ 'opt_gt', %q{ 1 > 0 }, ],
[ 'opt_gt', %q{ 1.0 > 0.0 }, ],
[ 'opt_gt', %q{ +0.0.next_float > 0.0 }, ],
[ 'opt_gt', %q{ ?z > ?a }, ],
[ 'opt_ge', %q{ 1 >= 0 }, ],
[ 'opt_ge', %q{ 1.0 >= 0.0 }, ],
[ 'opt_ge', %q{ +0.0.next_float >= 0.0 }, ],
[ 'opt_ge', %q{ ?z >= ?a }, ],
[ 'opt_ltlt', %q{ '' << 'true' }, ],
[ 'opt_ltlt', %q{ ([] << 'true').join }, ],
[ 'opt_ltlt', %q{ (1 << 31) == 2147483648 }, ],
[ 'opt_aref', %q{ ['true'][0] }, ],
[ 'opt_aref', %q{ { 0 => 'true'}[0] }, ],
[ 'opt_aref', %q{ 'true'[0] == ?t }, ],
[ 'opt_aset', %q{ [][0] = true }, ],
[ 'opt_aset', %q{ {}[0] = true }, ],
[ 'opt_aset', %q{ x = 'frue'; x[0] = 't'; x }, ],
[ 'opt_aset', <<-'},', ], # {
# opt_aref / opt_aset mixup situation
class X; def x; {}; end; end
x = X.new
x&.x[true] ||= true # here
},
[ 'opt_aref_with', %q{ { 'true' => true }['true'] }, ],
[ 'opt_aref_with', %q{ Struct.new(:nil).new['nil'].nil? }, ],
[ 'opt_aset_with', %q{ {}['true'] = true }, ],
[ 'opt_aset_with', %q{ Struct.new(:true).new['true'] = true }, ],
[ 'opt_length', %q{ 'true' .length == 4 }, ],
[ 'opt_length', %q{ :true .length == 4 }, ],
[ 'opt_length', %q{ [ 'true' ] .length == 1 }, ],
[ 'opt_length', %q{ { 'true' => 1 }.length == 1 }, ],
[ 'opt_size', %q{ 'true' .size == 4 }, ],
[ 'opt_size', %q{ 1.size >= 4 }, ],
[ 'opt_size', %q{ [ 'true' ] .size == 1 }, ],
[ 'opt_size', %q{ { 'true' => 1 }.size == 1 }, ],
[ 'opt_empty_p', %q{ ''.empty? }, ],
[ 'opt_empty_p', %q{ [].empty? }, ],
[ 'opt_empty_p', %q{ {}.empty? }, ],
[ 'opt_empty_p', %q{ Queue.new.empty? }, ],
[ 'opt_succ', %q{ 1.succ == 2 }, ],
if defined? $FIXNUM_MAX then
[ 'opt_succ',%Q{ #{ $FIXNUM_MAX }.succ == #{ $FIXNUM_MAX + 1 } }, ]
end,
[ 'opt_succ', %q{ '1'.succ == '2' }, ],
[ 'opt_succ', %q{ x = Time.at(0); x.succ == Time.at(1) }, ],
[ 'opt_not', %q{ ! false }, ],
[ 'opt_neq', <<-'},', ], # {
class X; def !; true; end; end
! X.new
},
[ 'opt_regexpmatch2', %q{ /true/ =~ 'true' && $~ }, ],
[ 'opt_regexpmatch2', <<-'},', ], # {
class Regexp; def =~ other; true; end; end
/true/ =~ 'true'
},
[ 'opt_regexpmatch2', %q{ 'true' =~ /true/ && $~ }, ],
[ 'opt_regexpmatch2', <<-'},', ], # {
class String; def =~ other; true; end; end
'true' =~ /true/
},
[ 'opt_call_c_function', 'Struct.new(:x).new.x = true', ],
]
# normal path
tests.compact.each do |(insn, expr, *a)|
if a.last.is_a?(Hash)
a = a.dup
kw = a.pop
assert_equal 'true', expr, insn, *a, **kw
else
assert_equal 'true', expr, insn, *a
end
end
# with trace
tests.compact.each {|(insn, expr, *a)|
progn = "set_trace_func(proc{})\n" + expr
if a.last.is_a?(Hash)
a = a.dup
kw = a.pop
assert_equal 'true', progn, 'trace_' + insn, *a, **kw
else
assert_equal 'true', progn, 'trace_' + insn, *a
end
}