git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64180 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2018-08-03 16:19:40 +00:00
Родитель aeeaadaad0
Коммит b53cf149ad
246 изменённых файлов: 9108 добавлений и 548 удалений

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

@ -92,6 +92,13 @@ In similar fashion, the following commands run the respective specs:
See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md).
### Socket specs from rubysl-socket
Most specs under `library/socket` were imported from [the rubysl-socket project](https://github.com/rubysl/rubysl-socket).
The 3 copyright holders of rubysl-socket, Yorick Peterse, Chuck Remes and
Brian Shirai, [agreed to relicense those specs](https://github.com/rubysl/rubysl-socket/issues/15)
under the MIT license in ruby/spec.
### History and RubySpec
This project was originally born from [Rubinius](https://github.com/rubinius/rubinius) tests being converted to the spec style.

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

@ -22,7 +22,7 @@ describe "Processing RUBYOPT" do
result.should =~ /value of \$DEBUG is true/
end
unless CROSS_COMPILING
guard -> { not CROSS_COMPILING } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION

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

@ -111,6 +111,31 @@ describe "Array#reject!" do
lambda { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(frozen_error_class)
end
it "does not truncate the array is the block raises an exception" do
a = [1, 2, 3]
begin
a.reject! { raise StandardError, 'Oops' }
rescue
end
a.should == [1, 2, 3]
end
ruby_version_is "2.4" do
it "only removes elements for which the block returns true, keeping the element which raised an error." do
a = [1, 2, 3, 4]
begin
a.reject! do |x|
return true if x == 2
raise raise StandardError, 'Oops' if x == 3
end
rescue
end
a.should == [1, 3, 4]
end
end
it_behaves_like :enumeratorize, :reject!
it_behaves_like :enumeratorized_with_origin_size, :reject!, [1,2,3]
it_behaves_like :delete_if, :reject!

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

@ -23,6 +23,54 @@ describe "Binding#eval" do
bind2.local_variables.should == []
end
it "inherits __LINE__ from the enclosing scope" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__LINE__").should == obj.get_line_of_binding
end
it "preserves __LINE__ across multiple calls to eval" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__LINE__").should == obj.get_line_of_binding
bind.eval("__LINE__").should == obj.get_line_of_binding
end
it "increments __LINE__ on each line of a multiline eval" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("#foo\n__LINE__").should == obj.get_line_of_binding + 1
end
it "inherits __LINE__ from the enclosing scope even if the Binding is created with #send" do
obj = BindingSpecs::Demo.new(1)
bind, line = obj.get_binding_with_send_and_line
bind.eval("__LINE__").should == line
end
it "starts with a __LINE__ of 1 if a filename is passed" do
bind = BindingSpecs::Demo.new(1).get_binding
bind.eval("__LINE__", "(test)").should == 1
bind.eval("#foo\n__LINE__", "(test)").should == 2
end
it "starts with a __LINE__ from the third argument if passed" do
bind = BindingSpecs::Demo.new(1).get_binding
bind.eval("__LINE__", "(test)", 88).should == 88
bind.eval("#foo\n__LINE__", "(test)", 88).should == 89
end
it "inherits __FILE__ from the enclosing scope" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__FILE__").should == obj.get_file_of_binding
end
it "uses the __FILE__ that is passed in" do
bind = BindingSpecs::Demo.new(1).get_binding
bind.eval("__FILE__", "(test)").should == "(test)"
end
describe "with a file given" do
it "does not store the filename permanently" do
obj = BindingSpecs::Demo.new(1)
@ -33,5 +81,15 @@ describe "Binding#eval" do
end
end
it "needs to be reviewed for spec completeness"
it "with __method__ returns the method where the Binding was created" do
obj = BindingSpecs::Demo.new(1)
bind, meth = obj.get_binding_and_method
bind.eval("__method__").should == meth
end
it "with __method__ returns the method where the Binding was created, ignoring #send" do
obj = BindingSpecs::Demo.new(1)
bind, meth = obj.get_binding_with_send_and_method
bind.eval("__method__").should == meth
end
end

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

@ -25,6 +25,18 @@ module BindingSpecs
__FILE__
end
def get_binding_with_send_and_line
[send(:binding), __LINE__]
end
def get_binding_and_method
[binding, :get_binding_and_method]
end
def get_binding_with_send_and_method
[send(:binding), :get_binding_with_send_and_method]
end
def get_empty_binding
binding
end

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

@ -1,46 +0,0 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Binding#eval" do
it "inherits __LINE__ from the enclosing scope" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__LINE__").should == obj.get_line_of_binding
end
it "preserves __LINE__ across multiple calls to eval" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__LINE__").should == obj.get_line_of_binding
bind.eval("__LINE__").should == obj.get_line_of_binding
end
it "increments __LINE__ on each line of a multiline eval" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("#foo\n__LINE__").should == obj.get_line_of_binding + 1
end
it "starts with a __LINE__ of 1 if a filename is passed" do
bind = BindingSpecs::Demo.new(1).get_binding
bind.eval("__LINE__", "(test)").should == 1
bind.eval("#foo\n__LINE__", "(test)").should == 2
end
it "starts with a __LINE__ from the third argument if passed" do
bind = BindingSpecs::Demo.new(1).get_binding
bind.eval("__LINE__", "(test)", 88).should == 88
bind.eval("#foo\n__LINE__", "(test)", 88).should == 89
end
it "inherits __FILE__ from the enclosing scope" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__FILE__").should == obj.get_file_of_binding
end
it "uses the __FILE__ that is passed in" do
bind = BindingSpecs::Demo.new(1).get_binding
bind.eval("__FILE__", "(test)").should == "(test)"
end
end

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

@ -32,5 +32,12 @@ describe "Enumerable#sort_by" do
b.sort_by{ |x| -x }.should == [3, 2, 1]
end
it "calls #each to iterate over the elements to be sorted" do
b = EnumerableSpecs::Numerous.new( 1, 2, 3 )
b.should_receive(:each).once.and_yield(1).and_yield(2).and_yield(3)
b.should_not_receive :map
b.sort_by { |x| -x }.should == [3, 2, 1]
end
it_behaves_like :enumerable_enumeratorized_with_origin_size, :sort_by
end

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

@ -27,6 +27,10 @@ describe "IO.read" do
IO.read(@fname, {}).should == @contents
end
it "accepts a length, and empty options Hash" do
IO.read(@fname, 3, {}).should == @contents[0, 3]
end
it "accepts a length, offset, and empty options Hash" do
IO.read(@fname, 3, 0, {}).should == @contents[0, 3]
end

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

@ -85,9 +85,9 @@ describe :io_write, shared: true do
@r.read.should == "foo"
end
it "raises Errno::EPIPE if the read end is closed" do
it "raises Errno::EPIPE if the read end is closed and does not die from SIGPIPE" do
@r.close
-> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, "Broken pipe")
-> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, /Broken pipe/)
end
end
end

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

@ -5,6 +5,13 @@ describe "Kernel#__dir__" do
__dir__.should == File.realpath(File.dirname(__FILE__))
end
context "when used in eval with a given filename" do
it "returns File.dirname(filename)" do
eval("__dir__", nil, "foo.rb").should == "."
eval("__dir__", nil, "foo/bar.rb").should == "foo"
end
end
context "when used in eval with top level binding" do
it "returns the real name of the directory containing the currently-executing file" do
eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__))

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

@ -7,7 +7,7 @@ require_relative 'fixtures/classes'
autoload :KSAutoloadA, "autoload_a.rb"
autoload :KSAutoloadB, fixture(__FILE__, "autoload_b.rb")
autoload :KSAutoloadC, fixture(__FILE__, "autoload_c.rb")
autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
def check_autoload(const)
autoload? const
@ -42,10 +42,11 @@ describe "Kernel#autoload" do
KSAutoloadB.loaded.should == :ksautoload_b
end
it "does not call Kernel.require or Kernel.load to load the file" do
Kernel.should_not_receive(:require)
Kernel.should_not_receive(:load)
KSAutoloadC.loaded.should == :ksautoload_c
it "calls main.require(path) to load the file" do
main = TOPLEVEL_BINDING.eval("self")
main.should_receive(:require).with("main_autoload_not_exist.rb")
# The constant won't be defined since require is mocked to do nothing
-> { KSAutoloadCallsRequire }.should raise_error(NameError)
end
it "can autoload in instance_eval" do

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

@ -1,5 +0,0 @@
module KSAutoloadC
def self.loaded
:ksautoload_c
end
end

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

@ -199,6 +199,46 @@ describe "Kernel#require_relative with a relative path" do
$LOADED_FEATURES.should include(@abs_path)
end
platform_is_not :windows do
describe "with symlinks" do
before :each do
@symlink_to_code_dir = tmp("codesymlink")
File.symlink(CODE_LOADING_DIR, @symlink_to_code_dir)
@symlink_basename = File.basename(@symlink_to_code_dir)
@requiring_file = tmp("requiring")
end
after :each do
rm_r @symlink_to_code_dir, @requiring_file
end
it "does not canonicalize the path and stores a path with symlinks" do
symlink_path = "#{@symlink_basename}/load_fixture.rb"
absolute_path = "#{tmp("")}#{symlink_path}"
canonical_path = "#{CODE_LOADING_DIR}/load_fixture.rb"
touch(@requiring_file) { |f|
f.puts "require_relative #{symlink_path.inspect}"
}
load(@requiring_file)
ScratchPad.recorded.should == [:loaded]
features = $LOADED_FEATURES.select { |path| path.end_with?('load_fixture.rb') }
features.should include(absolute_path)
features.should_not include(canonical_path)
end
it "stores the same path that __FILE__ returns in the required file" do
symlink_path = "#{@symlink_basename}/load_fixture_and__FILE__.rb"
touch(@requiring_file) { |f|
f.puts "require_relative #{symlink_path.inspect}"
}
load(@requiring_file)
loaded_feature = $LOADED_FEATURES.last
ScratchPad.recorded.should == [loaded_feature]
end
end
end
it "does not store the path if the load fails" do
saved_loaded_features = $LOADED_FEATURES.dup
lambda { require_relative("#{@dir}/raise_fixture.rb") }.should raise_error(RuntimeError)

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

@ -17,7 +17,6 @@ describe "Kernel#require" do
end
it_behaves_like :kernel_require_basic, :require, CodeLoadingSpecs::Method.new
it_behaves_like :kernel_require, :require, CodeLoadingSpecs::Method.new
end
@ -31,6 +30,5 @@ describe "Kernel.require" do
end
it_behaves_like :kernel_require_basic, :require, Kernel
it_behaves_like :kernel_require, :require, Kernel
end

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

@ -305,6 +305,80 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES.should include(@path)
end
platform_is_not :windows do
describe "with symlinks" do
before :each do
@symlink_to_code_dir = tmp("codesymlink")
File.symlink(CODE_LOADING_DIR, @symlink_to_code_dir)
$LOAD_PATH.delete(CODE_LOADING_DIR)
$LOAD_PATH.unshift(@symlink_to_code_dir)
end
after :each do
rm_r @symlink_to_code_dir
end
it "does not canonicalize the path and stores a path with symlinks" do
symlink_path = "#{@symlink_to_code_dir}/load_fixture.rb"
canonical_path = "#{CODE_LOADING_DIR}/load_fixture.rb"
@object.require(symlink_path).should be_true
ScratchPad.recorded.should == [:loaded]
features = $LOADED_FEATURES.select { |path| path.end_with?('load_fixture.rb') }
features.should include(symlink_path)
features.should_not include(canonical_path)
end
it "stores the same path that __FILE__ returns in the required file" do
symlink_path = "#{@symlink_to_code_dir}/load_fixture_and__FILE__.rb"
@object.require(symlink_path).should be_true
loaded_feature = $LOADED_FEATURES.last
ScratchPad.recorded.should == [loaded_feature]
end
end
describe "with symlinks in the required feature and $LOAD_PATH" do
before :each do
@dir = tmp("realdir")
mkdir_p @dir
@file = "#{@dir}/realfile.rb"
touch(@file) { |f| f.puts 'ScratchPad << __FILE__' }
@symlink_to_dir = tmp("symdir").freeze
File.symlink(@dir, @symlink_to_dir)
@symlink_to_file = "#{@dir}/symfile.rb"
File.symlink("realfile.rb", @symlink_to_file)
end
after :each do
rm_r @dir, @symlink_to_dir
end
ruby_version_is ""..."2.4.4" do
it "canonicalizes neither the entry in $LOAD_PATH nor the filename passed to #require" do
$LOAD_PATH.unshift(@symlink_to_dir)
@object.require("symfile").should be_true
loaded_feature = "#{@symlink_to_dir}/symfile.rb"
ScratchPad.recorded.should == [loaded_feature]
$".last.should == loaded_feature
$LOAD_PATH[0].should == @symlink_to_dir
end
end
ruby_version_is "2.4.4" do
it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do
$LOAD_PATH.unshift(@symlink_to_dir)
@object.require("symfile").should be_true
loaded_feature = "#{@dir}/symfile.rb"
ScratchPad.recorded.should == [loaded_feature]
$".last.should == loaded_feature
$LOAD_PATH[0].should == @symlink_to_dir
end
end
end
end
it "does not store the path if the load fails" do
$LOAD_PATH << CODE_LOADING_DIR
saved_loaded_features = $LOADED_FEATURES.dup
@ -417,7 +491,7 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES.should include(@path)
end
it "canonicalizes non-unique absolute paths" do
it "expands absolute paths containing .." do
path = File.join CODE_LOADING_DIR, "..", "code", "load_fixture.rb"
@object.require(path).should be_true
$LOADED_FEATURES.should include(@path)

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

@ -105,6 +105,14 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::J.should == :autoload_j
end
it "calls main.require(path) to load the file" do
ModuleSpecs::Autoload.autoload :ModuleAutoloadCallsRequire, "module_autoload_not_exist.rb"
main = TOPLEVEL_BINDING.eval("self")
main.should_receive(:require).with("module_autoload_not_exist.rb")
# The constant won't be defined since require is mocked to do nothing
-> { ModuleSpecs::Autoload::ModuleAutoloadCallsRequire }.should raise_error(NameError)
end
it "does not load the file if the file is manually required" do
filename = fixture(__FILE__, "autoload_k.rb")
ModuleSpecs::Autoload.autoload :KHash, filename
@ -158,28 +166,169 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.use_ex1.should == :good
end
it "does not load the file when referring to the constant in defined?" do
module ModuleSpecs::Autoload::Q
autoload :R, fixture(__FILE__, "autoload.rb")
defined?(R).should == "constant"
describe "interacting with defined?" do
it "does not load the file when referring to the constant in defined?" do
module ModuleSpecs::Autoload::Dog
autoload :R, fixture(__FILE__, "autoload_exception.rb")
end
defined?(ModuleSpecs::Autoload::Dog::R).should == "constant"
ScratchPad.recorded.should be_nil
ModuleSpecs::Autoload::Dog.should have_constant(:R)
end
it "loads an autoloaded parent when referencing a nested constant" do
module ModuleSpecs::Autoload
autoload :GoodParent, fixture(__FILE__, "autoload_nested.rb")
end
defined?(ModuleSpecs::Autoload::GoodParent::Nested).should == 'constant'
ScratchPad.recorded.should == :loaded
ModuleSpecs::Autoload.send(:remove_const, :GoodParent)
end
it "returns nil when it fails to load an autoloaded parent when referencing a nested constant" do
module ModuleSpecs::Autoload
autoload :BadParent, fixture(__FILE__, "autoload_exception.rb")
end
defined?(ModuleSpecs::Autoload::BadParent::Nested).should be_nil
ScratchPad.recorded.should == :exception
end
ModuleSpecs::Autoload::Q.should have_constant(:R)
end
it "does not remove the constant from the constant table if load fails" do
describe "during the autoload before the constant is assigned" do
before :each do
@path = fixture(__FILE__, "autoload_during_autoload.rb")
ModuleSpecs::Autoload.autoload :DuringAutoload, @path
raise unless ModuleSpecs::Autoload.autoload?(:DuringAutoload) == @path
end
after :each do
ModuleSpecs::Autoload.send(:remove_const, :DuringAutoload)
end
def check_before_during_thread_after(&check)
before = check.call
to_autoload_thread, from_autoload_thread = Queue.new, Queue.new
ScratchPad.record -> {
from_autoload_thread.push check.call
to_autoload_thread.pop
}
t = Thread.new {
in_loading_thread = from_autoload_thread.pop
in_other_thread = check.call
to_autoload_thread.push :done
[in_loading_thread, in_other_thread]
}
in_loading_thread, in_other_thread = nil
begin
ModuleSpecs::Autoload::DuringAutoload
ensure
in_loading_thread, in_other_thread = t.value
end
after = check.call
[before, in_loading_thread, in_other_thread, after]
end
it "returns nil in autoload thread and 'constant' otherwise for defined?" do
results = check_before_during_thread_after {
defined?(ModuleSpecs::Autoload::DuringAutoload)
}
results.should == ['constant', nil, 'constant', 'constant']
end
it "keeps the constant in Module#constants" do
results = check_before_during_thread_after {
ModuleSpecs::Autoload.constants(false).include?(:DuringAutoload)
}
results.should == [true, true, true, true]
end
it "returns false in autoload thread and true otherwise for Module#const_defined?" do
results = check_before_during_thread_after {
ModuleSpecs::Autoload.const_defined?(:DuringAutoload, false)
}
results.should == [true, false, true, true]
end
it "returns nil in autoload thread and returns the path in other threads for Module#autoload?" do
results = check_before_during_thread_after {
ModuleSpecs::Autoload.autoload?(:DuringAutoload)
}
results.should == [@path, nil, @path, nil]
end
end
it "does not remove the constant from Module#constants if load fails and keeps it as an autoload" do
ModuleSpecs::Autoload.autoload :Fail, @non_existent
ModuleSpecs::Autoload.const_defined?(:Fail).should == true
ModuleSpecs::Autoload.should have_constant(:Fail)
ModuleSpecs::Autoload.autoload?(:Fail).should == @non_existent
lambda { ModuleSpecs::Autoload::Fail }.should raise_error(LoadError)
ModuleSpecs::Autoload.should have_constant(:Fail)
ModuleSpecs::Autoload.const_defined?(:Fail).should == true
ModuleSpecs::Autoload.autoload?(:Fail).should == @non_existent
lambda { ModuleSpecs::Autoload::Fail }.should raise_error(LoadError)
end
it "does not remove the constant from the constant table if the loaded files does not define it" do
ModuleSpecs::Autoload.autoload :O, fixture(__FILE__, "autoload_o.rb")
it "does not remove the constant from Module#constants if load raises a RuntimeError and keeps it as an autoload" do
path = fixture(__FILE__, "autoload_raise.rb")
ScratchPad.record []
ModuleSpecs::Autoload.autoload :Raise, path
ModuleSpecs::Autoload.const_defined?(:Raise).should == true
ModuleSpecs::Autoload.should have_constant(:Raise)
ModuleSpecs::Autoload.autoload?(:Raise).should == path
lambda { ModuleSpecs::Autoload::Raise }.should raise_error(RuntimeError)
ScratchPad.recorded.should == [:raise]
ModuleSpecs::Autoload.should have_constant(:Raise)
ModuleSpecs::Autoload.const_defined?(:Raise).should == true
ModuleSpecs::Autoload.autoload?(:Raise).should == path
lambda { ModuleSpecs::Autoload::Raise }.should raise_error(RuntimeError)
ScratchPad.recorded.should == [:raise, :raise]
end
it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
ModuleSpecs::Autoload.autoload :O, path
ModuleSpecs::Autoload.const_defined?(:O).should == true
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.autoload?(:O).should == path
lambda { ModuleSpecs::Autoload::O }.should raise_error(NameError)
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.const_defined?(:O).should == false
ModuleSpecs::Autoload.autoload?(:O).should == nil
-> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
end
it "does not try to load the file again if the loaded file did not define the constant" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
ModuleSpecs::Autoload.autoload :NotDefinedByFile, path
-> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
ScratchPad.recorded.should == [:loaded]
-> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
ScratchPad.recorded.should == [:loaded]
Thread.new {
-> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
}.join
ScratchPad.recorded.should == [:loaded]
end
it "returns 'constant' on referring the constant with defined?()" do
@ -216,7 +365,6 @@ describe "Module#autoload" do
end
it "loads the file that defines subclass XX::YY < YY and YY is a top level constant" do
module ModuleSpecs::Autoload::XX
autoload :YY, fixture(__FILE__, "autoload_subclass.rb")
end
@ -224,30 +372,130 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::XX::YY.superclass.should == YY
end
describe "after autoloading searches for the constant like the original lookup" do
it "in lexical scopes if both declared and defined in parent" do
module ModuleSpecs::Autoload
ScratchPad.record -> {
DeclaredAndDefinedInParent = :declared_and_defined_in_parent
}
autoload :DeclaredAndDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
class LexicalScope
DeclaredAndDefinedInParent.should == :declared_and_defined_in_parent
it "looks up the constant in the scope where it is referred" do
module ModuleSpecs
module Autoload
autoload :QQ, fixture(__FILE__, "autoload_scope.rb")
class PP
QQ.new.should be_kind_of(ModuleSpecs::Autoload::PP::QQ)
# The constant is really in Autoload, not Autoload::LexicalScope
self.should_not have_constant(:DeclaredAndDefinedInParent)
-> { const_get(:DeclaredAndDefinedInParent) }.should raise_error(NameError)
end
DeclaredAndDefinedInParent.should == :declared_and_defined_in_parent
end
end
it "in lexical scopes if declared in parent and defined in current" do
module ModuleSpecs::Autoload
ScratchPad.record -> {
class LexicalScope
DeclaredInParentDefinedInCurrent = :declared_in_parent_defined_in_current
end
}
autoload :DeclaredInParentDefinedInCurrent, fixture(__FILE__, "autoload_callback.rb")
class LexicalScope
DeclaredInParentDefinedInCurrent.should == :declared_in_parent_defined_in_current
LexicalScope::DeclaredInParentDefinedInCurrent.should == :declared_in_parent_defined_in_current
end
# Basically, the parent autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInParentDefinedInCurrent).should == nil
const_defined?(:DeclaredInParentDefinedInCurrent).should == false
self.should have_constant(:DeclaredInParentDefinedInCurrent)
-> { DeclaredInParentDefinedInCurrent }.should raise_error(NameError)
ModuleSpecs::Autoload::LexicalScope.send(:remove_const, :DeclaredInParentDefinedInCurrent)
end
end
it "and fails when finding the undefined autoload constant in the the current scope when declared in current and defined in parent" do
module ModuleSpecs::Autoload
ScratchPad.record -> {
DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
}
class LexicalScope
autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
-> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError)
# Basically, the autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
const_defined?(:DeclaredInCurrentDefinedInParent).should == false
self.should have_constant(:DeclaredInCurrentDefinedInParent)
-> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
end
DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
end
end
it "in the included modules" do
module ModuleSpecs::Autoload
ScratchPad.record -> {
module DefinedInIncludedModule
Incl = :defined_in_included_module
end
include DefinedInIncludedModule
}
autoload :Incl, fixture(__FILE__, "autoload_callback.rb")
Incl.should == :defined_in_included_module
end
end
it "in the included modules of the superclass" do
module ModuleSpecs::Autoload
class LookupAfterAutoloadSuper
end
class LookupAfterAutoloadChild < LookupAfterAutoloadSuper
end
ScratchPad.record -> {
module DefinedInSuperclassIncludedModule
InclS = :defined_in_superclass_included_module
end
LookupAfterAutoloadSuper.include DefinedInSuperclassIncludedModule
}
class LookupAfterAutoloadChild
autoload :InclS, fixture(__FILE__, "autoload_callback.rb")
InclS.should == :defined_in_superclass_included_module
end
end
end
end
it "looks up the constant when in a meta class scope" do
module ModuleSpecs
module Autoload
autoload :R, fixture(__FILE__, "autoload_r.rb")
it "in the prepended modules" do
module ModuleSpecs::Autoload
ScratchPad.record -> {
module DefinedInPrependedModule
Prep = :defined_in_prepended_module
end
include DefinedInPrependedModule
}
autoload :Prep, fixture(__FILE__, "autoload_callback.rb")
Prep.should == :defined_in_prepended_module
end
end
it "in a meta class scope" do
module ModuleSpecs::Autoload
ScratchPad.record -> {
class MetaScope
end
}
autoload :MetaScope, fixture(__FILE__, "autoload_callback.rb")
class << self
def r
R.new
MetaScope.new
end
end
end
ModuleSpecs::Autoload.r.should be_kind_of(ModuleSpecs::Autoload::MetaScope)
end
ModuleSpecs::Autoload.r.should be_kind_of(ModuleSpecs::Autoload::R)
end
# [ruby-core:19127] [ruby-core:29941]
@ -266,6 +514,21 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::W.send(:remove_const, :Y)
end
it "does not call #require a second time and does not warn if already loading the same feature with #require" do
main = TOPLEVEL_BINDING.eval("self")
main.should_not_receive(:require)
module ModuleSpecs::Autoload
autoload :AutoloadDuringRequire, fixture(__FILE__, "autoload_during_require.rb")
end
-> {
$VERBOSE = true
Kernel.require fixture(__FILE__, "autoload_during_require.rb")
}.should_not complain
ModuleSpecs::Autoload::AutoloadDuringRequire.should be_kind_of(Class)
end
it "calls #to_path on non-string filenames" do
p = mock('path')
p.should_receive(:to_path).and_return @non_existent

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

@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative '../../fixtures/constants'
require_relative 'fixtures/constants_autoload'
describe "Module#const_get" do
it "accepts a String or Symbol name" do
@ -95,6 +96,10 @@ describe "Module#const_get" do
ConstantSpecs.const_get("ClassA::CS_CONST10").should == :const10_10
end
it "raises a NameError if the name includes two successive scope separators" do
lambda { ConstantSpecs.const_get("ClassA::::CS_CONST10") }.should raise_error(NameError)
end
it "raises a NameError if only '::' is passed" do
lambda { ConstantSpecs.const_get("::") }.should raise_error(NameError)
end
@ -111,6 +116,22 @@ describe "Module#const_get" do
ConstantSpecs.const_get(:CS_PRIVATE).should == :cs_private
end
it 'does autoload a constant' do
Object.const_get('CSAutoloadA').name.should == 'CSAutoloadA'
end
it 'does autoload a constant with a toplevel scope qualifier' do
Object.const_get('::CSAutoloadB').name.should == 'CSAutoloadB'
end
it 'does autoload a module and resolve a constant within' do
Object.const_get('CSAutoloadC::CONST').should == 7
end
it 'does autoload a non-toplevel module' do
Object.const_get('CSAutoloadD::InnerModule').name.should == 'CSAutoloadD::InnerModule'
end
describe "with statically assigned constants" do
it "searches the immediate class or module first" do
ConstantSpecs::ClassA.const_get(:CS_CONST10).should == :const10_10

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

@ -0,0 +1,2 @@
block = ScratchPad.recorded
block.call

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

@ -0,0 +1,7 @@
block = ScratchPad.recorded
ScratchPad.record(block.call)
module ModuleSpecs::Autoload
class DuringAutoload
end
end

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

@ -0,0 +1,4 @@
module ModuleSpecs::Autoload
class AutoloadDuringRequire
end
end

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

@ -0,0 +1,3 @@
ScratchPad.record(:exception)
raise 'intentional error to test failure conditions during autoloading'

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

@ -0,0 +1,8 @@
module ModuleSpecs::Autoload
module GoodParent
class Nested
end
end
end
ScratchPad.record(:loaded)

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

@ -1 +1,2 @@
# does not define ModuleSpecs::Autoload::O
ScratchPad << :loaded

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

@ -0,0 +1,2 @@
ScratchPad << :raise
raise "exception during autoload"

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

@ -1,8 +0,0 @@
module ModuleSpecs
module Autoload
class PP
class QQ
end
end
end
end

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

@ -0,0 +1,6 @@
autoload :CSAutoloadA, fixture(__FILE__, 'constants_autoload_a.rb')
autoload :CSAutoloadB, fixture(__FILE__, 'constants_autoload_b.rb')
autoload :CSAutoloadC, fixture(__FILE__, 'constants_autoload_c.rb')
module CSAutoloadD
autoload :InnerModule, fixture(__FILE__, 'constants_autoload_d.rb')
end

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

@ -0,0 +1,2 @@
module CSAutoloadA
end

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

@ -0,0 +1,2 @@
module CSAutoloadB
end

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

@ -0,0 +1,3 @@
module CSAutoloadC
CONST = 7
end

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

@ -0,0 +1,4 @@
module CSAutoloadD
module InnerModule
end
end

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

@ -7,4 +7,12 @@ describe "Module#initialize_copy" do
end
mod.dup.methods(false).should == [:hello]
end
# jruby/jruby#5245, https://bugs.ruby-lang.org/issues/3461
it "should produce a duped module with inspectable class methods" do
mod = Module.new
def mod.hello
end
mod.dup.method(:hello).inspect.should =~ /Module.*hello/
end
end

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

@ -0,0 +1,8 @@
reserved_signals = ARGV
(Signal.list.keys - reserved_signals).each do |signal|
Signal.trap(signal, -> {})
Signal.trap(signal, "DEFAULT")
end
puts "OK"

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

@ -115,6 +115,49 @@ platform_is_not :windows do
end
describe "Signal.trap" do
cannot_be_trapped = %w[KILL STOP] # See man 2 signal
reserved_signals = %w[VTALRM]
if PlatformGuard.implementation?(:ruby)
reserved_signals += %w[SEGV ILL FPE BUS]
end
if PlatformGuard.implementation?(:truffleruby)
if !TruffleRuby.native?
reserved_signals += %w[SEGV ILL FPE USR1 QUIT]
end
end
if PlatformGuard.implementation?(:jruby)
reserved_signals += %w[SEGV ILL FPE BUS USR1 QUIT]
end
cannot_be_trapped.each do |signal|
it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do
-> {
trap(signal, -> {})
}.should raise_error(StandardError) { |e|
[ArgumentError, Errno::EINVAL].should include(e.class)
e.message.should =~ /Invalid argument|Signal already used by VM or OS/
}
end
end
reserved_signals.each do |signal|
it "raises ArgumentError for reserved signal SIG#{signal}" do
-> {
trap(signal, -> {})
}.should raise_error(ArgumentError, /can't trap reserved signal|Signal already used by VM or OS/)
end
end
it "allows to register a handler for all known signals, except reserved signals" do
excluded = cannot_be_trapped + reserved_signals
out = ruby_exe(fixture(__FILE__, "trap_all.rb"), args: [*excluded, "2>&1"])
out.should == "OK\n"
$?.exitstatus.should == 0
end
it "returns SYSTEM_DEFAULT if passed DEFAULT and no handler was ever set" do
Signal.trap("PROF", "DEFAULT").should == "SYSTEM_DEFAULT"
end

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

@ -6,6 +6,26 @@ with_feature :encoding do
"abc".force_encoding('shift_jis').encoding.should == Encoding::Shift_JIS
end
describe "with a special encoding name" do
before :each do
@original_encoding = Encoding.default_internal
end
after :each do
Encoding.default_internal = @original_encoding
end
it "accepts valid special encoding names" do
Encoding.default_internal = "US-ASCII"
"abc".force_encoding("internal").encoding.should == Encoding::US_ASCII
end
it "defaults to ASCII-8BIT if special encoding name is not set" do
Encoding.default_internal = nil
"abc".force_encoding("internal").encoding.should == Encoding::ASCII_8BIT
end
end
it "accepts an Encoding instance" do
"abc".force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::Shift_JIS
end

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

@ -9,4 +9,42 @@ describe 'Thread::Backtrace::Location#absolute_path' do
it 'returns the absolute path of the call frame' do
@frame.absolute_path.should == File.realpath(__FILE__)
end
context "when used in eval with a given filename" do
it "returns filename" do
code = "caller_locations(0)[0].absolute_path"
eval(code, nil, "foo.rb").should == "foo.rb"
eval(code, nil, "foo/bar.rb").should == "foo/bar.rb"
end
end
platform_is_not :windows do
before :each do
@file = fixture(__FILE__, "absolute_path.rb")
@symlink = tmp("symlink.rb")
File.symlink(@file, @symlink)
ScratchPad.record []
end
after :each do
rm_r @symlink
end
it "returns a canonical path without symlinks, even when __FILE__ does not" do
realpath = File.realpath(@symlink)
realpath.should_not == @symlink
load @symlink
ScratchPad.recorded.should == [@symlink, realpath]
end
it "returns a canonical path without symlinks, even when __FILE__ is removed" do
realpath = File.realpath(@symlink)
realpath.should_not == @symlink
ScratchPad << -> { rm_r(@symlink) }
load @symlink
ScratchPad.recorded.should == [@symlink, realpath]
end
end
end

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

@ -0,0 +1,4 @@
action = ScratchPad.recorded.pop
ScratchPad << __FILE__
action.call if action
ScratchPad << caller_locations(0)[0].absolute_path

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

@ -93,7 +93,7 @@ describe "Time#localtime" do
it "does nothing if already in a local time zone" do
time = with_timezone("America/New_York") do
break Time.new(2005, 2, 27, 22, 50, 0)
Time.new(2005, 2, 27, 22, 50, 0)
end
zone = time.zone

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

@ -0,0 +1 @@
ScratchPad << __FILE__

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

@ -36,6 +36,13 @@ describe "Array literals" do
[1, *nil, 3].should == [1, 3]
[*nil, *nil, *nil].should == []
end
it "evaluates each argument exactly once" do
se = ArraySpec::SideEffect.new
se.array_result(true)
se.array_result(false)
se.call_count.should == 4
end
end
describe "Bareword array literal" do

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

@ -458,16 +458,17 @@ describe "Module#private_constant marked constants" do
lambda {mod::Foo}.should raise_error(NameError)
end
it "sends #const_missing to the original class or module" do
mod = Module.new
mod.const_set :Foo, true
mod.send :private_constant, :Foo
def mod.const_missing(name)
@const_missing_arg = name
name == :Foo ? name : super
end
ruby_version_is "2.6" do
it "sends #const_missing to the original class or module" do
mod = Module.new
mod.const_set :Foo, true
mod.send :private_constant, :Foo
def mod.const_missing(name)
name == :Foo ? name : super
end
mod::Foo.should == :Foo
mod::Foo.should == :Foo
end
end
describe "in a module" do

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

@ -8,4 +8,25 @@ module ArraySpec
[a, b, c, d]
end
end
class SideEffect
def initialize()
@call_count = 0
end
attr_reader :call_count
def array_result(a_number)
[result(a_number), result(a_number)]
end
def result(a_number)
@call_count += 1
if a_number
1
else
:thing
end
end
end
end

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

@ -185,6 +185,19 @@ describe 'Optional variable assignments' do
describe 'using a #[]' do
before do
@a = {}
klass = Class.new do
def [](k)
@hash ||= {}
@hash[k]
end
def []=(k, v)
@hash ||= {}
@hash[k] = v
7
end
end
@b = klass.new
end
it 'leaves new variable unassigned' do
@ -226,6 +239,15 @@ describe 'Optional variable assignments' do
@a[:k].should == 20
end
it 'returns the assigned value, not the result of the []= method with ||=' do
(@b[:k] ||= 12).should == 12
end
it 'returns the assigned value, not the result of the []= method with +=' do
@b[:k] = 17
(@b[:k] += 12).should == 29
end
end
end

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

@ -0,0 +1,37 @@
require_relative '../../spec_helper'
require 'date'
describe "Date.iso8601" do
it "parses YYYY-MM-DD into a Date object" do
d = Date.iso8601("2018-01-01")
d.should == Date.civil(2018, 1, 1)
end
it "parses YYYYMMDD into a Date object" do
d = Date.iso8601("20180715")
d.should == Date.civil(2018, 7, 15)
end
it "parses a negative Date" do
d = Date.iso8601("-4712-01-01")
d.should == Date.civil(-4712, 1, 1)
end
it "parses a Symbol into a Date object" do
d = Date.iso8601(:'2015-10-15')
d.should == Date.civil(2015, 10, 15)
end
it "parses a StringSubclass into a Date object" do
d = Date.iso8601(Class.new(String).new("-4712-01-01"))
d.should == Date.civil(-4712, 1, 1)
end
it "raises an ArgumentError when passed a Symbol without a valid Date" do
lambda { Date.iso8601(:test) }.should raise_error(ArgumentError)
end
it "raises a TypeError when passed an Object" do
lambda { Date.iso8601(Object.new) }.should raise_error(TypeError)
end
end

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

@ -64,6 +64,11 @@ describe "Date#parse" do
d = Date.parse("19101101")
d.should == Date.civil(1910, 11, 1)
end
it "raises a TypeError trying to parse non-String-like object" do
lambda { Date.parse(1) }.should raise_error(TypeError)
lambda { Date.parse(:invalid) }.should raise_error(TypeError)
end
end
describe "Date#parse with '.' separator" do

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#afamily" do
describe "for an ipv4 socket" do
@ -24,7 +23,7 @@ describe "Addrinfo#afamily" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,6 +1,5 @@
require_relative '../../../spec_helper'
require_relative '../spec_helper'
require_relative '../fixtures/classes'
require 'socket'
describe "Addrinfo#bind" do

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

@ -1,6 +1,5 @@
require_relative '../../../spec_helper'
require_relative '../spec_helper'
require_relative '../fixtures/classes'
require 'socket'
describe "Addrinfo#canonname" do
@ -16,4 +15,13 @@ describe "Addrinfo#canonname" do
canonname.should == nil
end
end
describe 'when the canonical name is not available' do
it 'returns nil' do
addr = Addrinfo.new(Socket.sockaddr_in(0, '127.0.0.1'))
addr.canonname.should be_nil
end
end
end

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

@ -0,0 +1,75 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe 'Addrinfo#connect_from' do
SocketSpecs.each_ip_protocol do |family, ip_address|
before do
@server = TCPServer.new(ip_address, 0)
@port = @server.connect_address.ip_port
@addr = Addrinfo.tcp(ip_address, @port)
end
after do
@socket.close if @socket
@server.close
end
describe 'using separate arguments' do
it 'returns a Socket when no block is given' do
@socket = @addr.connect_from(ip_address, 0)
@socket.should be_an_instance_of(Socket)
end
it 'yields the Socket when a block is given' do
@addr.connect_from(ip_address, 0) do |socket|
socket.should be_an_instance_of(Socket)
end
end
it 'treats the last argument as a set of options if it is a Hash' do
@socket = @addr.connect_from(ip_address, 0, timeout: 2)
@socket.should be_an_instance_of(Socket)
end
it 'binds the socket to the local address' do
@socket = @addr.connect_from(ip_address, 0)
@socket.local_address.ip_address.should == ip_address
@socket.local_address.ip_port.should > 0
@socket.local_address.ip_port.should_not == @port
end
end
describe 'using an Addrinfo as the 1st argument' do
before do
@from_addr = Addrinfo.tcp(ip_address, 0)
end
it 'returns a Socket when no block is given' do
@socket = @addr.connect_from(@from_addr)
@socket.should be_an_instance_of(Socket)
end
it 'yields the Socket when a block is given' do
@addr.connect_from(@from_addr) do |socket|
socket.should be_an_instance_of(Socket)
end
end
it 'treats the last argument as a set of options if it is a Hash' do
@socket = @addr.connect_from(@from_addr, timeout: 2)
@socket.should be_an_instance_of(Socket)
end
it 'binds the socket to the local address' do
@socket = @addr.connect_from(@from_addr)
@socket.local_address.ip_address.should == ip_address
@socket.local_address.ip_port.should > 0
@socket.local_address.ip_port.should_not == @port
end
end
end
end

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

@ -0,0 +1,35 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe 'Addrinfo#connect' do
SocketSpecs.each_ip_protocol do |family, ip_address|
before do
@server = TCPServer.new(ip_address, 0)
@port = @server.connect_address.ip_port
end
after do
@socket.close if @socket
@server.close
end
it 'returns a Socket when no block is given' do
addr = Addrinfo.tcp(ip_address, @port)
@socket = addr.connect
@socket.should be_an_instance_of(Socket)
end
it 'yields a Socket when a block is given' do
addr = Addrinfo.tcp(ip_address, @port)
addr.connect do |socket|
socket.should be_an_instance_of(Socket)
end
end
it 'accepts a Hash of options' do
addr = Addrinfo.tcp(ip_address, @port)
@socket = addr.connect(timeout: 2)
@socket.should be_an_instance_of(Socket)
end
end
end

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

@ -0,0 +1,75 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe 'Addrinfo#connect_to' do
SocketSpecs.each_ip_protocol do |family, ip_address|
before do
@server = TCPServer.new(ip_address, 0)
@port = @server.connect_address.ip_port
@addr = Addrinfo.tcp(ip_address, 0)
end
after do
@socket.close if @socket
@server.close
end
describe 'using separate arguments' do
it 'returns a Socket when no block is given' do
@socket = @addr.connect_to(ip_address, @port)
@socket.should be_an_instance_of(Socket)
end
it 'yields the Socket when a block is given' do
@addr.connect_to(ip_address, @port) do |socket|
socket.should be_an_instance_of(Socket)
end
end
it 'treats the last argument as a set of options if it is a Hash' do
@socket = @addr.connect_to(ip_address, @port, timeout: 2)
@socket.should be_an_instance_of(Socket)
end
it 'binds the Addrinfo to the local address' do
@socket = @addr.connect_to(ip_address, @port)
@socket.local_address.ip_address.should == ip_address
@socket.local_address.ip_port.should > 0
@socket.local_address.ip_port.should_not == @port
end
end
describe 'using an Addrinfo as the 1st argument' do
before do
@to_addr = Addrinfo.tcp(ip_address, @port)
end
it 'returns a Socket when no block is given' do
@socket = @addr.connect_to(@to_addr)
@socket.should be_an_instance_of(Socket)
end
it 'yields the Socket when a block is given' do
@addr.connect_to(@to_addr) do |socket|
socket.should be_an_instance_of(Socket)
end
end
it 'treats the last argument as a set of options if it is a Hash' do
@socket = @addr.connect_to(@to_addr, timeout: 2)
@socket.should be_an_instance_of(Socket)
end
it 'binds the socket to the local address' do
@socket = @addr.connect_to(@to_addr)
@socket.local_address.ip_address.should == ip_address
@socket.local_address.ip_port.should > 0
@socket.local_address.ip_port.should_not == @port
end
end
end
end

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

@ -0,0 +1,115 @@
require_relative '../spec_helper'
describe 'Addrinfo#family_addrinfo' do
it 'raises ArgumentError if no arguments are given' do
addr = Addrinfo.tcp('127.0.0.1', 0)
lambda { addr.family_addrinfo }.should raise_error(ArgumentError)
end
describe 'using multiple arguments' do
describe 'with an IP Addrinfo' do
before do
@source = Addrinfo.tcp('127.0.0.1', 0)
end
it 'raises ArgumentError if only 1 argument is given' do
lambda { @source.family_addrinfo('127.0.0.1') }.should raise_error(ArgumentError)
end
it 'raises ArgumentError if more than 2 arguments are given' do
lambda { @source.family_addrinfo('127.0.0.1', 0, 666) }.should raise_error(ArgumentError)
end
it 'returns an Addrinfo when a host and port are given' do
addr = @source.family_addrinfo('127.0.0.1', 0)
addr.should be_an_instance_of(Addrinfo)
end
describe 'the returned Addrinfo' do
before do
@addr = @source.family_addrinfo('127.0.0.1', 0)
end
it 'uses the same address family as the source Addrinfo' do
@addr.afamily.should == @source.afamily
end
it 'uses the same protocol family as the source Addrinfo' do
@addr.pfamily.should == @source.pfamily
end
it 'uses the same socket type as the source Addrinfo' do
@addr.socktype.should == @source.socktype
end
it 'uses the same protocol as the source Addrinfo' do
@addr.protocol.should == @source.protocol
end
end
end
with_feature :unix_socket do
describe 'with a UNIX Addrinfo' do
before do
@source = Addrinfo.unix('cats')
end
it 'raises ArgumentError if more than 1 argument is given' do
lambda { @source.family_addrinfo('foo', 'bar') }.should raise_error(ArgumentError)
end
it 'returns an Addrinfo when a UNIX socket path is given' do
addr = @source.family_addrinfo('dogs')
addr.should be_an_instance_of(Addrinfo)
end
describe 'the returned Addrinfo' do
before do
@addr = @source.family_addrinfo('dogs')
end
it 'uses AF_UNIX as the address family' do
@addr.afamily.should == Socket::AF_UNIX
end
it 'uses PF_UNIX as the protocol family' do
@addr.pfamily.should == Socket::PF_UNIX
end
it 'uses the given socket path' do
@addr.unix_path.should == 'dogs'
end
end
end
end
end
describe 'using an Addrinfo as the 1st argument' do
before do
@source = Addrinfo.tcp('127.0.0.1', 0)
end
it 'returns the input Addrinfo' do
input = Addrinfo.tcp('127.0.0.2', 0)
@source.family_addrinfo(input).should == input
end
it 'raises ArgumentError if more than 1 argument is given' do
input = Addrinfo.tcp('127.0.0.2', 0)
lambda { @source.family_addrinfo(input, 666) }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the protocol families don't match" do
input = Addrinfo.tcp('::1', 0)
lambda { @source.family_addrinfo(input) }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the socket types don't match" do
input = Addrinfo.udp('127.0.0.1', 0)
lambda { @source.family_addrinfo(input) }.should raise_error(ArgumentError)
end
end
end

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

@ -0,0 +1,9 @@
require_relative '../spec_helper'
describe 'Addrinfo.foreach' do
it 'yields Addrinfo instances to the supplied block' do
Addrinfo.foreach('localhost', 80) do |addr|
addr.should be_an_instance_of(Addrinfo)
end
end
end

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

@ -0,0 +1,88 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe 'Addrinfo.getaddrinfo' do
it 'returns an Array of Addrinfo instances' do
array = Addrinfo.getaddrinfo('localhost', 80)
array.should be_an_instance_of(Array)
array[0].should be_an_instance_of(Addrinfo)
end
SocketSpecs.each_ip_protocol do |family, ip_address|
it 'sets the IP address of the Addrinfo instances' do
array = Addrinfo.getaddrinfo(ip_address, 80)
array[0].ip_address.should == ip_address
end
it 'sets the port of the Addrinfo instances' do
array = Addrinfo.getaddrinfo(ip_address, 80)
array[0].ip_port.should == 80
end
it 'sets the address family of the Addrinfo instances' do
array = Addrinfo.getaddrinfo(ip_address, 80)
array[0].afamily.should == family
end
it 'sets the protocol family of the Addrinfo instances' do
array = Addrinfo.getaddrinfo(ip_address, 80)
array[0].pfamily.should == family
end
end
guard -> { SocketSpecs.ipv6_available? } do
it 'sets a custom protocol family of the Addrinfo instances' do
array = Addrinfo.getaddrinfo('localhost', 80, Socket::PF_INET6)
array[0].pfamily.should == Socket::PF_INET6
end
it 'sets a corresponding address family based on a custom protocol family' do
array = Addrinfo.getaddrinfo('localhost', 80, Socket::PF_INET6)
array[0].afamily.should == Socket::AF_INET6
end
end
platform_is_not :windows do
it 'sets the default socket type of the Addrinfo instances' do
array = Addrinfo.getaddrinfo('localhost', 80)
possible = [Socket::SOCK_STREAM, Socket::SOCK_DGRAM]
possible.should include(array[0].socktype)
end
end
it 'sets a custom socket type of the Addrinfo instances' do
array = Addrinfo.getaddrinfo('localhost', 80, nil, Socket::SOCK_DGRAM)
array[0].socktype.should == Socket::SOCK_DGRAM
end
platform_is_not :windows do
it 'sets the default socket protocol of the Addrinfo instances' do
array = Addrinfo.getaddrinfo('localhost', 80)
possible = [Socket::IPPROTO_TCP, Socket::IPPROTO_UDP]
possible.should include(array[0].protocol)
end
end
it 'sets a custom socket protocol of the Addrinfo instances' do
array = Addrinfo.getaddrinfo('localhost', 80, nil, nil, Socket::IPPROTO_UDP)
array[0].protocol.should == Socket::IPPROTO_UDP
end
it 'sets the canonical name when AI_CANONNAME is given as a flag' do
array = Addrinfo
.getaddrinfo('localhost', 80, nil, nil, nil, Socket::AI_CANONNAME)
array[0].canonname.should be_an_instance_of(String)
end
end

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

@ -0,0 +1,44 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe 'Addrinfo#getnameinfo' do
describe 'using an IP Addrinfo' do
SocketSpecs.each_ip_protocol do |family, ip_address|
before do
@addr = Addrinfo.tcp(ip_address, 80)
end
it 'returns the node and service names' do
host, service = @addr.getnameinfo
host.should be_an_instance_of(String)
service.should == 'http'
end
it 'accepts flags as a Fixnum as the first argument' do
host, service = @addr.getnameinfo(Socket::NI_NUMERICSERV)
host.should be_an_instance_of(String)
service.should == '80'
end
end
end
platform_is :linux do
with_feature :unix_socket do
describe 'using a UNIX Addrinfo' do
before do
@addr = Addrinfo.unix('cats')
@host = Socket.gethostname
end
it 'returns the hostname and UNIX socket path' do
host, path = @addr.getnameinfo
host.should == @host
path.should == 'cats'
end
end
end
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#initialize" do
@ -22,6 +21,12 @@ describe "Addrinfo#initialize" do
@addrinfo.pfamily.should == Socket::PF_UNSPEC
end
it 'returns AF_INET as the default address family' do
addr = Addrinfo.new(Socket.sockaddr_in(80, '127.0.0.1'))
addr.afamily.should == Socket::AF_INET
end
it "returns the INET6 afamily" do
@addrinfo.afamily.should == Socket::AF_INET6
end
@ -142,7 +147,7 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 46102
end
it "returns the Socket::UNSPEC pfamily" do
it "returns the Socket::PF_INET pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET
end
@ -159,6 +164,46 @@ describe "Addrinfo#initialize" do
end
end
describe 'with a valid IP address' do
# Uses AF_INET6 since AF_INET is the default, making it a better test
# that Addrinfo actually sets the family correctly.
before do
@sockaddr = ['AF_INET6', 80, 'hostname', '::1']
end
it 'returns an Addrinfo with the correct IP' do
addr = Addrinfo.new(@sockaddr)
addr.ip_address.should == '::1'
end
it 'returns an Addrinfo with the correct address family' do
addr = Addrinfo.new(@sockaddr)
addr.afamily.should == Socket::AF_INET6
end
it 'returns an Addrinfo with the correct protocol family' do
addr = Addrinfo.new(@sockaddr)
addr.pfamily.should == Socket::PF_INET6
end
it 'returns an Addrinfo with the correct port' do
addr = Addrinfo.new(@sockaddr)
addr.ip_port.should == 80
end
end
describe 'with an invalid IP address' do
it 'raises SocketError' do
block = lambda { Addrinfo.new(['AF_INET6', 80, 'hostname', '127.0.0.1']) }
block.should raise_error(SocketError)
end
end
describe "with a family given" do
before :each do
@addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET)
@ -217,6 +262,38 @@ describe "Addrinfo#initialize" do
it "returns the 0 protocol" do
@addrinfo.protocol.should == 0
end
[:SOCK_STREAM, :SOCK_DGRAM, :SOCK_RAW].each do |type|
it "overwrites the socket type #{type}" do
sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1']
value = Socket.const_get(type)
addr = Addrinfo.new(sockaddr, nil, value)
addr.socktype.should == value
end
end
with_feature :sock_packet do
[:SOCK_SEQPACKET].each do |type|
it "overwrites the socket type #{type}" do
sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1']
value = Socket.const_get(type)
addr = Addrinfo.new(sockaddr, nil, value)
addr.socktype.should == value
end
end
end
it "raises SocketError when using SOCK_RDM" do
sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1']
value = Socket::SOCK_RDM
block = lambda { Addrinfo.new(sockaddr, nil, value) }
block.should raise_error(SocketError)
end
end
describe "with a family, socket type and protocol" do
@ -250,4 +327,261 @@ describe "Addrinfo#initialize" do
end
end
describe 'using an Array with extra arguments' do
describe 'with the AF_INET6 address family and an explicit protocol family' do
before do
@sockaddr = ['AF_INET6', 80, 'hostname', '127.0.0.1']
end
it "raises SocketError when using any Socket constant except except AF_INET(6)/PF_INET(6)" do
Socket.constants.grep(/(^AF_|^PF_)(?!INET)/).each do |constant|
value = Socket.const_get(constant)
-> {
Addrinfo.new(@sockaddr, value)
}.should raise_error(SocketError)
end
end
end
describe 'with the AF_INET address family and an explicit socket protocol' do
before do
@sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1']
end
describe 'and no socket type is given' do
valid = [:IPPROTO_IP, :IPPROTO_UDP, :IPPROTO_HOPOPTS]
valid.each do |type|
it "overwrites the protocol when using #{type}" do
value = Socket.const_get(type)
addr = Addrinfo.new(@sockaddr, nil, nil, value)
addr.protocol.should == value
end
end
platform_is_not :windows do
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
block = lambda { Addrinfo.new(@sockaddr, nil, nil, value) }
block.should raise_error(SocketError)
end
end
end
end
describe 'and the socket type is set to SOCK_DGRAM' do
before do
@socktype = Socket::SOCK_DGRAM
end
valid = [:IPPROTO_IP, :IPPROTO_UDP, :IPPROTO_HOPOPTS]
valid.each do |type|
it "overwrites the protocol when using #{type}" do
value = Socket.const_get(type)
addr = Addrinfo.new(@sockaddr, nil, @socktype, value)
addr.protocol.should == value
end
end
platform_is_not :windows do
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
block = lambda { Addrinfo.new(@sockaddr, nil, @socktype, value) }
block.should raise_error(SocketError)
end
end
end
end
with_feature :sock_packet do
describe 'and the socket type is set to SOCK_PACKET' do
before do
@socktype = Socket::SOCK_PACKET
end
Socket.constants.grep(/^IPPROTO/).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
block = lambda { Addrinfo.new(@sockaddr, nil, @socktype, value) }
block.should raise_error(SocketError)
end
end
end
end
describe 'and the socket type is set to SOCK_RAW' do
before do
@socktype = Socket::SOCK_RAW
end
Socket.constants.grep(/^IPPROTO/).each do |type|
it "overwrites the protocol when using #{type}" do
value = Socket.const_get(type)
addr = Addrinfo.new(@sockaddr, nil, @socktype, value)
addr.protocol.should == value
end
end
end
describe 'and the socket type is set to SOCK_RDM' do
before do
@socktype = Socket::SOCK_RDM
end
Socket.constants.grep(/^IPPROTO/).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
block = lambda { Addrinfo.new(@sockaddr, nil, @socktype, value) }
block.should raise_error(SocketError)
end
end
end
platform_is_not :windows do
describe 'and the socket type is set to SOCK_SEQPACKET' do
before do
@socktype = Socket::SOCK_SEQPACKET
end
valid = [:IPPROTO_IP, :IPPROTO_HOPOPTS]
valid.each do |type|
it "overwrites the protocol when using #{type}" do
value = Socket.const_get(type)
addr = Addrinfo.new(@sockaddr, nil, @socktype, value)
addr.protocol.should == value
end
end
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
block = lambda { Addrinfo.new(@sockaddr, nil, @socktype, value) }
block.should raise_error(SocketError)
end
end
end
end
describe 'and the socket type is set to SOCK_STREAM' do
before do
@socktype = Socket::SOCK_STREAM
end
valid = [:IPPROTO_IP, :IPPROTO_TCP, :IPPROTO_HOPOPTS]
valid.each do |type|
it "overwrites the protocol when using #{type}" do
value = Socket.const_get(type)
addr = Addrinfo.new(@sockaddr, nil, @socktype, value)
addr.protocol.should == value
end
end
platform_is_not :windows do
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
block = lambda { Addrinfo.new(@sockaddr, nil, @socktype, value) }
block.should raise_error(SocketError)
end
end
end
end
end
end
describe 'with Symbols' do
before do
@sockaddr = Socket.sockaddr_in(80, '127.0.0.1')
end
it 'returns an Addrinfo with :PF_INET family' do
addr = Addrinfo.new(@sockaddr, :PF_INET)
addr.pfamily.should == Socket::PF_INET
end
it 'returns an Addrinfo with :INET family' do
addr = Addrinfo.new(@sockaddr, :INET)
addr.pfamily.should == Socket::PF_INET
end
it 'returns an Addrinfo with :SOCK_STREAM as the socket type' do
addr = Addrinfo.new(@sockaddr, nil, :SOCK_STREAM)
addr.socktype.should == Socket::SOCK_STREAM
end
it 'returns an Addrinfo with :STREAM as the socket type' do
addr = Addrinfo.new(@sockaddr, nil, :STREAM)
addr.socktype.should == Socket::SOCK_STREAM
end
end
describe 'with Strings' do
before do
@sockaddr = Socket.sockaddr_in(80, '127.0.0.1')
end
it 'returns an Addrinfo with "PF_INET" family' do
addr = Addrinfo.new(@sockaddr, 'PF_INET')
addr.pfamily.should == Socket::PF_INET
end
it 'returns an Addrinfo with "INET" family' do
addr = Addrinfo.new(@sockaddr, 'INET')
addr.pfamily.should == Socket::PF_INET
end
it 'returns an Addrinfo with "SOCK_STREAM" as the socket type' do
addr = Addrinfo.new(@sockaddr, nil, 'SOCK_STREAM')
addr.socktype.should == Socket::SOCK_STREAM
end
it 'returns an Addrinfo with "STREAM" as the socket type' do
addr = Addrinfo.new(@sockaddr, nil, 'STREAM')
addr.socktype.should == Socket::SOCK_STREAM
end
end
with_feature :unix_socket do
describe 'using separate arguments for a Unix socket' do
before do
@sockaddr = Socket.pack_sockaddr_un('socket')
end
it 'returns an Addrinfo with the correct unix path' do
Addrinfo.new(@sockaddr).unix_path.should == 'socket'
end
it 'returns an Addrinfo with the correct protocol family' do
Addrinfo.new(@sockaddr).pfamily.should == Socket::PF_UNSPEC
end
it 'returns an Addrinfo with the correct address family' do
Addrinfo.new(@sockaddr).afamily.should == Socket::AF_UNIX
end
end
end
end

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

@ -1,25 +1,50 @@
require_relative '../../../spec_helper'
require_relative '../spec_helper'
require 'socket'
describe 'Addrinfo#inspect_sockaddr' do
it 'IPv4' do
Addrinfo.tcp('127.0.0.1', 80).inspect_sockaddr.should == '127.0.0.1:80'
Addrinfo.tcp('127.0.0.1', 0).inspect_sockaddr.should == '127.0.0.1'
describe 'using an IPv4 address' do
it 'returns a String containing the IP address and port number' do
addr = Addrinfo.tcp('127.0.0.1', 80)
addr.inspect_sockaddr.should == '127.0.0.1:80'
end
it 'returns a String containing just the IP address when no port is given' do
addr = Addrinfo.tcp('127.0.0.1', 0)
addr.inspect_sockaddr.should == '127.0.0.1'
end
end
it 'IPv6' do
Addrinfo.tcp('::1', 80).inspect_sockaddr.should == '[::1]:80'
Addrinfo.tcp('::1', 0).inspect_sockaddr.should == '::1'
ip = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
Addrinfo.tcp(ip, 80).inspect_sockaddr.should == '[2001:db8:85a3::8a2e:370:7334]:80'
Addrinfo.tcp(ip, 0).inspect_sockaddr.should == '2001:db8:85a3::8a2e:370:7334'
describe 'using an IPv6 address' do
before :each do
@ip = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
end
it 'returns a String containing the IP address and port number' do
Addrinfo.tcp('::1', 80).inspect_sockaddr.should == '[::1]:80'
Addrinfo.tcp(@ip, 80).inspect_sockaddr.should == '[2001:db8:85a3::8a2e:370:7334]:80'
end
it 'returns a String containing just the IP address when no port is given' do
Addrinfo.tcp('::1', 0).inspect_sockaddr.should == '::1'
Addrinfo.tcp(@ip, 0).inspect_sockaddr.should == '2001:db8:85a3::8a2e:370:7334'
end
end
platform_is_not :windows do
it 'UNIX' do
Addrinfo.unix('/tmp/sock').inspect_sockaddr.should == '/tmp/sock'
Addrinfo.unix('rel').inspect_sockaddr.should == 'UNIX rel'
with_feature :unix_socket do
describe 'using a UNIX path' do
it 'returns a String containing the UNIX path' do
addr = Addrinfo.unix('/foo/bar')
addr.inspect_sockaddr.should == '/foo/bar'
end
it 'returns a String containing the UNIX path when using a relative path' do
addr = Addrinfo.unix('foo')
addr.inspect_sockaddr.should == 'UNIX foo'
end
end
end
end

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

@ -0,0 +1,65 @@
require_relative '../spec_helper'
describe 'Addrinfo#inspect' do
describe 'using an IPv4 Addrinfo' do
it 'returns a String when using a TCP Addrinfo' do
addr = Addrinfo.tcp('127.0.0.1', 80)
addr.inspect.should == '#<Addrinfo: 127.0.0.1:80 TCP>'
end
it 'returns a String when using an UDP Addrinfo' do
addr = Addrinfo.udp('127.0.0.1', 80)
addr.inspect.should == '#<Addrinfo: 127.0.0.1:80 UDP>'
end
it 'returns a String when using an Addrinfo without a port' do
addr = Addrinfo.ip('127.0.0.1')
addr.inspect.should == '#<Addrinfo: 127.0.0.1>'
end
end
describe 'using an IPv6 Addrinfo' do
it 'returns a String when using a TCP Addrinfo' do
addr = Addrinfo.tcp('::1', 80)
addr.inspect.should == '#<Addrinfo: [::1]:80 TCP>'
end
it 'returns a String when using an UDP Addrinfo' do
addr = Addrinfo.udp('::1', 80)
addr.inspect.should == '#<Addrinfo: [::1]:80 UDP>'
end
it 'returns a String when using an Addrinfo without a port' do
addr = Addrinfo.ip('::1')
addr.inspect.should == '#<Addrinfo: ::1>'
end
end
with_feature :unix_socket do
describe 'using a UNIX Addrinfo' do
it 'returns a String' do
addr = Addrinfo.unix('/foo')
addr.inspect.should == '#<Addrinfo: /foo SOCK_STREAM>'
end
it 'returns a String when using a relative UNIX path' do
addr = Addrinfo.unix('foo')
addr.inspect.should == '#<Addrinfo: UNIX foo SOCK_STREAM>'
end
it 'returns a String when using a DGRAM socket' do
addr = Addrinfo.unix('/foo', Socket::SOCK_DGRAM)
addr.inspect.should == '#<Addrinfo: /foo SOCK_DGRAM>'
end
end
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ip_address" do
describe "for an ipv4 socket" do
@ -22,7 +21,7 @@ describe "Addrinfo#ip_address" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")
@ -33,4 +32,54 @@ describe "Addrinfo#ip_address" do
end
end
end
describe 'with an Array as the socket address' do
it 'returns the IP as a String' do
sockaddr = ['AF_INET', 80, 'localhost', '127.0.0.1']
addr = Addrinfo.new(sockaddr)
addr.ip_address.should == '127.0.0.1'
end
end
describe 'without an IP address' do
before do
@ips = ['127.0.0.1', '0.0.0.0', '::1']
end
# Both these cases seem to return different values at times on MRI. Since
# this is network dependent we can't rely on an exact IP being returned.
it 'returns the local IP address when using an empty String as the IP' do
sockaddr = Socket.sockaddr_in(80, '')
addr = Addrinfo.new(sockaddr)
@ips.include?(addr.ip_address).should == true
end
it 'returns the local IP address when using nil as the IP' do
sockaddr = Socket.sockaddr_in(80, nil)
addr = Addrinfo.new(sockaddr)
@ips.include?(addr.ip_address).should == true
end
end
# On MRI calling Addrinfo#ip_address with AF_UNSPEC as the address family is
# supposed to raise a SocketError. MRI however doesn't provide a way to
# actually initialize an Addrinfo with AF_UNSPEC, nor does it allow stubbing
# of any methods since Addrinfo doesn't use any Ruby methods for checking the
# IP address. As a result we can only run this test on Rubinius.
with_feature :pure_ruby_addrinfo do
describe 'with a non IPv4 or IPv6 address' do
it 'raises SocketError' do
sockaddr = Socket.sockaddr_in(80, '127.0.0.1')
addr = Addrinfo.new(sockaddr)
addr.stub!(:ipv4?).and_return(false)
addr.stub!(:ipv6?).and_return(false)
lambda { addr.ip_address }.should raise_error(SocketError)
end
end
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ip_port" do
describe "for an ipv4 socket" do
@ -22,7 +21,7 @@ describe "Addrinfo#ip_port" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,5 +1,5 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "Addrinfo#ip?" do
describe "for an ipv4 socket" do
@ -22,15 +22,43 @@ describe "Addrinfo#ip?" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")
end
it "returns Socket::AF_INET6" do
it "returns false" do
@addrinfo.ip?.should be_false
end
end
end
end
describe 'Addrinfo.ip' do
SocketSpecs.each_ip_protocol do |family, ip_address|
it 'returns an Addrinfo instance' do
Addrinfo.ip(ip_address).should be_an_instance_of(Addrinfo)
end
it 'sets the IP address' do
Addrinfo.ip(ip_address).ip_address.should == ip_address
end
it 'sets the port to 0' do
Addrinfo.ip(ip_address).ip_port.should == 0
end
it 'sets the address family' do
Addrinfo.ip(ip_address).afamily.should == family
end
it 'sets the protocol family' do
Addrinfo.ip(ip_address).pfamily.should == family
end
it 'sets the socket type to 0' do
Addrinfo.ip(ip_address).socktype.should == 0
end
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ip_unpack" do
describe "for an ipv4 socket" do
@ -22,7 +21,7 @@ describe "Addrinfo#ip_unpack" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,19 +1,16 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv4_loopback?" do
describe "for an ipv4 socket" do
before :each do
@loopback = Addrinfo.tcp("127.0.0.1", 80)
@other = Addrinfo.tcp("0.0.0.0", 80)
end
it "returns true for the loopback address" do
@loopback.ipv4_loopback?.should be_true
Addrinfo.ip('127.0.0.1').ipv4_loopback?.should == true
Addrinfo.ip('127.0.0.2').ipv4_loopback?.should == true
Addrinfo.ip('127.255.0.1').ipv4_loopback?.should == true
Addrinfo.ip('127.255.255.255').ipv4_loopback?.should == true
end
it "returns false for another address" do
@other.ipv4_loopback?.should be_false
Addrinfo.ip('255.255.255.0').ipv4_loopback?.should be_false
end
end
@ -32,7 +29,7 @@ describe "Addrinfo#ipv4_loopback?" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,38 +1,21 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv4_multicast?" do
describe "for an ipv4 socket" do
before :each do
@multicast = Addrinfo.tcp("224.0.0.1", 80)
@other = Addrinfo.tcp("0.0.0.0", 80)
end
it "returns true for the loopback address" do
@multicast.ipv4_multicast?.should be_true
end
it "returns false for another address" do
@other.ipv4_multicast?.should be_false
end
it 'returns true for a multicast address' do
Addrinfo.ip('224.0.0.0').ipv4_multicast?.should == true
Addrinfo.ip('224.0.0.9').ipv4_multicast?.should == true
Addrinfo.ip('239.255.255.250').ipv4_multicast?.should == true
end
describe "for an ipv6 socket" do
before :each do
@multicast = Addrinfo.tcp("ff02::1", 80)
@other = Addrinfo.tcp("::", 80)
end
it "returns false for the loopback address" do
@multicast.ipv4_multicast?.should be_false
end
it "returns false for another address" do
@other.ipv4_multicast?.should be_false
end
it 'returns false for a regular addrss' do
Addrinfo.ip('8.8.8.8').ipv4_multicast?.should == false
end
platform_is_not :windows do
it 'returns false for an IPv6 address' do
Addrinfo.ip('::1').ipv4_multicast?.should == false
end
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv4_private?" do
describe "for an ipv4 socket" do
@ -9,7 +8,14 @@ describe "Addrinfo#ipv4_private?" do
end
it "returns true for a private address" do
@private.ipv4_private?.should be_true
Addrinfo.ip('10.0.0.0').ipv4_private?.should == true
Addrinfo.ip('10.0.0.5').ipv4_private?.should == true
Addrinfo.ip('172.16.0.0').ipv4_private?.should == true
Addrinfo.ip('172.16.0.5').ipv4_private?.should == true
Addrinfo.ip('192.168.0.0').ipv4_private?.should == true
Addrinfo.ip('192.168.0.5').ipv4_private?.should == true
end
it "returns false for a public address" do
@ -27,7 +33,7 @@ describe "Addrinfo#ipv4_private?" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv4?" do
describe "for an ipv4 socket" do
@ -22,7 +21,7 @@ describe "Addrinfo#ipv4?" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -0,0 +1,18 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_linklocal?' do
it 'returns true for a link-local address' do
Addrinfo.ip('fe80::').ipv6_linklocal?.should == true
Addrinfo.ip('fe81::').ipv6_linklocal?.should == true
Addrinfo.ip('fe8f::').ipv6_linklocal?.should == true
Addrinfo.ip('fe80::1').ipv6_linklocal?.should == true
end
it 'returns false for a regular address' do
Addrinfo.ip('::1').ipv6_linklocal?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_linklocal?.should == false
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv6_loopback?" do
describe "for an ipv4 socket" do
@ -8,7 +7,7 @@ describe "Addrinfo#ipv6_loopback?" do
@other = Addrinfo.tcp("0.0.0.0", 80)
end
it "returns true for the loopback address" do
it "returns false for the loopback address" do
@loopback.ipv6_loopback?.should be_false
end
@ -23,7 +22,7 @@ describe "Addrinfo#ipv6_loopback?" do
@other = Addrinfo.tcp("::", 80)
end
it "returns false for the loopback address" do
it "returns true for the loopback address" do
@loopback.ipv6_loopback?.should be_true
end
@ -32,7 +31,7 @@ describe "Addrinfo#ipv6_loopback?" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -0,0 +1,20 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_global?' do
it 'returns true for a multi-cast address in the global scope' do
Addrinfo.ip('ff1e::').ipv6_mc_global?.should == true
Addrinfo.ip('fffe::').ipv6_mc_global?.should == true
Addrinfo.ip('ff0e::').ipv6_mc_global?.should == true
Addrinfo.ip('ff1e::1').ipv6_mc_global?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_mc_global?.should == false
Addrinfo.ip('ff1a::').ipv6_mc_global?.should == false
Addrinfo.ip('ff1f::1').ipv6_mc_global?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_mc_global?.should == false
end
end

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

@ -0,0 +1,19 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_linklocal?' do
it 'returns true for a multi-cast link-local address' do
Addrinfo.ip('ff12::').ipv6_mc_linklocal?.should == true
Addrinfo.ip('ff02::').ipv6_mc_linklocal?.should == true
Addrinfo.ip('fff2::').ipv6_mc_linklocal?.should == true
Addrinfo.ip('ff12::1').ipv6_mc_linklocal?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_mc_linklocal?.should == false
Addrinfo.ip('fff1::').ipv6_mc_linklocal?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_mc_linklocal?.should == false
end
end

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

@ -0,0 +1,18 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_nodelocal?' do
it 'returns true for a multi-cast node-local address' do
Addrinfo.ip('ff11::').ipv6_mc_nodelocal?.should == true
Addrinfo.ip('ff01::').ipv6_mc_nodelocal?.should == true
Addrinfo.ip('fff1::').ipv6_mc_nodelocal?.should == true
Addrinfo.ip('ff11::1').ipv6_mc_nodelocal?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_mc_nodelocal?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_mc_nodelocal?.should == false
end
end

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

@ -0,0 +1,18 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_orglocal?' do
it 'returns true for a multi-cast org-local address' do
Addrinfo.ip('ff18::').ipv6_mc_orglocal?.should == true
Addrinfo.ip('ff08::').ipv6_mc_orglocal?.should == true
Addrinfo.ip('fff8::').ipv6_mc_orglocal?.should == true
Addrinfo.ip('ff18::1').ipv6_mc_orglocal?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_mc_orglocal?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_mc_orglocal?.should == false
end
end

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

@ -0,0 +1,18 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_sitelocal?' do
it 'returns true for a multi-cast site-local address' do
Addrinfo.ip('ff15::').ipv6_mc_sitelocal?.should == true
Addrinfo.ip('ff05::').ipv6_mc_sitelocal?.should == true
Addrinfo.ip('fff5::').ipv6_mc_sitelocal?.should == true
Addrinfo.ip('ff15::1').ipv6_mc_sitelocal?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_mc_sitelocal?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_mc_sitelocal?.should == false
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv6_multicast?" do
describe "for an ipv4 socket" do
@ -8,7 +7,7 @@ describe "Addrinfo#ipv6_multicast?" do
@other = Addrinfo.tcp("0.0.0.0", 80)
end
it "returns true for the loopback address" do
it "returns true for a multicast address" do
@multicast.ipv6_multicast?.should be_false
end
@ -18,21 +17,24 @@ describe "Addrinfo#ipv6_multicast?" do
end
describe "for an ipv6 socket" do
before :each do
@multicast = Addrinfo.tcp("ff02::1", 80)
@other = Addrinfo.tcp("::", 80)
end
it "returns true for a multicast address" do
Addrinfo.ip('ff00::').ipv6_multicast?.should == true
Addrinfo.ip('ff00::1').ipv6_multicast?.should == true
Addrinfo.ip('ff08::1').ipv6_multicast?.should == true
Addrinfo.ip('fff8::1').ipv6_multicast?.should == true
it "returns false for the loopback address" do
@multicast.ipv6_multicast?.should be_true
Addrinfo.ip('ff02::').ipv6_multicast?.should == true
Addrinfo.ip('ff02::1').ipv6_multicast?.should == true
Addrinfo.ip('ff0f::').ipv6_multicast?.should == true
end
it "returns false for another address" do
@other.ipv6_multicast?.should be_false
Addrinfo.ip('::1').ipv6_multicast?.should == false
Addrinfo.ip('fe80::').ipv6_multicast?.should == false
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -0,0 +1,18 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_sitelocal?' do
it 'returns true for a site-local address' do
Addrinfo.ip('feef::').ipv6_sitelocal?.should == true
Addrinfo.ip('fee0::').ipv6_sitelocal?.should == true
Addrinfo.ip('fee2::').ipv6_sitelocal?.should == true
Addrinfo.ip('feef::1').ipv6_sitelocal?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_sitelocal?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_sitelocal?.should == false
end
end

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

@ -1,5 +1,4 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#ipv6?" do
describe "for an ipv4 socket" do
@ -22,7 +21,7 @@ describe "Addrinfo#ipv6?" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -0,0 +1,66 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_to_ipv4' do
it 'returns an Addrinfo for ::192.168.1.1' do
addr = Addrinfo.ip('::192.168.1.1').ipv6_to_ipv4
addr.should be_an_instance_of(Addrinfo)
addr.afamily.should == Socket::AF_INET
addr.ip_address.should == '192.168.1.1'
end
it 'returns an Addrinfo for ::0.0.1.1' do
addr = Addrinfo.ip('::0.0.1.1').ipv6_to_ipv4
addr.should be_an_instance_of(Addrinfo)
addr.afamily.should == Socket::AF_INET
addr.ip_address.should == '0.0.1.1'
end
it 'returns an Addrinfo for ::0.0.1.0' do
addr = Addrinfo.ip('::0.0.1.0').ipv6_to_ipv4
addr.should be_an_instance_of(Addrinfo)
addr.afamily.should == Socket::AF_INET
addr.ip_address.should == '0.0.1.0'
end
it 'returns an Addrinfo for ::0.1.0.0' do
addr = Addrinfo.ip('::0.1.0.0').ipv6_to_ipv4
addr.should be_an_instance_of(Addrinfo)
addr.afamily.should == Socket::AF_INET
addr.ip_address.should == '0.1.0.0'
end
it 'returns an Addrinfo for ::ffff:192.168.1.1' do
addr = Addrinfo.ip('::ffff:192.168.1.1').ipv6_to_ipv4
addr.should be_an_instance_of(Addrinfo)
addr.afamily.should == Socket::AF_INET
addr.ip_address.should == '192.168.1.1'
end
it 'returns nil for ::0.0.0.1' do
Addrinfo.ip('::0.0.0.1').ipv6_to_ipv4.should be_nil
end
it 'returns nil for a pure IPv6 Addrinfo' do
Addrinfo.ip('::1').ipv6_to_ipv4.should be_nil
end
it 'returns nil for an IPv4 Addrinfo' do
Addrinfo.ip('192.168.1.1').ipv6_to_ipv4.should be_nil
end
with_feature :unix_socket do
it 'returns nil for a UNIX Addrinfo' do
Addrinfo.unix('foo').ipv6_to_ipv4.should be_nil
end
end
end

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

@ -0,0 +1,18 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_unique_local?' do
it 'returns true for an unique local IPv6 address' do
Addrinfo.ip('fc00::').ipv6_unique_local?.should == true
Addrinfo.ip('fd00::').ipv6_unique_local?.should == true
Addrinfo.ip('fcff::').ipv6_unique_local?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_unique_local?.should == false
Addrinfo.ip('fe00::').ipv6_unique_local?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_unique_local?.should == false
end
end

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

@ -0,0 +1,15 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_unspecified?' do
it 'returns true for an unspecified IPv6 address' do
Addrinfo.ip('::').ipv6_unspecified?.should == true
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_unspecified?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_unspecified?.should == false
end
end

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

@ -0,0 +1,20 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_v4compat?' do
it 'returns true for an IPv4 compatible address' do
Addrinfo.ip('::127.0.0.1').ipv6_v4compat?.should == true
Addrinfo.ip('::192.168.1.1').ipv6_v4compat?.should == true
end
it 'returns false for an IPv4 mapped address' do
Addrinfo.ip('::ffff:192.168.1.1').ipv6_v4compat?.should == false
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_v4compat?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_v4compat?.should == false
end
end

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

@ -0,0 +1,20 @@
require_relative '../spec_helper'
describe 'Addrinfo#ipv6_v4mapped?' do
it 'returns true for an IPv4 compatible address' do
Addrinfo.ip('::ffff:192.168.1.1').ipv6_v4mapped?.should == true
end
it 'returns false for an IPv4 compatible address' do
Addrinfo.ip('::192.168.1.1').ipv6_v4mapped?.should == false
Addrinfo.ip('::127.0.0.1').ipv6_v4mapped?.should == false
end
it 'returns false for a regular IPv6 address' do
Addrinfo.ip('::1').ipv6_v4mapped?.should == false
end
it 'returns false for an IPv4 address' do
Addrinfo.ip('127.0.0.1').ipv6_v4mapped?.should == false
end
end

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

