summaryrefslogtreecommitdiff
path: root/spec/ruby/language
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/language')
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rb1
-rw-r--r--spec/ruby/language/fixtures/variables.rb72
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb16
-rw-r--r--spec/ruby/language/predefined_spec.rb4
-rw-r--r--spec/ruby/language/proc_spec.rb12
-rw-r--r--spec/ruby/language/singleton_class_spec.rb17
-rw-r--r--spec/ruby/language/variables_spec.rb80
7 files changed, 199 insertions, 3 deletions
diff --git a/spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rb b/spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rb
index 7a1f872e05..f72a32e879 100644
--- a/spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rb
+++ b/spec/ruby/language/fixtures/freeze_magic_comment_required_diff_enc.rb
@@ -2,4 +2,3 @@
# frozen_string_literal: true
$second_literal_id = "abc".object_id
-
diff --git a/spec/ruby/language/fixtures/variables.rb b/spec/ruby/language/fixtures/variables.rb
index 07265dbb2b..527caa7a78 100644
--- a/spec/ruby/language/fixtures/variables.rb
+++ b/spec/ruby/language/fixtures/variables.rb
@@ -82,4 +82,76 @@ module VariablesSpecs
def self.false
false
end
+
+ class EvalOrder
+ attr_reader :order
+
+ def initialize
+ @order = []
+ end
+
+ def reset
+ @order = []
+ end
+
+ def foo
+ self << "foo"
+ FooClass.new(self)
+ end
+
+ def bar
+ self << "bar"
+ BarClass.new(self)
+ end
+
+ def a
+ self << "a"
+ end
+
+ def b
+ self << "b"
+ end
+
+ def node
+ self << "node"
+
+ node = Node.new
+ node.left = Node.new
+ node.left.right = Node.new
+
+ node
+ end
+
+ def <<(value)
+ order << value
+ end
+
+ class FooClass
+ attr_reader :evaluator
+
+ def initialize(evaluator)
+ @evaluator = evaluator
+ end
+
+ def []=(_index, _value)
+ evaluator << "foo[]="
+ end
+ end
+
+ class BarClass
+ attr_reader :evaluator
+
+ def initialize(evaluator)
+ @evaluator = evaluator
+ end
+
+ def baz=(_value)
+ evaluator << "bar.baz="
+ end
+ end
+
+ class Node
+ attr_accessor :left, :right
+ end
+ end
end
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
index f3cc86fa0b..e4b7a5105e 100644
--- a/spec/ruby/language/pattern_matching_spec.rb
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -205,7 +205,7 @@ describe "Pattern matching" do
in []
end
RUBY
- }.should raise_error(SyntaxError, /syntax error, unexpected `in'/)
+ }.should raise_error(SyntaxError, /syntax error, unexpected `in'|\(eval\):3: syntax error, unexpected keyword_in/)
-> {
eval <<~RUBY
@@ -214,7 +214,7 @@ describe "Pattern matching" do
when 1 == 1
end
RUBY
- }.should raise_error(SyntaxError, /syntax error, unexpected `when'/)
+ }.should raise_error(SyntaxError, /syntax error, unexpected `when'|\(eval\):3: syntax error, unexpected keyword_when/)
end
it "checks patterns until the first matching" do
@@ -251,6 +251,18 @@ describe "Pattern matching" do
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
end
+ it "raises NoMatchingPatternError if no pattern matches and evaluates the expression only once" do
+ evals = 0
+ -> {
+ eval <<~RUBY
+ case (evals += 1; [0, 1])
+ in [0]
+ end
+ RUBY
+ }.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+ evals.should == 1
+ end
+
it "does not allow calculation or method calls in a pattern" do
-> {
eval <<~RUBY
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index d1cda25918..f6cec5fa75 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -979,6 +979,10 @@ describe "Global variable $VERBOSE" do
$VERBOSE = @verbose
end
+ it "is false by default" do
+ $VERBOSE.should be_false
+ end
+
it "converts truthy values to true" do
[true, 1, 0, [], ""].each do |true_value|
$VERBOSE = true_value
diff --git a/spec/ruby/language/proc_spec.rb b/spec/ruby/language/proc_spec.rb
index f8a29962b0..c5876fb2ed 100644
--- a/spec/ruby/language/proc_spec.rb
+++ b/spec/ruby/language/proc_spec.rb
@@ -161,6 +161,18 @@ describe "A Proc" do
end
end
+ describe "taking |*a, b| arguments" do
+ it "assigns [] to the argument when passed no values" do
+ proc { |*a, b| [a, b] }.call.should == [[], nil]
+ end
+ end
+
+ describe "taking |a, *b, c| arguments" do
+ it "assigns [] to the argument when passed no values" do
+ proc { |a, *b, c| [a, b, c] }.call.should == [nil, [], nil]
+ end
+ end
+
describe "taking |a, | arguments" do
before :each do
@l = lambda { |a, | a }
diff --git a/spec/ruby/language/singleton_class_spec.rb b/spec/ruby/language/singleton_class_spec.rb
index c1fb682ea0..7512f0eb39 100644
--- a/spec/ruby/language/singleton_class_spec.rb
+++ b/spec/ruby/language/singleton_class_spec.rb
@@ -291,3 +291,20 @@ describe "Instantiating a singleton class" do
}.should raise_error(TypeError)
end
end
+
+describe "Frozen properties" do
+ it "is frozen if the object it is created from is frozen" do
+ o = Object.new
+ o.freeze
+ klass = o.singleton_class
+ klass.frozen?.should == true
+ end
+
+ it "will be frozen if the object it is created from becomes frozen" do
+ o = Object.new
+ klass = o.singleton_class
+ klass.frozen?.should == false
+ o.freeze
+ klass.frozen?.should == true
+ end
+end
diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb
index c900c03d37..cd862727ac 100644
--- a/spec/ruby/language/variables_spec.rb
+++ b/spec/ruby/language/variables_spec.rb
@@ -1,6 +1,86 @@
require_relative '../spec_helper'
require_relative 'fixtures/variables'
+describe "Evaluation order during assignment" do
+ context "with single assignment" do
+ it "evaluates from left to right" do
+ obj = VariablesSpecs::EvalOrder.new
+ obj.instance_eval do
+ foo[0] = a
+ end
+
+ obj.order.should == ["foo", "a", "foo[]="]
+ end
+ end
+
+ context "with multiple assignment" do
+ ruby_version_is ""..."3.1" do
+ it "does not evaluate from left to right" do
+ obj = VariablesSpecs::EvalOrder.new
+
+ obj.instance_eval do
+ foo[0], bar.baz = a, b
+ end
+
+ obj.order.should == ["a", "b", "foo", "foo[]=", "bar", "bar.baz="]
+ end
+
+ it "cannot be used to swap variables with nested method calls" do
+ node = VariablesSpecs::EvalOrder.new.node
+
+ original_node = node
+ original_node_left = node.left
+ original_node_left_right = node.left.right
+
+ node.left, node.left.right, node = node.left.right, node, node.left
+ # Should evaluate in the order of:
+ # RHS: node.left.right, node, node.left
+ # LHS:
+ # * node(original_node), original_node.left = original_node_left_right
+ # * node(original_node), node.left(changed in the previous assignment to original_node_left_right),
+ # original_node_left_right.right = original_node
+ # * node = original_node_left
+
+ node.should == original_node_left
+ node.right.should_not == original_node
+ node.right.left.should_not == original_node_left_right
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "evaluates from left to right, receivers first then methods" do
+ obj = VariablesSpecs::EvalOrder.new
+ obj.instance_eval do
+ foo[0], bar.baz = a, b
+ end
+
+ obj.order.should == ["foo", "bar", "a", "b", "foo[]=", "bar.baz="]
+ end
+
+ it "can be used to swap variables with nested method calls" do
+ node = VariablesSpecs::EvalOrder.new.node
+
+ original_node = node
+ original_node_left = node.left
+ original_node_left_right = node.left.right
+
+ node.left, node.left.right, node = node.left.right, node, node.left
+ # Should evaluate in the order of:
+ # LHS: node, node.left(original_node_left)
+ # RHS: original_node_left_right, original_node, original_node_left
+ # Ops:
+ # * node(original_node), original_node.left = original_node_left_right
+ # * original_node_left.right = original_node
+ # * node = original_node_left
+
+ node.should == original_node_left
+ node.right.should == original_node
+ node.right.left.should == original_node_left_right
+ end
+ end
+ end
+end
+
describe "Multiple assignment" do
context "with a single RHS value" do
it "assigns a simple MLHS" do