Skip to content

Commit 9224d90

Browse files
nobuko1
andauthored
Refactor socket timestamp tests
- Avoid unnecessarily binding sender sockets, as ephemeral ports can very occasionally conflict on Linux. This investigation is assisted by Claude Code. - Compare timestamps using a range instead of relying on `inspect`. - Use the `timestamp_retry_rw` helper in `test_bintime` as well. - Use `String#unpack1` with offset to extract the timestamp data. Co-authored-by: Koichi Sasada <ko1@atdot.net>
1 parent ce398d7 commit 9224d90

File tree

1 file changed

+20
-45
lines changed

1 file changed

+20
-45
lines changed

test/socket/test_socket.rb

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,11 @@ def test_linger
485485
}
486486
end
487487

488-
def timestamp_retry_rw(s1, s2, t1, type)
488+
def timestamp_retry_rw(s1, type)
489489
IO.pipe do |r,w|
490+
t1 = Time.now
490491
# UDP may not be reliable, keep sending until recvmsg returns:
492+
s2 = Socket.new(:INET, :DGRAM, 0)
491493
th = Thread.new do
492494
n = 0
493495
begin
@@ -500,80 +502,53 @@ def timestamp_retry_rw(s1, s2, t1, type)
500502
assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout))
501503
msg, _, _, stamp = s1.recvmsg
502504
assert_equal("a", msg)
503-
assert(stamp.cmsg_is?(:SOCKET, type))
505+
assert_send([stamp, :cmsg_is?, :SOCKET, type])
504506
w.close # stop th
505507
n = th.value
506508
th = nil
507509
n > 1 and
508510
warn "UDP packet loss for #{type} over loopback, #{n} tries needed"
509-
t2 = Time.now.strftime("%Y-%m-%d")
510-
pat = Regexp.union([t1, t2].uniq)
511-
assert_match(pat, stamp.inspect)
512-
t = stamp.timestamp
513-
assert_match(pat, t.strftime("%Y-%m-%d"))
511+
t2 = Time.now
512+
assert_include(t1..t2, stamp.timestamp)
514513
stamp
515514
ensure
516515
if th and !th.join(10)
517516
th.kill.join(10)
518517
end
518+
s2.close
519519
end
520520
end
521521

522522
def test_timestamp
523523
return if /linux|freebsd|netbsd|openbsd|darwin/ !~ RUBY_PLATFORM
524524
return if !defined?(Socket::AncillaryData) || !defined?(Socket::SO_TIMESTAMP)
525-
t1 = Time.now.strftime("%Y-%m-%d")
526-
stamp = nil
527525
Addrinfo.udp("127.0.0.1", 0).bind {|s1|
528-
Addrinfo.udp("127.0.0.1", 0).bind {|s2|
529-
s1.setsockopt(:SOCKET, :TIMESTAMP, true)
530-
stamp = timestamp_retry_rw(s1, s2, t1, :TIMESTAMP)
531-
}
526+
s1.setsockopt(:SOCKET, :TIMESTAMP, true)
527+
timestamp_retry_rw(s1, :TIMESTAMP)
532528
}
533-
t = stamp.timestamp
534-
pat = /\.#{"%06d" % t.usec}/
535-
assert_match(pat, stamp.inspect)
536529
end
537530

538531
def test_timestampns
539532
return if /linux/ !~ RUBY_PLATFORM || !defined?(Socket::SO_TIMESTAMPNS)
540-
t1 = Time.now.strftime("%Y-%m-%d")
541-
stamp = nil
542533
Addrinfo.udp("127.0.0.1", 0).bind {|s1|
543-
Addrinfo.udp("127.0.0.1", 0).bind {|s2|
544-
begin
545-
s1.setsockopt(:SOCKET, :TIMESTAMPNS, true)
546-
rescue Errno::ENOPROTOOPT
547-
# SO_TIMESTAMPNS is available since Linux 2.6.22
548-
return
549-
end
550-
stamp = timestamp_retry_rw(s1, s2, t1, :TIMESTAMPNS)
551-
}
534+
begin
535+
s1.setsockopt(:SOCKET, :TIMESTAMPNS, true)
536+
rescue Errno::ENOPROTOOPT
537+
# SO_TIMESTAMPNS is available since Linux 2.6.22
538+
return
539+
end
540+
timestamp_retry_rw(s1, :TIMESTAMPNS)
552541
}
553-
t = stamp.timestamp
554-
pat = /\.#{"%09d" % t.nsec}/
555-
assert_match(pat, stamp.inspect)
556542
end
557543

558544
def test_bintime
559545
return if /freebsd/ !~ RUBY_PLATFORM
560-
t1 = Time.now.strftime("%Y-%m-%d")
561-
stamp = nil
562-
Addrinfo.udp("127.0.0.1", 0).bind {|s1|
563-
Addrinfo.udp("127.0.0.1", 0).bind {|s2|
564-
s1.setsockopt(:SOCKET, :BINTIME, true)
565-
s2.send "a", 0, s1.local_address
566-
msg, _, _, stamp = s1.recvmsg
567-
assert_equal("a", msg)
568-
assert(stamp.cmsg_is?(:SOCKET, :BINTIME))
569-
}
546+
stamp = Addrinfo.udp("127.0.0.1", 0).bind {|s1|
547+
s1.setsockopt(:SOCKET, :BINTIME, true)
548+
timestamp_retry_rw(s1, :BINTIME)
570549
}
571-
t2 = Time.now.strftime("%Y-%m-%d")
572-
pat = Regexp.union([t1, t2].uniq)
573-
assert_match(pat, stamp.inspect)
574550
t = stamp.timestamp
575-
assert_match(pat, t.strftime("%Y-%m-%d"))
576-
assert_equal(stamp.data[-8,8].unpack("Q")[0], t.subsec * 2**64)
551+
assert_equal(stamp.data.unpack1("Q", offset: -8), t.subsec * 2**64)
577552
end
578553

579554
def test_closed_read

0 commit comments

Comments
 (0)