@ -0,0 +1,34 @@
require_relative '../spec_helper'
describe 'Addrinfo#listen' do
before do
@addr = Addrinfo.tcp('127.0.0.1', 0)
@socket = nil
end
after do
@socket.close if @socket
end
it 'returns a Socket when no block is given' do
@socket = @addr.listen
@socket.should be_an_instance_of(Socket)
end
it 'yields the Socket if a block is given' do
@addr.listen do |socket|
socket.should be_an_instance_of(Socket)
end
end
it 'closes the socket if a block is given' do
socket = nil
@addr.listen do |sock|
socket = sock
end
socket.closed?.should == true
end
end

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

@ -0,0 +1,82 @@
require_relative '../spec_helper'
describe 'Addrinfo#marshal_dump' do
describe 'using an IP Addrinfo' do
before do
@addr = Addrinfo.getaddrinfo('localhost', 80, :INET, :STREAM,
Socket::IPPROTO_TCP, Socket::AI_CANONNAME)[0]
end
it 'returns an Array' do
@addr.marshal_dump.should be_an_instance_of(Array)
end
describe 'the returned Array' do
before do
@array = @addr.marshal_dump
end
it 'includes the address family as the 1st value' do
@array[0].should == 'AF_INET'
end
it 'includes the IP address as the 2nd value' do
@array[1].should == [@addr.ip_address, @addr.ip_port.to_s]
end
it 'includes the protocol family as the 3rd value' do
@array[2].should == 'PF_INET'
end
it 'includes the socket type as the 4th value' do
@array[3].should == 'SOCK_STREAM'
end
it 'includes the protocol as the 5th value' do
@array[4].should == 'IPPROTO_TCP'
end
it 'includes the canonical name as the 6th value' do
@array[5].should == @addr.canonname
end
end
end
with_feature :unix_socket do
describe 'using a UNIX Addrinfo' do
before do
@addr = Addrinfo.unix('foo')
end
it 'returns an Array' do
@addr.marshal_dump.should be_an_instance_of(Array)
end
describe 'the returned Array' do
before do
@array = @addr.marshal_dump
end
it 'includes the address family as the 1st value' do
@array[0].should == 'AF_UNIX'
end
it 'includes the UNIX path as the 2nd value' do
@array[1].should == @addr.unix_path
end
it 'includes the protocol family as the 3rd value' do
@array[2].should == 'PF_UNIX'
end
it 'includes the socket type as the 4th value' do
@array[3].should == 'SOCK_STREAM'
end
it 'includes the protocol as the 5th value' do
@array[4].should == 0
end
end
end
end
end

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

@ -0,0 +1,35 @@
require_relative '../spec_helper'
describe 'Addrinfo#marshal_load' do
describe 'using an IP address' do
it 'returns a new Addrinfo' do
source = Addrinfo.getaddrinfo('localhost', 80, :INET, :STREAM,
Socket::IPPROTO_TCP, Socket::AI_CANONNAME)[0]
addr = Marshal.load(Marshal.dump(source))
addr.afamily.should == source.afamily
addr.pfamily.should == source.pfamily
addr.socktype.should == source.socktype
addr.protocol.should == source.protocol
addr.ip_address.should == source.ip_address
addr.ip_port.should == source.ip_port
addr.canonname.should == source.canonname
end
end
with_feature :unix_socket do
describe 'using a UNIX socket' do
it 'returns a new Addrinfo' do
source = Addrinfo.unix('foo')
addr = Marshal.load(Marshal.dump(source))
addr.afamily.should == source.afamily
addr.pfamily.should == source.pfamily
addr.socktype.should == source.socktype
addr.protocol.should == source.protocol
addr.unix_path.should == source.unix_path
end
end
end
end

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

@ -1,7 +1,12 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#pfamily" do
it 'returns PF_UNSPEC as the default socket family' do
sockaddr = Socket.pack_sockaddr_in(80, 'localhost')
Addrinfo.new(sockaddr).pfamily.should == Socket::PF_UNSPEC
end
describe "for an ipv4 socket" do
before :each do
@ -24,7 +29,7 @@ describe "Addrinfo#pfamily" do
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,30 +1,16 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#protocol" do
describe "for an ipv4 socket" do
before :each do
@addrinfo = Addrinfo.tcp("127.0.0.1", 80)
end
it "returns Socket::IPPROTO_TCP" do
@addrinfo.protocol.should == Socket::IPPROTO_TCP
end
it 'returns 0 by default' do
Addrinfo.ip('127.0.0.1').protocol.should == 0
end
describe "for an ipv6 socket" do
before :each do
@addrinfo = Addrinfo.tcp("::1", 80)
end
it "returns Socket::IPPROTO_TCP" do
@addrinfo.protocol.should == Socket::IPPROTO_TCP
end
it 'returns a custom protocol when given' do
Addrinfo.tcp('127.0.0.1', 80).protocol.should == Socket::IPPROTO_TCP
Addrinfo.tcp('::1', 80).protocol.should == Socket::IPPROTO_TCP
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -6,7 +6,7 @@ describe :socket_addrinfo_to_sockaddr, :shared => true do
end
it "returns a sockaddr packed structure" do
@addrinfo.send(@method).should be_kind_of(String)
@addrinfo.send(@method).should == Socket.sockaddr_in(80, '127.0.0.1')
end
end
@ -16,20 +16,36 @@ describe :socket_addrinfo_to_sockaddr, :shared => true do
end
it "returns a sockaddr packed structure" do
@addrinfo.send(@method).should be_kind_of(String)
@addrinfo.send(@method).should == Socket.sockaddr_in(80, '::1')
end
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")
end
it "returns a sockaddr packed structure" do
@addrinfo.send(@method).should be_kind_of(String)
@addrinfo.send(@method).should == Socket.sockaddr_un('/tmp/sock')
end
end
end
describe 'using a Addrinfo with just an IP address' do
it 'returns a String' do
addr = Addrinfo.ip('127.0.0.1')
addr.send(@method).should == Socket.sockaddr_in(0, '127.0.0.1')
end
end
describe 'using a Addrinfo without an IP and port' do
it 'returns a String' do
addr = Addrinfo.new(['AF_INET', 0, '', ''])
addr.send(@method).should == Socket.sockaddr_in(0, '')
end
end
end

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

@ -1,30 +1,15 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo#socktype" do
describe "for an ipv4 socket" do
before :each do
@addrinfo = Addrinfo.tcp("127.0.0.1", 80)
end
it "returns Socket::SOCK_STREAM" do
@addrinfo.socktype.should == Socket::SOCK_STREAM
end
it 'returns 0 by default' do
Addrinfo.ip('127.0.0.1').socktype.should == 0
end
describe "for an ipv6 socket" do
before :each do
@addrinfo = Addrinfo.tcp("::1", 80)
end
it "returns Socket::SOCK_STREAM" do
@addrinfo.socktype.should == Socket::SOCK_STREAM
end
it 'returns the socket type when given' do
Addrinfo.tcp('127.0.0.1', 80).socktype.should == Socket::SOCK_STREAM
end
platform_is_not :windows do
with_feature :unix_socket do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")

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

@ -1,20 +1,34 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "Addrinfo.tcp" do
describe 'Addrinfo.tcp' do
SocketSpecs.each_ip_protocol do |family, ip_address|
it 'returns an Addrinfo instance' do
Addrinfo.tcp(ip_address, 80).should be_an_instance_of(Addrinfo)
end
before :each do
@addrinfo = Addrinfo.tcp("localhost", "smtp")
end
it 'sets the IP address' do
Addrinfo.tcp(ip_address, 80).ip_address.should == ip_address
end
it "creates a addrinfo for a tcp socket" do
["::1", "127.0.0.1"].should include(@addrinfo.ip_address)
[Socket::PF_INET, Socket::PF_INET6].should include(@addrinfo.pfamily)
@addrinfo.ip_port.should == 25
@addrinfo.socktype.should == Socket::SOCK_STREAM
platform_is_not :solaris do
@addrinfo.protocol.should == Socket::IPPROTO_TCP
it 'sets the port' do
Addrinfo.tcp(ip_address, 80).ip_port.should == 80
end
it 'sets the address family' do
Addrinfo.tcp(ip_address, 80).afamily.should == family
end
it 'sets the protocol family' do
Addrinfo.tcp(ip_address, 80).pfamily.should == family
end
it 'sets the socket type' do
Addrinfo.tcp(ip_address, 80).socktype.should == Socket::SOCK_STREAM
end
it 'sets the socket protocol' do
Addrinfo.tcp(ip_address, 80).protocol.should == Socket::IPPROTO_TCP
end
end
end

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

@ -1,6 +1,5 @@
require_relative '../../../spec_helper'
require_relative '../spec_helper'
require_relative 'shared/to_sockaddr'
require 'socket'
describe "Addrinfo#to_s" do
it_behaves_like :socket_addrinfo_to_sockaddr, :to_s

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

@ -1,6 +1,5 @@
require_relative '../../../spec_helper'
require_relative '../spec_helper'
require_relative 'shared/to_sockaddr'
require 'socket'
describe "Addrinfo#to_sockaddr" do
it_behaves_like :socket_addrinfo_to_sockaddr, :to_sockaddr

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

@ -1,20 +1,36 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "Addrinfo.udp" do
describe 'Addrinfo.udp' do
SocketSpecs.each_ip_protocol do |family, ip_address|
it 'returns an Addrinfo instance' do
Addrinfo.udp(ip_address, 80).should be_an_instance_of(Addrinfo)
end
before :each do
@addrinfo = Addrinfo.udp("localhost", "daytime")
end
it 'sets the IP address' do
Addrinfo.udp(ip_address, 80).ip_address.should == ip_address
end
it 'sets the port' do
Addrinfo.udp(ip_address, 80).ip_port.should == 80
end
it 'sets the address family' do
Addrinfo.udp(ip_address, 80).afamily.should == family
end
it 'sets the protocol family' do
Addrinfo.udp(ip_address, 80).pfamily.should == family
end
it 'sets the socket type' do
Addrinfo.udp(ip_address, 80).socktype.should == Socket::SOCK_DGRAM
end
it "creates a addrinfo for a tcp socket" do
["::1", "127.0.0.1"].should include(@addrinfo.ip_address)
[Socket::PF_INET, Socket::PF_INET6].should include(@addrinfo.pfamily)
@addrinfo.ip_port.should == 13
@addrinfo.socktype.should == Socket::SOCK_DGRAM
platform_is_not :solaris do
@addrinfo.protocol.should == Socket::IPPROTO_UDP
it 'sets the socket protocol' do
Addrinfo.udp(ip_address, 80).protocol.should == Socket::IPPROTO_UDP
end
end
end
end

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

@ -1,7 +1,6 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
platform_is_not :windows do
with_feature :unix_socket do
describe "Addrinfo#unix_path" do
describe "for an ipv4 socket" do
@ -25,15 +24,13 @@ platform_is_not :windows do
end
end
platform_is_not :windows do
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")
end
describe "for a unix socket" do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")
end
it "returns the socket path" do
@addrinfo.unix_path.should == "/tmp/sock"
end
it "returns the socket path" do
@addrinfo.unix_path.should == "/tmp/sock"
end
end
end

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

@ -1,18 +1,35 @@
require_relative '../../../spec_helper'
require 'socket'
require_relative '../spec_helper'
describe "Addrinfo.unix" do
platform_is_not :windows do
before :each do
@addrinfo = Addrinfo.unix("/tmp/sock")
with_feature :unix_socket do
describe 'Addrinfo.unix' do
it 'returns an Addrinfo instance' do
Addrinfo.unix('socket').should be_an_instance_of(Addrinfo)
end
it "creates a addrinfo for a unix socket" do
@addrinfo.pfamily.should == Socket::PF_UNIX
@addrinfo.socktype.should == Socket::SOCK_STREAM
@addrinfo.protocol.should == 0
@addrinfo.unix_path.should == "/tmp/sock"
it 'sets the IP address' do
Addrinfo.unix('socket').unix_path.should == 'socket'
end
it 'sets the address family' do
Addrinfo.unix('socket').afamily.should == Socket::AF_UNIX
end
it 'sets the protocol family' do
Addrinfo.unix('socket').pfamily.should == Socket::PF_UNIX
end
it 'sets the socket type' do
Addrinfo.unix('socket').socktype.should == Socket::SOCK_STREAM
end
it 'sets a custom socket type' do
addr = Addrinfo.unix('socket', Socket::SOCK_DGRAM)
addr.socktype.should == Socket::SOCK_DGRAM
end
it 'sets the socket protocol to 0' do
Addrinfo.unix('socket').protocol.should == 0
end
end
end

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

@ -0,0 +1,31 @@
require_relative '../spec_helper'
with_feature :ancillary_data do
describe 'Socket::AncillaryData#cmsg_is?' do
describe 'using :INET, :IP, :TTL as the family, level, and type' do
before do
@data = Socket::AncillaryData.new(:INET, :IP, :TTL, '')
end
it 'returns true when comparing with IPPROTO_IP and IP_TTL' do
@data.cmsg_is?(Socket::IPPROTO_IP, Socket::IP_TTL).should == true
end
it 'returns true when comparing with :IP and :TTL' do
@data.cmsg_is?(:IP, :TTL).should == true
end
it 'returns false when comparing with :IP and :PKTINFO' do
@data.cmsg_is?(:IP, :PKTINFO).should == false
end
it 'returns false when comparing with :SOCKET and :RIGHTS' do
@data.cmsg_is?(:SOCKET, :RIGHTS).should == false
end
it 'raises SocketError when comparign with :IPV6 and :RIGHTS' do
lambda { @data.cmsg_is?(:IPV6, :RIGHTS) }.should raise_error(SocketError)
end
end
end
end

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

@ -0,0 +1,9 @@
require_relative '../spec_helper'
with_feature :ancillary_data do
describe 'Socket::AncillaryData#data' do
it 'returns the data as a String' do
Socket::AncillaryData.new(:INET, :SOCKET, :RIGHTS, 'ugh').data.should == 'ugh'
end
end
end

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

@ -0,0 +1,9 @@
require_relative '../spec_helper'
with_feature :ancillary_data do
describe 'Socket::AncillaryData#family' do
it 'returns the family as a Fixnum' do
Socket::AncillaryData.new(:INET, :SOCKET, :RIGHTS, '').family.should == Socket::AF_INET
end
end
end

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

@ -0,0 +1,282 @@
require_relative '../spec_helper'
with_feature :ancillary_data do
describe 'Socket::AncillaryData#initialize' do
describe 'using Fixnums for the family, level, and type' do
before do
@data = Socket::AncillaryData
.new(Socket::AF_INET, Socket::IPPROTO_IP, Socket::IP_RECVTTL, 'ugh')
end
it 'sets the address family' do
@data.family.should == Socket::AF_INET
end
it 'sets the message level' do
@data.level.should == Socket::IPPROTO_IP
end
it 'sets the message type' do
@data.type.should == Socket::IP_RECVTTL
end
it 'sets the data' do
@data.data.should == 'ugh'
end
end
describe 'using Symbols for the family, level, and type' do
before do
@data = Socket::AncillaryData.new(:INET, :IPPROTO_IP, :RECVTTL, 'ugh')
end
it 'sets the address family' do
@data.family.should == Socket::AF_INET
end
it 'sets the message level' do
@data.level.should == Socket::IPPROTO_IP
end
it 'sets the message type' do
@data.type.should == Socket::IP_RECVTTL
end
it 'sets the data' do
@data.data.should == 'ugh'
end
end
describe 'using Strings for the family, level, and type' do
before do
@data = Socket::AncillaryData.new('INET', 'IPPROTO_IP', 'RECVTTL', 'ugh')
end
it 'sets the address family' do
@data.family.should == Socket::AF_INET
end
it 'sets the message level' do
@data.level.should == Socket::IPPROTO_IP
end
it 'sets the message type' do
@data.type.should == Socket::IP_RECVTTL
end
it 'sets the data' do
@data.data.should == 'ugh'
end
end
describe 'using custom objects with a to_str method for the family, level, and type' do
before do
fmock = mock(:family)
lmock = mock(:level)
tmock = mock(:type)
dmock = mock(:data)
fmock.stub!(:to_str).and_return('INET')
lmock.stub!(:to_str).and_return('IP')
tmock.stub!(:to_str).and_return('RECVTTL')
dmock.stub!(:to_str).and_return('ugh')
@data = Socket::AncillaryData.new(fmock, lmock, tmock, dmock)
end
it 'sets the address family' do
@data.family.should == Socket::AF_INET
end
it 'sets the message level' do
@data.level.should == Socket::IPPROTO_IP
end
it 'sets the message type' do
@data.type.should == Socket::IP_RECVTTL
end
it 'sets the data' do
@data.data.should == 'ugh'
end
end
describe 'using :AF_INET as the family and :SOCKET as the level' do
it 'sets the type to SCM_RIGHTS when using :RIGHTS as the type argument' do
Socket::AncillaryData.new(:INET, :SOCKET, :RIGHTS, '').type.should == Socket::SCM_RIGHTS
end
it 'sets the type to SCM_TIMESTAMP when using :TIMESTAMP as the type argument' do
Socket::AncillaryData.new(:INET, :SOCKET, :TIMESTAMP, '').type.should == Socket::SCM_TIMESTAMP
end
it 'raises TypeError when using a numeric string as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :IGMP, Socket::SCM_RIGHTS.to_s, '')
}.should raise_error(TypeError)
end
it 'raises SocketError when using :RECVTTL as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :SOCKET, :RECVTTL, '')
}.should raise_error(SocketError)
end
it 'raises SocketError when using :MOO as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :SOCKET, :MOO, '')
}.should raise_error(SocketError)
end
it 'raises SocketError when using :IP_RECVTTL as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :SOCKET, :IP_RECVTTL, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_INET as the family and :SOCKET as the level' do
it 'sets the type to SCM_RIGHTS when using :RIGHTS as the type argument' do
Socket::AncillaryData.new(:INET, :SOCKET, :RIGHTS, '').type.should == Socket::SCM_RIGHTS
end
end
describe 'using :AF_INET as the family and :IP as the level' do
it 'sets the type to IP_RECVTTL when using :RECVTTL as the type argument' do
Socket::AncillaryData.new(:INET, :IP, :RECVTTL, '').type.should == Socket::IP_RECVTTL
end
with_feature :ip_mtu do
it 'sets the type to IP_MTU when using :MTU as the type argument' do
Socket::AncillaryData.new(:INET, :IP, :MTU, '').type.should == Socket::IP_MTU
end
end
it 'raises SocketError when using :RIGHTS as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :IP, :RIGHTS, '')
}.should raise_error(SocketError)
end
it 'raises SocketError when using :MOO as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :IP, :MOO, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_INET as the family and :IPV6 as the level' do
it 'sets the type to IPV6_CHECKSUM when using :CHECKSUM as the type argument' do
Socket::AncillaryData.new(:INET, :IPV6, :CHECKSUM, '').type.should == Socket::IPV6_CHECKSUM
end
with_feature :ipv6_nexthop do
it 'sets the type to IPV6_NEXTHOP when using :NEXTHOP as the type argument' do
Socket::AncillaryData.new(:INET, :IPV6, :NEXTHOP, '').type.should == Socket::IPV6_NEXTHOP
end
end
it 'raises SocketError when using :RIGHTS as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :IPV6, :RIGHTS, '')
}.should raise_error(SocketError)
end
it 'raises SocketError when using :MOO as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :IPV6, :MOO, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_INET as the family and :TCP as the level' do
with_feature :tcp_cork do
it 'sets the type to TCP_CORK when using :CORK as the type argument' do
Socket::AncillaryData.new(:INET, :TCP, :CORK, '').type.should == Socket::TCP_CORK
end
end
with_feature :tcp_info do
it 'sets the type to TCP_INFO when using :INFO as the type argument' do
Socket::AncillaryData.new(:INET, :TCP, :INFO, '').type.should == Socket::TCP_INFO
end
end
it 'raises SocketError when using :RIGHTS as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :TCP, :RIGHTS, '')
}.should raise_error(SocketError)
end
it 'raises SocketError when using :MOO as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :TCP, :MOO, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_INET as the family and :UDP as the level' do
with_feature :udp_cork do
it 'sets the type to UDP_CORK when using :CORK as the type argument' do
Socket::AncillaryData.new(:INET, :UDP, :CORK, '').type.should == Socket::UDP_CORK
end
end
it 'raises SocketError when using :RIGHTS as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :UDP, :RIGHTS, '')
}.should raise_error(SocketError)
end
it 'raises SocketError when using :MOO as the type argument' do
lambda {
Socket::AncillaryData.new(:INET, :UDP, :MOO, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_UNIX as the family and :SOCKET as the level' do
it 'sets the type to SCM_RIGHTS when using :RIGHTS as the type argument' do
Socket::AncillaryData.new(:UNIX, :SOCKET, :RIGHTS, '').type.should == Socket::SCM_RIGHTS
end
it 'raises SocketError when using :CORK sa the type argument' do
lambda {
Socket::AncillaryData.new(:UNIX, :SOCKET, :CORK, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_UNIX as the family and :IP as the level' do
it 'raises SocketError' do
lambda {
Socket::AncillaryData.new(:UNIX, :IP, :RECVTTL, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_UNIX as the family and :IPV6 as the level' do
it 'raises SocketError' do
lambda {
Socket::AncillaryData.new(:UNIX, :IPV6, :NEXTHOP, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_UNIX as the family and :TCP as the level' do
it 'raises SocketError' do
lambda {
Socket::AncillaryData.new(:UNIX, :TCP, :CORK, '')
}.should raise_error(SocketError)
end
end
describe 'using :AF_UNIX as the family and :UDP as the level' do
it 'raises SocketError' do
lambda {
Socket::AncillaryData.new(:UNIX, :UDP, :CORK, '')
}.should raise_error(SocketError)
end
end
end
end

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

@ -0,0 +1,43 @@
require_relative '../spec_helper'
with_feature :ancillary_data do
describe 'Socket::AncillaryData.int' do
before do
@data = Socket::AncillaryData.int(:INET, :SOCKET, :RIGHTS, 4)
end
it 'returns a Socket::AncillaryData' do
@data.should be_an_instance_of(Socket::AncillaryData)
end
it 'sets the family to AF_INET' do
@data.family.should == Socket::AF_INET
end
it 'sets the level SOL_SOCKET' do
@data.level.should == Socket::SOL_SOCKET
end
it 'sets the type SCM_RIGHTS' do
@data.type.should == Socket::SCM_RIGHTS
end
it 'sets the data to a packed String' do
@data.data.should == [4].pack('I')
end
end
describe 'Socket::AncillaryData#int' do
it 'returns the data as a Fixnum' do
data = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, 4)
data.int.should == 4
end
it 'raises when the data is not a Fixnum' do
data = Socket::AncillaryData.new(:UNIX, :SOCKET, :RIGHTS, 'ugh')
lambda { data.int }.should raise_error(TypeError)
end
end
end

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

@ -0,0 +1,145 @@
require_relative '../spec_helper'
with_feature :ancillary_data do
describe 'Socket::AncillaryData.ip_pktinfo' do
describe 'with a source address and index' do
before do
@data = Socket::AncillaryData.ip_pktinfo(Addrinfo.ip('127.0.0.1'), 4)
end
it 'returns a Socket::AncillaryData' do
@data.should be_an_instance_of(Socket::AncillaryData)
end
it 'sets the family to AF_INET' do
@data.family.should == Socket::AF_INET
end
it 'sets the level to IPPROTO_IP' do
@data.level.should == Socket::IPPROTO_IP
end
it 'sets the type to IP_PKTINFO' do
@data.type.should == Socket::IP_PKTINFO
end
end
describe 'with a source address, index, and destination address' do
before do
source = Addrinfo.ip('127.0.0.1')
dest = Addrinfo.ip('127.0.0.5')
@data = Socket::AncillaryData.ip_pktinfo(source, 4, dest)
end
it 'returns a Socket::AncillaryData' do
@data.should be_an_instance_of(Socket::AncillaryData)
end
it 'sets the family to AF_INET' do
@data.family.should == Socket::AF_INET
end
it 'sets the level to IPPROTO_IP' do
@data.level.should == Socket::IPPROTO_IP
end
it 'sets the type to IP_PKTINFO' do
@data.type.should == Socket::IP_PKTINFO
end
end
end
describe 'Socket::AncillaryData#ip_pktinfo' do
describe 'using an Addrinfo without a port number' do
before do
@source = Addrinfo.ip('127.0.0.1')
@dest = Addrinfo.ip('127.0.0.5')
@data = Socket::AncillaryData.ip_pktinfo(@source, 4, @dest)
end
it 'returns an Array' do
@data.ip_pktinfo.should be_an_instance_of(Array)
end
describe 'the returned Array' do
before do
@info = @data.ip_pktinfo
end
it 'stores an Addrinfo at index 0' do
@info[0].should be_an_instance_of(Addrinfo)
end
it 'stores the ifindex at index 1' do
@info[1].should be_an_instance_of(Fixnum)
end
it 'stores an Addrinfo at index 2' do
@info[2].should be_an_instance_of(Addrinfo)
end
end
describe 'the source Addrinfo' do
before do
@addr = @data.ip_pktinfo[0]
end
it 'uses the correct IP address' do
@addr.ip_address.should == '127.0.0.1'
end
it 'is not the same object as the input Addrinfo' do
@addr.should_not == @source
end
end
describe 'the ifindex' do
it 'is a Fixnum' do
@data.ip_pktinfo[1].should == 4
end
end
describe 'the destination Addrinfo' do
before do
@addr = @data.ip_pktinfo[2]
end
it 'uses the correct IP address' do
@addr.ip_address.should == '127.0.0.5'
end
it 'is not the same object as the input Addrinfo' do
@addr.should_not == @dest
end
end
end
describe 'using an Addrinfo with a port number' do
before do
@source = Addrinfo.tcp('127.0.0.1', 80)
@dest = Addrinfo.tcp('127.0.0.5', 85)
@data = Socket::AncillaryData.ip_pktinfo(@source, 4, @dest)
end
describe 'the source Addrinfo' do
before do
@addr = @data.ip_pktinfo[0]
end
it 'does not contain a port number' do
@addr.ip_port.should == 0
end
end
describe 'the destination Addrinfo' do
before do
@addr = @data.ip_pktinfo[2]
end
it 'does not contain a port number' do
@addr.ip_port.should == 0
end
end
end
end
end

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

@ -0,0 +1,11 @@
require_relative '../spec_helper'
with_feature :ancillary_data, :ipv6_pktinfo do
describe 'Socket::AncillaryData#ipv6_pktinfo_addr' do
it 'returns an Addrinfo' do
data = Socket::AncillaryData.ipv6_pktinfo(Addrinfo.ip('::1'), 4)
data.ipv6_pktinfo_addr.should be_an_instance_of(Addrinfo)
end
end
end

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше