зеркало из https://github.com/github/ruby.git
Make specs pass on OpenBSD
Skip Process clockres specs that don't work on either FreeBSD or Solaris/AIX in addition to OpenBSD. Run most current String#crypt specs on non-OpenBSD, and add a new set of crypt specs for OpenBSD, which support bcrypt but not DES in crypt(3). Use @server.connect_address instead of @server.getsockname in some socket tests, as OpenBSD does not treat connection to all zero IPv4 or IPv6 addresses as connection to localhost. When trying to connect using UDP on an unsupported address family, allow Errno::EPROTONOSUPPORT in addition to Errno::EAFNOSUPPORT, as OpenBSD raises the former.
This commit is contained in:
Родитель
c55de95ff1
Коммит
119ca4343c
|
@ -4,7 +4,7 @@ require_relative 'fixtures/clocks'
|
|||
describe "Process.clock_getres" do
|
||||
# clock_getres() seems completely buggy on FreeBSD:
|
||||
# https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd11zfs/ruby-trunk/log/20190428T093003Z.fail.html.gz
|
||||
platform_is_not :freebsd do
|
||||
platform_is_not :freebsd, :openbsd do
|
||||
# NOTE: Look at fixtures/clocks.rb for clock and OS-specific exclusions
|
||||
ProcessSpecs.clock_constants_for_resolution_checks.each do |name, value|
|
||||
it "matches the clock in practice for Process::#{name}" do
|
||||
|
@ -50,13 +50,13 @@ describe "Process.clock_getres" do
|
|||
|
||||
# These are observed
|
||||
|
||||
platform_is_not :solaris, :aix do
|
||||
platform_is_not :solaris, :aix, :openbsd do
|
||||
it "with Process::CLOCK_REALTIME reports at least 1 microsecond" do
|
||||
Process.clock_getres(Process::CLOCK_REALTIME, :nanosecond).should <= 1_000
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :aix do
|
||||
platform_is_not :aix, :openbsd do
|
||||
it "with Process::CLOCK_MONOTONIC reports at least 1 microsecond" do
|
||||
Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond).should <= 1_000
|
||||
end
|
||||
|
|
|
@ -2,72 +2,117 @@ require_relative '../../spec_helper'
|
|||
require_relative 'fixtures/classes'
|
||||
|
||||
describe "String#crypt" do
|
||||
# Note: MRI's documentation just says that the C stdlib function crypt() is
|
||||
# called.
|
||||
#
|
||||
# I'm not sure if crypt() is guaranteed to produce the same result across
|
||||
# different platforms. It seems that there is one standard UNIX implementation
|
||||
# of crypt(), but that alternative implementations are possible. See
|
||||
# http://www.unix.org.ua/orelly/networking/puis/ch08_06.htm
|
||||
it "returns a cryptographic hash of self by applying the UNIX crypt algorithm with the specified salt" do
|
||||
"".crypt("aa").should == "aaQSqAReePlq6"
|
||||
"nutmeg".crypt("Mi").should == "MiqkFWCm1fNJI"
|
||||
"ellen1".crypt("ri").should == "ri79kNd7V6.Sk"
|
||||
"Sharon".crypt("./").should == "./UY9Q7TvYJDg"
|
||||
"norahs".crypt("am").should == "amfIADT2iqjA."
|
||||
"norahs".crypt("7a").should == "7azfT5tIdyh0I"
|
||||
platform_is :openbsd do
|
||||
it "returns a cryptographic hash of self by applying the bcrypt algorithm with the specified salt" do
|
||||
"mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should == "$2a$04$0WVaz0pV3jzfZ5G5tpmHWuBQGbkjzgtSc3gJbmdy0GAGMa45MFM2."
|
||||
|
||||
# Only uses first 8 chars of string
|
||||
"01234567".crypt("aa").should == "aa4c4gpuvCkSE"
|
||||
"012345678".crypt("aa").should == "aa4c4gpuvCkSE"
|
||||
"0123456789".crypt("aa").should == "aa4c4gpuvCkSE"
|
||||
# Only uses first 72 characters of string
|
||||
("12345678"*9).crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should == "$2a$04$0WVaz0pV3jzfZ5G5tpmHWukj/ORBnsMjCGpST/zCJnAypc7eAbutK"
|
||||
("12345678"*10).crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should == "$2a$04$0WVaz0pV3jzfZ5G5tpmHWukj/ORBnsMjCGpST/zCJnAypc7eAbutK"
|
||||
|
||||
# Only uses first 2 chars of salt
|
||||
"hello world".crypt("aa").should == "aayPz4hyPS1wI"
|
||||
"hello world".crypt("aab").should == "aayPz4hyPS1wI"
|
||||
"hello world".crypt("aabc").should == "aayPz4hyPS1wI"
|
||||
# Only uses first 29 characters of salt
|
||||
"mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWuB").should == "$2a$04$0WVaz0pV3jzfZ5G5tpmHWuBQGbkjzgtSc3gJbmdy0GAGMa45MFM2."
|
||||
end
|
||||
|
||||
it "raises Errno::EINVAL when the salt is shorter than 29 characters" do
|
||||
lambda { "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHW") }.should raise_error(Errno::EINVAL)
|
||||
end
|
||||
|
||||
it "calls #to_str to converts the salt arg to a String" do
|
||||
obj = mock('$2a$04$0WVaz0pV3jzfZ5G5tpmHWu')
|
||||
obj.should_receive(:to_str).and_return("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")
|
||||
|
||||
"mypassword".crypt(obj).should == "$2a$04$0WVaz0pV3jzfZ5G5tpmHWuBQGbkjzgtSc3gJbmdy0GAGMa45MFM2."
|
||||
end
|
||||
|
||||
it "taints the result if either salt or self is tainted" do
|
||||
tainted_salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmHWu"
|
||||
tainted_str = "mypassword"
|
||||
|
||||
tainted_salt.taint
|
||||
tainted_str.taint
|
||||
|
||||
"mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").tainted?.should == false
|
||||
tainted_str.crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").tainted?.should == true
|
||||
"mypassword".crypt(tainted_salt).tainted?.should == true
|
||||
tainted_str.crypt(tainted_salt).tainted?.should == true
|
||||
end
|
||||
|
||||
it "doesn't return subclass instances" do
|
||||
StringSpecs::MyString.new("mypassword").crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should be_an_instance_of(String)
|
||||
"mypassword".crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should be_an_instance_of(String)
|
||||
StringSpecs::MyString.new("mypassword").crypt(StringSpecs::MyString.new("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu")).should be_an_instance_of(String)
|
||||
end
|
||||
end
|
||||
|
||||
it "raises an ArgumentError when the salt is shorter than two characters" do
|
||||
lambda { "hello".crypt("") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("f") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("\x00\x00") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("\x00a") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("a\x00") }.should raise_error(ArgumentError)
|
||||
end
|
||||
platform_is_not :openbsd do
|
||||
# Note: MRI's documentation just says that the C stdlib function crypt() is
|
||||
# called.
|
||||
#
|
||||
# I'm not sure if crypt() is guaranteed to produce the same result across
|
||||
# different platforms. It seems that there is one standard UNIX implementation
|
||||
# of crypt(), but that alternative implementations are possible. See
|
||||
# http://www.unix.org.ua/orelly/networking/puis/ch08_06.htm
|
||||
it "returns a cryptographic hash of self by applying the UNIX crypt algorithm with the specified salt" do
|
||||
"".crypt("aa").should == "aaQSqAReePlq6"
|
||||
"nutmeg".crypt("Mi").should == "MiqkFWCm1fNJI"
|
||||
"ellen1".crypt("ri").should == "ri79kNd7V6.Sk"
|
||||
"Sharon".crypt("./").should == "./UY9Q7TvYJDg"
|
||||
"norahs".crypt("am").should == "amfIADT2iqjA."
|
||||
"norahs".crypt("7a").should == "7azfT5tIdyh0I"
|
||||
|
||||
it "raises an ArgumentError when the string contains NUL character" do
|
||||
lambda { "poison\0null".crypt("aa") }.should raise_error(ArgumentError)
|
||||
end
|
||||
# Only uses first 8 chars of string
|
||||
"01234567".crypt("aa").should == "aa4c4gpuvCkSE"
|
||||
"012345678".crypt("aa").should == "aa4c4gpuvCkSE"
|
||||
"0123456789".crypt("aa").should == "aa4c4gpuvCkSE"
|
||||
|
||||
it "calls #to_str to converts the salt arg to a String" do
|
||||
obj = mock('aa')
|
||||
obj.should_receive(:to_str).and_return("aa")
|
||||
# Only uses first 2 chars of salt
|
||||
"hello world".crypt("aa").should == "aayPz4hyPS1wI"
|
||||
"hello world".crypt("aab").should == "aayPz4hyPS1wI"
|
||||
"hello world".crypt("aabc").should == "aayPz4hyPS1wI"
|
||||
end
|
||||
|
||||
"".crypt(obj).should == "aaQSqAReePlq6"
|
||||
it "raises an ArgumentError when the string contains NUL character" do
|
||||
lambda { "poison\0null".crypt("aa") }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "calls #to_str to converts the salt arg to a String" do
|
||||
obj = mock('aa')
|
||||
obj.should_receive(:to_str).and_return("aa")
|
||||
|
||||
"".crypt(obj).should == "aaQSqAReePlq6"
|
||||
end
|
||||
|
||||
it "taints the result if either salt or self is tainted" do
|
||||
tainted_salt = "aa"
|
||||
tainted_str = "hello"
|
||||
|
||||
tainted_salt.taint
|
||||
tainted_str.taint
|
||||
|
||||
"hello".crypt("aa").tainted?.should == false
|
||||
tainted_str.crypt("aa").tainted?.should == true
|
||||
"hello".crypt(tainted_salt).tainted?.should == true
|
||||
tainted_str.crypt(tainted_salt).tainted?.should == true
|
||||
end
|
||||
|
||||
it "doesn't return subclass instances" do
|
||||
StringSpecs::MyString.new("hello").crypt("aa").should be_an_instance_of(String)
|
||||
"hello".crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
|
||||
StringSpecs::MyString.new("hello").crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
|
||||
end
|
||||
|
||||
it "raises an ArgumentError when the salt is shorter than two characters" do
|
||||
lambda { "hello".crypt("") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("f") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("\x00\x00") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("\x00a") }.should raise_error(ArgumentError)
|
||||
lambda { "hello".crypt("a\x00") }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
it "raises a type error when the salt arg can't be converted to a string" do
|
||||
lambda { "".crypt(5) }.should raise_error(TypeError)
|
||||
lambda { "".crypt(mock('x')) }.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "taints the result if either salt or self is tainted" do
|
||||
tainted_salt = "aa"
|
||||
tainted_str = "hello"
|
||||
|
||||
tainted_salt.taint
|
||||
tainted_str.taint
|
||||
|
||||
"hello".crypt("aa").tainted?.should == false
|
||||
tainted_str.crypt("aa").tainted?.should == true
|
||||
"hello".crypt(tainted_salt).tainted?.should == true
|
||||
tainted_str.crypt(tainted_salt).tainted?.should == true
|
||||
end
|
||||
|
||||
it "doesn't return subclass instances" do
|
||||
StringSpecs::MyString.new("hello").crypt("aa").should be_an_instance_of(String)
|
||||
"hello".crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
|
||||
StringSpecs::MyString.new("hello").crypt(StringSpecs::MyString.new("aa")).should be_an_instance_of(String)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -114,24 +114,24 @@ describe 'Socket#connect_nonblock' do
|
|||
platform_is_not :windows do
|
||||
it 'raises Errno::EISCONN when already connected' do
|
||||
@server.listen(1)
|
||||
@client.connect(@server.getsockname).should == 0
|
||||
@client.connect(@server.connect_address).should == 0
|
||||
|
||||
lambda {
|
||||
@client.connect_nonblock(@server.getsockname)
|
||||
@client.connect_nonblock(@server.connect_address)
|
||||
|
||||
# A second call needed if non-blocking sockets become default
|
||||
# XXX honestly I don't expect any real code to care about this spec
|
||||
# as it's too implementation-dependent and checking for connect()
|
||||
# errors is futile anyways because of TOCTOU
|
||||
@client.connect_nonblock(@server.getsockname)
|
||||
@client.connect_nonblock(@server.connect_address)
|
||||
}.should raise_error(Errno::EISCONN)
|
||||
end
|
||||
|
||||
it 'returns 0 when already connected in exceptionless mode' do
|
||||
@server.listen(1)
|
||||
@client.connect(@server.getsockname).should == 0
|
||||
@client.connect(@server.connect_address).should == 0
|
||||
|
||||
@client.connect_nonblock(@server.getsockname, exception: false).should == 0
|
||||
@client.connect_nonblock(@server.connect_address, exception: false).should == 0
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -140,7 +140,7 @@ describe 'Socket#connect_nonblock' do
|
|||
@server.bind(@sockaddr)
|
||||
|
||||
lambda {
|
||||
@client.connect_nonblock(@server.getsockname)
|
||||
@client.connect_nonblock(@server.connect_address)
|
||||
}.should raise_error(IO::EINPROGRESSWaitWritable)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,7 +30,13 @@ describe 'UDPSocket#initialize' do
|
|||
@socket.binmode?.should be_true
|
||||
end
|
||||
|
||||
it 'raises Errno::EAFNOSUPPORT when given an invalid address family' do
|
||||
lambda { UDPSocket.new(666) }.should raise_error(Errno::EAFNOSUPPORT)
|
||||
it 'raises Errno::EAFNOSUPPORT or Errno::EPROTONOSUPPORT when given an invalid address family' do
|
||||
begin
|
||||
UDPSocket.new(666)
|
||||
rescue Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT => e
|
||||
[Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT].should include(e.class)
|
||||
else
|
||||
raise "expected Errno::EAFNOSUPPORT or Errno::EPROTONOSUPPORT exception raised"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче