зеркало из https://github.com/github/ruby.git
Update to ruby/spec@9be7c7e
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64180 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
aeeaadaad0
Коммит
b53cf149ad
|
@ -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
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче