Skip to content
Open
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
24 changes: 0 additions & 24 deletions core/float.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,6 @@ Float::EPSILON: Float
#
Float::INFINITY: Float

Float::Infinity: Float

# <!-- rdoc-file=numeric.c -->
# The number of base digits for the `double` data type.
#
Expand Down Expand Up @@ -1292,25 +1290,3 @@ Float::NAN: Float
# decimal.
#
Float::RADIX: Integer

# Deprecated, do not use.
#
# Represents the rounding mode for floating point addition at the start time.
#
# Usually defaults to 1, rounding to the nearest number.
#
# Other modes include:
#
# -1
# : Indeterminable
# 0
# : Rounding towards zero
# 1
# : Rounding to the nearest number
# 2
# : Rounding towards positive infinity
# 3
# : Rounding towards negative infinity
#
#
Float::ROUNDS: Integer
54 changes: 54 additions & 0 deletions test/stdlib/Float_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
require_relative "test_helper"

class FloatSingletonTest < Test::Unit::TestCase
include TestHelper

testing 'singleton(::Float)'

def test_DIG
assert_const_type 'Integer', 'Float::DIG'
end

def test_EPSILON
assert_const_type 'Float', 'Float::EPSILON'
end

def test_INFINITY
assert_const_type 'Float', 'Float::INFINITY'
end

def test_MANT_DIG
assert_const_type 'Integer', 'Float::MANT_DIG'
end

def test_MAX
assert_const_type 'Float', 'Float::MAX'
end

def test_MAX_10_EXP
assert_const_type 'Integer', 'Float::MAX_10_EXP'
end

def test_MAX_EXP
assert_const_type 'Integer', 'Float::MAX_EXP'
end

def test_MIN
assert_const_type 'Float', 'Float::MIN'
end

def test_MIN_10_EXP
assert_const_type 'Integer', 'Float::MIN_10_EXP'
end

def test_MIN_EXP
assert_const_type 'Integer', 'Float::MIN_EXP'
end

def test_NAN
assert_const_type 'Float', 'Float::NAN'
end

def test_RADIX
assert_const_type 'Integer', 'Float::RADIX'
end
end

class FloatTest < StdlibTest
target Float

Expand Down
77 changes: 77 additions & 0 deletions test/stdlib/constant_drift_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require_relative "test_helper"

# Guards against "constant drift" between the RBS core signatures and the actual
# runtime, in both directions:
#
# * a constant declared in RBS but no longer defined by Ruby (e.g.
# `Float::ROUNDS`, removed in Ruby 3.0), and
# * a constant defined by Ruby but missing from RBS.
#
# Only platform- and build-invariant core classes are hard-gated here. Classes
# whose constant set legitimately varies by OS or build options (`Process`,
# `Socket`, `Errno`, `Signal`, `File::Constants`, `RbConfig`, `Etc`, ...) are
# intentionally excluded: their RBS declarations cannot match any single
# platform's runtime. `Object`/`BasicObject`/`Kernel` are excluded too, since
# every top-level class shows up under `Object.constants`.
class ConstantDriftTest < Test::Unit::TestCase
# Platform/build-invariant core classes and modules whose declared constant
# set must match the runtime exactly.
HARD_GATE = [
Float, Integer, Numeric, Rational, Complex,
Math, Comparable,
String, Symbol,
Array, Hash, Range, Struct,
NilClass, TrueClass, FalseClass
].freeze

# Known, intentional exceptions keyed by "::Name" => [:CONST, ...]. Use this
# for build- or platform-conditional constants (and `private_constant`s) that
# are legitimately undeclared, so the gate stays green across CI platforms
# without being weakened elsewhere.
SKIP = {
# Defined only when Ruby is built with GMP (USE_GMP): present on the Linux
# CI build, absent on e.g. macOS.
"::Integer" => [:GMP_VERSION]
}.freeze

def env
StdlibTest::DEFAULT_ENV
end

# Constants declared directly under `type_name` in the loaded RBS environment
# (plain constants plus nested classes/modules and their aliases), matching
# what `Module#constants(false)` returns at runtime.
def rbs_constants(type_name)
prefix = "#{type_name}::"
names = []
[env.constant_decls, env.class_decls, env.class_alias_decls].each do |store|
store.each_key do |tn|
s = tn.to_s
next unless s.start_with?(prefix)

rest = s.delete_prefix(prefix)
names << rest.to_sym unless rest.include?("::")
end
end
names.uniq.sort
end

HARD_GATE.each do |klass|
define_method(:"test_no_constant_drift_#{klass.name.gsub("::", "_")}") do
type_name = "::#{klass.name}"
skip = SKIP[type_name] || []
runtime = (klass.constants(false) - skip).sort
declared = (rbs_constants(type_name) - skip).sort

stale = declared - runtime
missing = runtime - declared

assert_empty stale,
"RBS declares #{type_name} constants that no longer exist at runtime: #{stale.inspect}. " \
"Remove them from the signature (or add to ConstantDriftTest::SKIP if intentional)."
assert_empty missing,
"Runtime defines #{type_name} constants missing from RBS: #{missing.inspect}. " \
"Add them to the signature (or add to ConstantDriftTest::SKIP if intentional)."
end
end
end
Loading