diff options
Diffstat (limited to 'spec/ruby/core/struct')
-rw-r--r-- | spec/ruby/core/struct/constants_spec.rb | 15 | ||||
-rw-r--r-- | spec/ruby/core/struct/deconstruct_keys_spec.rb | 2 | ||||
-rw-r--r-- | spec/ruby/core/struct/fixtures/classes.rb | 6 | ||||
-rw-r--r-- | spec/ruby/core/struct/initialize_spec.rb | 18 | ||||
-rw-r--r-- | spec/ruby/core/struct/inspect_spec.rb | 5 | ||||
-rw-r--r-- | spec/ruby/core/struct/keyword_init_spec.rb | 40 | ||||
-rw-r--r-- | spec/ruby/core/struct/new_spec.rb | 19 | ||||
-rw-r--r-- | spec/ruby/core/struct/shared/inspect.rb | 35 | ||||
-rw-r--r-- | spec/ruby/core/struct/values_at_spec.rb | 55 |
9 files changed, 183 insertions, 12 deletions
diff --git a/spec/ruby/core/struct/constants_spec.rb b/spec/ruby/core/struct/constants_spec.rb new file mode 100644 index 0000000000..fa61a4b912 --- /dev/null +++ b/spec/ruby/core/struct/constants_spec.rb @@ -0,0 +1,15 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.2" do + describe "Struct::Group" do + it "is no longer defined" do + Struct.should_not.const_defined?(:Group) + end + end + + describe "Struct::Passwd" do + it "is no longer defined" do + Struct.should_not.const_defined?(:Passwd) + end + end +end diff --git a/spec/ruby/core/struct/deconstruct_keys_spec.rb b/spec/ruby/core/struct/deconstruct_keys_spec.rb index 088803d028..b4c84c49df 100644 --- a/spec/ruby/core/struct/deconstruct_keys_spec.rb +++ b/spec/ruby/core/struct/deconstruct_keys_spec.rb @@ -64,7 +64,7 @@ describe "Struct#deconstruct_keys" do obj.deconstruct_keys(nil).should == {x: 1, y: 2} end - it "raise TypeError if passed anything accept nil or array" do + it "raise TypeError if passed anything except nil or array" do struct = Struct.new(:x, :y) s = struct.new(1, 2) diff --git a/spec/ruby/core/struct/fixtures/classes.rb b/spec/ruby/core/struct/fixtures/classes.rb index 6d620f9060..bf838d05df 100644 --- a/spec/ruby/core/struct/fixtures/classes.rb +++ b/spec/ruby/core/struct/fixtures/classes.rb @@ -13,6 +13,12 @@ module StructClasses end end + class StructWithOverriddenName < Struct.new(:a) + def self.name + "A" + end + end + class SubclassX < Struct end diff --git a/spec/ruby/core/struct/initialize_spec.rb b/spec/ruby/core/struct/initialize_spec.rb index e82289071a..a5ebe9551c 100644 --- a/spec/ruby/core/struct/initialize_spec.rb +++ b/spec/ruby/core/struct/initialize_spec.rb @@ -40,4 +40,22 @@ describe "Struct#initialize" do it "can be overridden" do StructClasses::SubclassX.new(:y).new.key.should == :value end + + ruby_version_is "3.1"..."3.2" do + it "warns about passing only keyword arguments" do + -> { + StructClasses::Ruby.new(version: "3.1", platform: "OS") + }.should complain(/warning: Passing only keyword arguments/) + end + end + + ruby_version_is "3.2" do + it "can be initialized with keyword arguments" do + positional_args = StructClasses::Ruby.new("3.2", "OS") + keyword_args = StructClasses::Ruby.new(version: "3.2", platform: "OS") + + positional_args.version.should == keyword_args.version + positional_args.platform.should == keyword_args.platform + end + end end diff --git a/spec/ruby/core/struct/inspect_spec.rb b/spec/ruby/core/struct/inspect_spec.rb index 83e13597ba..657b06abc1 100644 --- a/spec/ruby/core/struct/inspect_spec.rb +++ b/spec/ruby/core/struct/inspect_spec.rb @@ -3,10 +3,5 @@ require_relative 'fixtures/classes' require_relative 'shared/inspect' describe "Struct#inspect" do - it "returns a string representation showing members and values" do - car = StructClasses::Car.new('Ford', 'Ranger') - car.inspect.should == '#<struct StructClasses::Car make="Ford", model="Ranger", year=nil>' - end - it_behaves_like :struct_inspect, :inspect end diff --git a/spec/ruby/core/struct/keyword_init_spec.rb b/spec/ruby/core/struct/keyword_init_spec.rb new file mode 100644 index 0000000000..8de4c14351 --- /dev/null +++ b/spec/ruby/core/struct/keyword_init_spec.rb @@ -0,0 +1,40 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + # See https://bugs.ruby-lang.org/issues/18008 + describe "StructClass#keyword_init?" do + it "returns true for a struct that accepts keyword arguments to initialize" do + struct = Struct.new(:arg, keyword_init: true) + struct.keyword_init?.should be_true + end + + it "returns false for a struct that does not accept keyword arguments to initialize" do + struct = Struct.new(:arg, keyword_init: false) + struct.keyword_init?.should be_false + end + + it "returns nil for a struct that did not explicitly specify keyword_init" do + struct = Struct.new(:arg) + struct.keyword_init?.should be_nil + end + + it "returns nil for a struct that does specify keyword_init to be nil" do + struct = Struct.new(:arg, keyword_init: nil) + struct.keyword_init?.should be_nil + end + + it "returns true for any truthy value, not just for true" do + struct = Struct.new(:arg, keyword_init: 1) + struct.keyword_init?.should be_true + + struct = Struct.new(:arg, keyword_init: "") + struct.keyword_init?.should be_true + + struct = Struct.new(:arg, keyword_init: []) + struct.keyword_init?.should be_true + + struct = Struct.new(:arg, keyword_init: {}) + struct.keyword_init?.should be_true + end + end +end diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb index 7b4a4f7980..a94eb852e1 100644 --- a/spec/ruby/core/struct/new_spec.rb +++ b/spec/ruby/core/struct/new_spec.rb @@ -47,6 +47,11 @@ describe "Struct.new" do Struct.const_defined?("Animal2").should be_false end + it "allows non-ASCII member name" do + name = "r\xe9sum\xe9".dup.force_encoding(Encoding::ISO_8859_1).to_sym + struct = Struct.new(name) + struct.new("foo").send(name).should == "foo" + end it "fails with invalid constant name as first argument" do -> { Struct.new('animal', :name, :legs, :eyeballs) }.should raise_error(NameError) @@ -78,6 +83,20 @@ describe "Struct.new" do end end + ruby_version_is ""..."3.3" do + it "raises ArgumentError if not provided any arguments" do + -> { Struct.new }.should raise_error(ArgumentError) + end + end + + ruby_version_is "3.3" do + it "works when not provided any arguments" do + c = Struct.new + c.should be_kind_of(Class) + c.superclass.should == Struct + end + end + it "raises ArgumentError when there is a duplicate member" do -> { Struct.new(:foo, :foo) }.should raise_error(ArgumentError, "duplicate member: foo") end diff --git a/spec/ruby/core/struct/shared/inspect.rb b/spec/ruby/core/struct/shared/inspect.rb index 90594a5452..1a0fb6a6b2 100644 --- a/spec/ruby/core/struct/shared/inspect.rb +++ b/spec/ruby/core/struct/shared/inspect.rb @@ -1,5 +1,40 @@ describe :struct_inspect, shared: true do + it "returns a string representation showing members and values" do + car = StructClasses::Car.new('Ford', 'Ranger') + car.send(@method).should == '#<struct StructClasses::Car make="Ford", model="Ranger", year=nil>' + end + it "returns a string representation without the class name for anonymous structs" do Struct.new(:a).new("").send(@method).should == '#<struct a="">' end + + it "returns a string representation without the class name for structs nested in anonymous classes" do + c = Class.new + c.class_eval <<~DOC + class Foo < Struct.new(:a); end + DOC + + c::Foo.new("").send(@method).should == '#<struct a="">' + end + + it "returns a string representation without the class name for structs nested in anonymous modules" do + m = Module.new + m.module_eval <<~DOC + class Foo < Struct.new(:a); end + DOC + + m::Foo.new("").send(@method).should == '#<struct a="">' + end + + it "does not call #name method" do + struct = StructClasses::StructWithOverriddenName.new("") + struct.send(@method).should == '#<struct StructClasses::StructWithOverriddenName a="">' + end + + it "does not call #name method when struct is anonymous" do + struct = Struct.new(:a) + def struct.name; "A"; end + + struct.new("").send(@method).should == '#<struct a="">' + end end diff --git a/spec/ruby/core/struct/values_at_spec.rb b/spec/ruby/core/struct/values_at_spec.rb index e7d287cba2..5e5a496600 100644 --- a/spec/ruby/core/struct/values_at_spec.rb +++ b/spec/ruby/core/struct/values_at_spec.rb @@ -1,16 +1,59 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +# Should be synchronized with core/array/values_at_spec.rb describe "Struct#values_at" do - it "returns an array of values" do + before do clazz = Struct.new(:name, :director, :year) - movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002) - movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park'] - movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002] + @movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002) + end + + context "when passed a list of Integers" do + it "returns an array containing each value given by one of integers" do + @movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park'] + end + + it "raises IndexError if any of integers is out of range" do + -> { @movie.values_at(3) }.should raise_error(IndexError, "offset 3 too large for struct(size:3)") + -> { @movie.values_at(-4) }.should raise_error(IndexError, "offset -4 too small for struct(size:3)") + end + end + + context "when passed an integer Range" do + it "returns an array containing each value given by the elements of the range" do + @movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002] + end + + it "fills with nil values for range elements larger than the structure" do + @movie.values_at(0..3).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, nil] + end + + it "raises RangeError if any element of the range is negative and out of range" do + -> { @movie.values_at(-4..3) }.should raise_error(RangeError, "-4..3 out of range") + end + + it "supports endless Range" do + @movie.values_at(0..).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002] + end + + it "supports beginningless Range" do + @movie.values_at(..2).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002] + end + end + + it "supports multiple integer Ranges" do + @movie.values_at(0..2, 1..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 'Chan-wook Park', 2002] + end + + it "supports mixing integer Ranges and Integers" do + @movie.values_at(0..2, 2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 2002] + end + + it "returns a new empty Array if no arguments given" do + @movie.values_at().should == [] end it "fails when passed unsupported types" do - car = StructClasses::Car.new('Ford', 'Ranger') - -> { car.values_at('make') }.should raise_error(TypeError) + -> { @movie.values_at('make') }.should raise_error(TypeError, "no implicit conversion of String into Integer") end end |