Add "c_long_size" guard, supplanting "wordsize" and stop using Integer#size

What a "word" is when talking about sizes is confusing because it's a
highly overloaded term. Intel, Microsoft, and GDB are just a few vendors
that have their own definition of what a "word" is. Specs that used the
"wordsize" guard actually were mostly testing for the size of the C
`long` fundamental type, so rename the guard for clarity.

Also, get the size of `long` directly from RbConfig instead of guessing
using Integer#size. Integer#size is not guaranteed to have anything to
do with the `long` type.
This commit is contained in:
Alan Wu 2024-07-23 18:14:45 -04:00 коммит произвёл Benoit Daloze
Родитель 1a18b03ee7
Коммит 12e6cf77ef
17 изменённых файлов: 67 добавлений и 63 удалений

Просмотреть файл

@ -53,23 +53,27 @@ class PlatformGuard < SpecGuard
end
end
WORD_SIZE = 1.size * 8
POINTER_SIZE = begin
require 'rbconfig/sizeof'
RbConfig::SIZEOF["void*"] * 8
rescue LoadError
WORD_SIZE
[0].pack('j').size
end
def self.wordsize?(size)
size == WORD_SIZE
C_LONG_SIZE = if defined?(RbConfig::SIZEOF[])
RbConfig::SIZEOF["long"] * 8
else
[0].pack('l!').size
end
def self.pointer_size?(size)
size == POINTER_SIZE
end
def self.c_long_size?(size)
size == C_LONG_SIZE
end
def initialize(*args)
if args.last.is_a?(Hash)
@options, @platforms = args.last, args[0..-2]
@ -85,10 +89,10 @@ class PlatformGuard < SpecGuard
case key
when :os
match &&= PlatformGuard.os?(*value)
when :wordsize
match &&= PlatformGuard.wordsize? value
when :pointer_size
match &&= PlatformGuard.pointer_size? value
when :c_long_size
match &&= PlatformGuard::c_long_size? value
end
end
match

Просмотреть файл

@ -28,7 +28,7 @@ end
# specs based on the relationship between values rather than specific
# values.
if PlatformGuard.standard? or PlatformGuard.implementation? :topaz
if PlatformGuard.wordsize? 32
if PlatformGuard.c_long_size? 32
def fixnum_max
(2**30) - 1
end
@ -36,7 +36,7 @@ if PlatformGuard.standard? or PlatformGuard.implementation? :topaz
def fixnum_min
-(2**30)
end
elsif PlatformGuard.wordsize? 64
elsif PlatformGuard.c_long_size? 64
def fixnum_max
(2**62) - 1
end

Просмотреть файл

@ -81,44 +81,44 @@ RSpec.describe Object, "#platform_is_not" do
end
end
RSpec.describe Object, "#platform_is :wordsize => SIZE_SPEC" do
RSpec.describe Object, "#platform_is :c_long_size => SIZE_SPEC" do
before :each do
@guard = PlatformGuard.new :darwin, :wordsize => 32
@guard = PlatformGuard.new :darwin, :c_long_size => 32
allow(PlatformGuard).to receive(:os?).and_return(true)
allow(PlatformGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "yields when #wordsize? returns true" do
allow(PlatformGuard).to receive(:wordsize?).and_return(true)
platform_is(:wordsize => 32) { ScratchPad.record :yield }
it "yields when #c_long_size? returns true" do
allow(PlatformGuard).to receive(:c_long_size?).and_return(true)
platform_is(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).to eq(:yield)
end
it "doesn not yield when #wordsize? returns false" do
allow(PlatformGuard).to receive(:wordsize?).and_return(false)
platform_is(:wordsize => 32) { ScratchPad.record :yield }
it "doesn not yield when #c_long_size? returns false" do
allow(PlatformGuard).to receive(:c_long_size?).and_return(false)
platform_is(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).not_to eq(:yield)
end
end
RSpec.describe Object, "#platform_is_not :wordsize => SIZE_SPEC" do
RSpec.describe Object, "#platform_is_not :c_long_size => SIZE_SPEC" do
before :each do
@guard = PlatformGuard.new :darwin, :wordsize => 32
@guard = PlatformGuard.new :darwin, :c_long_size => 32
allow(PlatformGuard).to receive(:os?).and_return(true)
allow(PlatformGuard).to receive(:new).and_return(@guard)
ScratchPad.clear
end
it "yields when #wordsize? returns false" do
allow(PlatformGuard).to receive(:wordsize?).and_return(false)
platform_is_not(:wordsize => 32) { ScratchPad.record :yield }
it "yields when #c_long_size? returns false" do
allow(PlatformGuard).to receive(:c_long_size?).and_return(false)
platform_is_not(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).to eq(:yield)
end
it "doesn not yield when #wordsize? returns true" do
allow(PlatformGuard).to receive(:wordsize?).and_return(true)
platform_is_not(:wordsize => 32) { ScratchPad.record :yield }
it "doesn not yield when #c_long_size? returns true" do
allow(PlatformGuard).to receive(:c_long_size?).and_return(true)
platform_is_not(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).not_to eq(:yield)
end
end
@ -184,13 +184,13 @@ RSpec.describe PlatformGuard, ".standard?" do
end
end
RSpec.describe PlatformGuard, ".wordsize?" do
RSpec.describe PlatformGuard, ".c_long_size?" do
it "returns true when arg is 32 and 1.size is 4" do
expect(PlatformGuard.wordsize?(32)).to eq(1.size == 4)
expect(PlatformGuard.c_long_size?(32)).to eq(1.size == 4)
end
it "returns true when arg is 64 and 1.size is 8" do
expect(PlatformGuard.wordsize?(64)).to eq(1.size == 8)
expect(PlatformGuard.c_long_size?(64)).to eq(1.size == 8)
end
end

Просмотреть файл

@ -164,7 +164,7 @@ end
platform_is_not :linux, :darwin do # Not Linux and not Darwin
end
platform_is wordsize: 64 do
platform_is pointer_size: 64 do
# 64-bit platform
end

Просмотреть файл

@ -29,7 +29,7 @@ describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_be, 'L>'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'L<_'
it_behaves_like :array_pack_32bit_le, 'L_<'
@ -51,7 +51,7 @@ describe "Array#pack with format 'L'" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'L<_'
it_behaves_like :array_pack_64bit_le, 'L_<'
@ -83,7 +83,7 @@ describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_be, 'l>'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'l<_'
it_behaves_like :array_pack_32bit_le, 'l_<'
@ -105,7 +105,7 @@ describe "Array#pack with format 'l'" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'l<_'
it_behaves_like :array_pack_64bit_le, 'l_<'
@ -137,7 +137,7 @@ little_endian do
it_behaves_like :array_pack_32bit_le, 'l'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'L_'
end
@ -155,7 +155,7 @@ little_endian do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'L_'
end
@ -183,7 +183,7 @@ big_endian do
it_behaves_like :array_pack_32bit_be, 'l'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'L_'
end
@ -201,7 +201,7 @@ big_endian do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'L_'
end

Просмотреть файл

@ -273,7 +273,7 @@ describe :array_pack_32bit_le_platform, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x21\x43\x65\x78"],
[[-0xff_7865_4321], "\xdf\xbc\x9a\x87"]
@ -299,7 +299,7 @@ describe :array_pack_32bit_be_platform, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x78\x65\x43\x21"],
[[-0xff_7865_4321], "\x87\x9a\xbc\xdf"]

Просмотреть файл

@ -84,7 +84,7 @@ describe :update_time, shared: true do
end
platform_is :linux do
platform_is wordsize: 64 do
platform_is pointer_size: 64 do
it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do
# https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
# "Therefore, timestamps should not overflow until May 2446."

Просмотреть файл

@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Integer#size" do
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
it "returns the number of bytes in the machine representation of self" do
-1.size.should == 4
0.size.should == 4
@ -9,7 +9,7 @@ describe "Integer#size" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "returns the number of bytes in the machine representation of self" do
-1.size.should == 8
0.size.should == 8

Просмотреть файл

@ -38,7 +38,7 @@ describe "Marshal.dump" do
].should be_computed_by(:dump)
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "dumps a positive Fixnum > 31 bits as a Bignum" do
Marshal.dump(2**31 + 1).should == "\x04\bl+\a\x01\x00\x00\x80"
end

Просмотреть файл

@ -1049,7 +1049,7 @@ describe :marshal_load, shared: true do
end
describe "for a Bignum" do
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
context "that is Bignum on 32-bit platforms but Fixnum on 64-bit" do
it "dumps a Fixnum" do
val = Marshal.send(@method, "\004\bl+\ab:wU")

Просмотреть файл

@ -14,7 +14,7 @@ describe "String#unpack with format 'L'" do
it_behaves_like :string_unpack_32bit_be_unsigned, 'L>'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'L<_'
it_behaves_like :string_unpack_32bit_le, 'L_<'
@ -44,7 +44,7 @@ describe "String#unpack with format 'L'" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'L<_'
it_behaves_like :string_unpack_64bit_le, 'L_<'
@ -86,7 +86,7 @@ describe "String#unpack with format 'l'" do
it_behaves_like :string_unpack_32bit_be_signed, 'l>'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'l<_'
it_behaves_like :string_unpack_32bit_le, 'l_<'
@ -116,7 +116,7 @@ describe "String#unpack with format 'l'" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'l<_'
it_behaves_like :string_unpack_64bit_le, 'l_<'
@ -160,7 +160,7 @@ little_endian do
it_behaves_like :string_unpack_32bit_le_signed, 'l'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'L_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'L_'
@ -182,7 +182,7 @@ little_endian do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'L_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'L_'
@ -218,7 +218,7 @@ big_endian do
it_behaves_like :string_unpack_32bit_be_signed, 'l'
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'L_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'L_'
@ -240,7 +240,7 @@ big_endian do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_be, 'L_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'L_'

Просмотреть файл

@ -36,7 +36,7 @@ describe "BigDecimal#sqrt" do
BigDecimal('121').sqrt(5).should be_close(11, 0.00001)
end
platform_is_not wordsize: 32 do # fails on i686
platform_is_not c_long_size: 32 do # fails on i686
it "returns square root of 0.9E-99999 with desired precision" do
@frac_2.sqrt(1).to_s.should =~ /\A0\.3E-49999\z/i
end

Просмотреть файл

@ -123,7 +123,7 @@ describe "CApiBignumSpecs" do
val.should == @max_ulong
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "packs max_ulong into 2 ulongs to allow sign bit" do
val = @s.rb_big_pack_length(@max_ulong)
val.should == 2

Просмотреть файл

@ -25,7 +25,7 @@ describe "CApiFixnumSpecs" do
end
end
platform_is wordsize: 64 do # sizeof(long) > sizeof(int)
platform_is c_long_size: 64 do # sizeof(long) > sizeof(int)
it "raises a TypeError if passed nil" do
-> { @s.FIX2INT(nil) }.should raise_error(TypeError)
end
@ -74,7 +74,7 @@ describe "CApiFixnumSpecs" do
end
end
platform_is wordsize: 64 do # sizeof(long) > sizeof(int)
platform_is c_long_size: 64 do # sizeof(long) > sizeof(int)
it "raises a TypeError if passed nil" do
-> { @s.FIX2UINT(nil) }.should raise_error(TypeError)
end

Просмотреть файл

@ -106,7 +106,7 @@ describe "CApiNumericSpecs" do
@s.NUM2LONG(5).should == 5
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
it "converts -1 to an signed number" do
@s.NUM2LONG(-1).should == -1
end
@ -120,7 +120,7 @@ describe "CApiNumericSpecs" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "converts -1 to an signed number" do
@s.NUM2LONG(-1).should == -1
end
@ -210,7 +210,7 @@ describe "CApiNumericSpecs" do
@s.NUM2ULONG(5).should == 5
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
it "converts -1 to an unsigned number" do
@s.NUM2ULONG(-1).should == 4294967295
end
@ -231,7 +231,7 @@ describe "CApiNumericSpecs" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "converts -1 to an unsigned number" do
@s.NUM2ULONG(-1).should == 18446744073709551615
end

Просмотреть файл

@ -209,7 +209,7 @@ describe "C-API Util function" do
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
describe "rb_long2int" do
it "raises a RangeError if the value is outside the range of a C int" do
-> { @o.rb_long2int(0xffff_ffff_ffff) }.should raise_error(RangeError)

Просмотреть файл

@ -44,13 +44,13 @@ describe :string_times, shared: true do
result.encoding.should equal(Encoding::UTF_8)
end
platform_is wordsize: 32 do
platform_is c_long_size: 32 do
it "raises an ArgumentError if the length of the resulting string doesn't fit into a long" do
-> { @object.call("abc", (2 ** 31) - 1) }.should raise_error(ArgumentError)
end
end
platform_is wordsize: 64 do
platform_is c_long_size: 64 do
it "raises an ArgumentError if the length of the resulting string doesn't fit into a long" do
-> { @object.call("abc", (2 ** 63) - 1) }.should raise_error(ArgumentError)
end