From 4de713cf567798be490a1cbe9317b16f49236d2f Mon Sep 17 00:00:00 2001 From: ksss Date: Tue, 9 Jun 2026 16:08:09 +0900 Subject: [PATCH] Add stdlib signature tests for #2967 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #2967 で更新された core/stdlib の signature に対する runtime signature test を追加する。 - IO#pathconf — pipe + Etc::PC_PIPE_BUF で検証 - StringIO singleton: open (non-block / block 両形) - StringIO instance: pread, read_nonblock, write_nonblock, sysread, ungetc, fcntl (NotImplementedError), fsync, internal_encoding, external_encoding, set_encoding_by_bom - Etc::Group.each / Etc::Passwd.each の block + Enumerator overload - Etc::Passwd の age/comment/quota (member 存在で guard) read_nonblock / write_nonblock の `exception:` キーワードは true/false のリテラルに展開して assertion を分けた。 `exception: false` は empty 入力で nil を返す分岐があるため。 Digest::Class の変更は raap で別途検証されているため test/stdlib/digest には手を入れていない。 Co-Authored-By: Claude Opus 4.7 --- test/stdlib/Etc_test.rb | 65 +++++++++++++++++++++++++++ test/stdlib/IO_test.rb | 10 +++++ test/stdlib/StringIO_test.rb | 87 ++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/test/stdlib/Etc_test.rb b/test/stdlib/Etc_test.rb index a5d73377ca..abb67b2528 100644 --- a/test/stdlib/Etc_test.rb +++ b/test/stdlib/Etc_test.rb @@ -111,3 +111,68 @@ def test_uname Etc, :uname end end + +class EtcGroupSingletonTest < Test::Unit::TestCase + include TestHelper + + library "etc" + testing "singleton(::Etc::Group)" + + def test_each + assert_send_type "() { (::Etc::Group) -> void } -> singleton(::Etc::Group)", + Etc::Group, :each do |_g| end + assert_send_type "() -> ::Enumerator[::Etc::Group]", + Etc::Group, :each + end +end + +class EtcPasswdSingletonTest < Test::Unit::TestCase + include TestHelper + + library "etc" + testing "singleton(::Etc::Passwd)" + + def test_each + assert_send_type "() { (::Etc::Passwd) -> void } -> singleton(::Etc::Passwd)", + Etc::Passwd, :each do |_u| end + assert_send_type "() -> ::Enumerator[::Etc::Passwd]", + Etc::Passwd, :each + end +end + +class EtcPasswdInstanceTest < Test::Unit::TestCase + include TestHelper + + library "etc" + testing "::Etc::Passwd" + + def test_age + omit "no age member on this platform" unless Etc::Passwd.members.include?(:age) + pw = Etc.getpwuid + + assert_send_type "() -> ::Integer", + pw, :age + assert_send_type "(::Integer) -> void", + pw, :age=, pw.age + end + + def test_comment + omit "no comment member on this platform" unless Etc::Passwd.members.include?(:comment) + pw = Etc.getpwuid + + assert_send_type "() -> ::String", + pw, :comment + assert_send_type "(::String) -> void", + pw, :comment=, pw.comment + end + + def test_quota + omit "no quota member on this platform" unless Etc::Passwd.members.include?(:quota) + pw = Etc.getpwuid + + assert_send_type "() -> ::Integer", + pw, :quota + assert_send_type "(::Integer) -> void", + pw, :quota=, pw.quota + end +end diff --git a/test/stdlib/IO_test.rb b/test/stdlib/IO_test.rb index e2b1971947..76062eea9f 100644 --- a/test/stdlib/IO_test.rb +++ b/test/stdlib/IO_test.rb @@ -1,5 +1,6 @@ require_relative "test_helper" require 'tempfile' +require 'etc' require "io/wait" @@ -227,6 +228,15 @@ def test_append_symbol end end + def test_pathconf + IO.pipe do |r, w| + assert_send_type "(Integer) -> Integer", + w, :pathconf, Etc::PC_PIPE_BUF + end + rescue NotImplementedError + omit "Not implemented" + end + def test_advise IO.open(IO.sysopen(File.expand_path(__FILE__))) do |io| assert_send_type "(Symbol) -> nil", diff --git a/test/stdlib/StringIO_test.rb b/test/stdlib/StringIO_test.rb index 62745afc8b..fd072490a0 100644 --- a/test/stdlib/StringIO_test.rb +++ b/test/stdlib/StringIO_test.rb @@ -39,6 +39,23 @@ def test_gets end end +class StringIOSingletonTest < Test::Unit::TestCase + include TestHelper + + testing 'singleton(::StringIO)' + + def test_open + assert_send_type "() -> ::StringIO", + StringIO, :open + assert_send_type "(::String) -> ::StringIO", + StringIO, :open, "abc" + assert_send_type "(::String, ::String) -> ::StringIO", + StringIO, :open, "abc", "r" + assert_send_type "() { (::StringIO) -> ::Integer } -> ::Integer", + StringIO, :open do |io| io.write("a") end + end +end + class StringIOTypeTest < Test::Unit::TestCase include TestHelper @@ -85,4 +102,74 @@ def test_readlines assert_send_type "(::String sep, ::Integer limit, chomp: boolish) -> ::Array[::String]", StringIO.new("\n"), :readlines, "\n", 1, chomp: true end + + def test_pread + assert_send_type "(Integer, Integer) -> String", + StringIO.new("abcdef"), :pread, 3, 0 + assert_send_type "(Integer, Integer, String) -> String", + StringIO.new("abcdef"), :pread, 3, 0, +"buf" + end + + def test_read_nonblock + assert_send_type "(int) -> String", + StringIO.new("abc"), :read_nonblock, 2 + assert_send_type "(int, string) -> String", + StringIO.new("abc"), :read_nonblock, 2, +"buf" + assert_send_type "(int, exception: true) -> String", + StringIO.new("abc"), :read_nonblock, 2, exception: true + assert_send_type "(int, exception: false) -> String", + StringIO.new("abc"), :read_nonblock, 2, exception: false + assert_send_type "(int, exception: false) -> nil", + StringIO.new(""), :read_nonblock, 2, exception: false + end + + def test_write_nonblock + assert_send_type "(_ToS) -> Integer", + StringIO.new(+""), :write_nonblock, "abc" + assert_send_type "(_ToS, exception: true) -> Integer", + StringIO.new(+""), :write_nonblock, "abc", exception: true + assert_send_type "(_ToS, exception: false) -> Integer", + StringIO.new(+""), :write_nonblock, "abc", exception: false + end + + def test_sysread + assert_send_type "(Integer) -> String", + StringIO.new("abc"), :sysread, 2 + assert_send_type "(Integer, String) -> String", + StringIO.new("abc"), :sysread, 2, +"buf" + end + + def test_ungetc + assert_send_type "(String) -> nil", + StringIO.new(+"abc"), :ungetc, "x" + assert_send_type "(Integer) -> nil", + StringIO.new(+"abc"), :ungetc, 65 + end + + def test_set_encoding_by_bom + assert_send_type "() -> Encoding", + StringIO.new("\u{FEFF}abc"), :set_encoding_by_bom + assert_send_type "() -> nil", + StringIO.new("abc"), :set_encoding_by_bom + end + + def test_fcntl + assert_send_type_error "(*untyped) -> bot", NotImplementedError, + StringIO.new("abc"), :fcntl, 1, 1 + end + + def test_fsync + assert_send_type "() -> Integer", + StringIO.new("abc"), :fsync + end + + def test_internal_encoding + assert_send_type "() -> nil", + StringIO.new("abc"), :internal_encoding + end + + def test_external_encoding + assert_send_type "() -> Encoding", + StringIO.new("abc"), :external_encoding + end end