summaryrefslogtreecommitdiff
path: root/test/ruby/test_namespace.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_namespace.rb')
-rw-r--r--test/ruby/test_namespace.rb618
1 files changed, 0 insertions, 618 deletions
diff --git a/test/ruby/test_namespace.rb b/test/ruby/test_namespace.rb
deleted file mode 100644
index cd59306867..0000000000
--- a/test/ruby/test_namespace.rb
+++ /dev/null
@@ -1,618 +0,0 @@
-# frozen_string_literal: true
-
-require 'test/unit'
-
-class TestNamespace < Test::Unit::TestCase
- ENV_ENABLE_NAMESPACE = {'RUBY_NAMESPACE' => '1'}
-
- def setup
- @n = Namespace.new if Namespace.enabled?
- end
-
- def teardown
- @n = nil
- end
-
- def test_namespace_availability
- env_has_RUBY_NAMESPACE = (ENV['RUBY_NAMESPACE'].to_i == 1)
- assert_equal env_has_RUBY_NAMESPACE, Namespace.enabled?
- end
-
- def test_current_namespace
- pend unless Namespace.enabled?
-
- main = Namespace.current
- assert main.inspect.include?("main")
-
- @n.require_relative('namespace/current')
-
- assert_equal @n, @n::CurrentNamespace.in_require
- assert_equal @n, @n::CurrentNamespace.in_method_call
- assert_equal main, Namespace.current
- end
-
- def test_require_rb_separately
- pend unless Namespace.enabled?
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
-
- @n.require(File.join(__dir__, 'namespace', 'a.1_1_0'))
-
- assert_not_nil @n::NS_A
- assert_not_nil @n::NS_B
- assert_equal "1.1.0", @n::NS_A::VERSION
- assert_equal "yay 1.1.0", @n::NS_A.new.yay
- assert_equal "1.1.0", @n::NS_B::VERSION
- assert_equal "yay_b1", @n::NS_B.yay
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
- end
-
- def test_require_relative_rb_separately
- pend unless Namespace.enabled?
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
-
- @n.require_relative('namespace/a.1_1_0')
-
- assert_not_nil @n::NS_A
- assert_not_nil @n::NS_B
- assert_equal "1.1.0", @n::NS_A::VERSION
- assert_equal "yay 1.1.0", @n::NS_A.new.yay
- assert_equal "1.1.0", @n::NS_B::VERSION
- assert_equal "yay_b1", @n::NS_B.yay
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
- end
-
- def test_load_separately
- pend unless Namespace.enabled?
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
-
- @n.load(File.join(__dir__, 'namespace', 'a.1_1_0.rb'))
-
- assert_not_nil @n::NS_A
- assert_not_nil @n::NS_B
- assert_equal "1.1.0", @n::NS_A::VERSION
- assert_equal "yay 1.1.0", @n::NS_A.new.yay
- assert_equal "1.1.0", @n::NS_B::VERSION
- assert_equal "yay_b1", @n::NS_B.yay
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
- end
-
- def test_namespace_in_namespace
- pend unless Namespace.enabled?
-
- assert_raise(NameError) { NS1 }
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
-
- @n.require_relative('namespace/ns')
-
- assert_not_nil @n::NS1
- assert_not_nil @n::NS1::NS_A
- assert_not_nil @n::NS1::NS_B
- assert_equal "1.1.0", @n::NS1::NS_A::VERSION
- assert_equal "yay 1.1.0", @n::NS1::NS_A.new.yay
- assert_equal "1.1.0", @n::NS1::NS_B::VERSION
- assert_equal "yay_b1", @n::NS1::NS_B.yay
-
- assert_raise(NameError) { NS1 }
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
- end
-
- def test_require_rb_2versions
- pend unless Namespace.enabled?
-
- assert_raise(NameError) { NS_A }
-
- @n.require(File.join(__dir__, 'namespace', 'a.1_2_0'))
- assert_equal "1.2.0", @n::NS_A::VERSION
- assert_equal "yay 1.2.0", @n::NS_A.new.yay
-
- n2 = Namespace.new
- n2.require(File.join(__dir__, 'namespace', 'a.1_1_0'))
- assert_equal "1.1.0", n2::NS_A::VERSION
- assert_equal "yay 1.1.0", n2::NS_A.new.yay
-
- # recheck @n is not affected by the following require
- assert_equal "1.2.0", @n::NS_A::VERSION
- assert_equal "yay 1.2.0", @n::NS_A.new.yay
-
- assert_raise(NameError) { NS_A }
- end
-
- def test_raising_errors_in_require
- pend unless Namespace.enabled?
-
- assert_raise(RuntimeError, "Yay!") { @n.require(File.join(__dir__, 'namespace', 'raise')) }
- assert Namespace.current.inspect.include?("main")
- end
-
- def test_autoload_in_namespace
- pend unless Namespace.enabled?
-
- assert_raise(NameError) { NS_A }
-
- @n.require_relative('namespace/autoloading')
- # autoloaded A is visible from global
- assert_equal '1.1.0', @n::NS_A::VERSION
-
- assert_raise(NameError) { NS_A }
-
- # autoload trigger NS_B::BAR is valid even from global
- assert_equal 'bar_b1', @n::NS_B::BAR
-
- assert_raise(NameError) { NS_A }
- assert_raise(NameError) { NS_B }
- end
-
- def test_continuous_top_level_method_in_a_namespace
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/define_toplevel')
- @n.require_relative('namespace/call_toplevel')
-
- assert_raise(NameError) { foo }
- end
-
- def test_top_level_methods_in_namespace
- pend # TODO: fix loading/current namespace detection
- pend unless Namespace.enabled?
- @n.require_relative('namespace/top_level')
- assert_equal "yay!", @n::Foo.foo
- assert_raise(NameError) { yaaay }
- assert_equal "foo", @n::Bar.bar
- assert_raise_with_message(RuntimeError, "boooo") { @n::Baz.baz }
- end
-
- def test_proc_defined_in_namespace_refers_module_in_namespace
- pend unless Namespace.enabled?
-
- # require_relative dosn't work well in assert_separately even with __FILE__ and __LINE__
- assert_separately([ENV_ENABLE_NAMESPACE], __FILE__, __LINE__, "here = '#{__dir__}'; #{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- ns1 = Namespace.new
- ns1.require(File.join("#{here}", 'namespace/proc_callee'))
- proc_v = ns1::Foo.callee
- assert_raise(NameError) { Target }
- assert ns1::Target
- assert_equal "fooooo", proc_v.call # refers Target in the namespace ns1
- ns1.require(File.join("#{here}", 'namespace/proc_caller'))
- assert_equal "fooooo", ns1::Bar.caller(proc_v)
-
- ns2 = Namespace.new
- ns2.require(File.join("#{here}", 'namespace/proc_caller'))
- assert_raise(NameError) { ns2::Target }
- assert_equal "fooooo", ns2::Bar.caller(proc_v) # refers Target in the namespace ns1
- end;
- end
-
- def test_proc_defined_globally_refers_global_module
- pend unless Namespace.enabled?
-
- # require_relative dosn't work well in assert_separately even with __FILE__ and __LINE__
- assert_separately([ENV_ENABLE_NAMESPACE], __FILE__, __LINE__, "here = '#{__dir__}'; #{<<~"begin;"}\n#{<<~'end;'}", ignore_stderr: true)
- begin;
- require(File.join("#{here}", 'namespace/proc_callee'))
- def Target.foo
- "yay"
- end
- proc_v = Foo.callee
- assert Target
- assert_equal "yay", proc_v.call # refers global Foo
- ns1 = Namespace.new
- ns1.require(File.join("#{here}", 'namespace/proc_caller'))
- assert_equal "yay", ns1::Bar.caller(proc_v)
-
- ns2 = Namespace.new
- ns2.require(File.join("#{here}", 'namespace/proc_callee'))
- ns2.require(File.join("#{here}", 'namespace/proc_caller'))
- assert_equal "fooooo", ns2::Foo.callee.call
- assert_equal "yay", ns2::Bar.caller(proc_v) # should refer the global Target, not Foo in ns2
- end;
- end
-
- def test_instance_variable
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/instance_variables')
-
- assert_equal [], String.instance_variables
- assert_equal [:@str_ivar1, :@str_ivar2], @n::StringDelegatorObj.instance_variables
- assert_equal 111, @n::StringDelegatorObj.str_ivar1
- assert_equal 222, @n::StringDelegatorObj.str_ivar2
- assert_equal 222, @n::StringDelegatorObj.instance_variable_get(:@str_ivar2)
-
- @n::StringDelegatorObj.instance_variable_set(:@str_ivar3, 333)
- assert_equal 333, @n::StringDelegatorObj.instance_variable_get(:@str_ivar3)
- @n::StringDelegatorObj.remove_instance_variable(:@str_ivar1)
- assert_nil @n::StringDelegatorObj.str_ivar1
- assert_equal [:@str_ivar2, :@str_ivar3], @n::StringDelegatorObj.instance_variables
-
- assert_equal [], String.instance_variables
- end
-
- def test_methods_added_in_namespace_are_invisible_globally
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/string_ext')
-
- assert_equal "yay", @n::Bar.yay
-
- assert_raise(NoMethodError){ String.new.yay }
- end
-
- def test_continuous_method_definitions_in_a_namespace
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/string_ext')
- assert_equal "yay", @n::Bar.yay
-
- @n.require_relative('namespace/string_ext_caller')
- assert_equal "yay", @n::Foo.yay
-
- @n.require_relative('namespace/string_ext_calling')
- end
-
- def test_methods_added_in_namespace_later_than_caller_code
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/string_ext_caller')
- @n.require_relative('namespace/string_ext')
-
- assert_equal "yay", @n::Bar.yay
- assert_equal "yay", @n::Foo.yay
- end
-
- def test_method_added_in_namespace_are_available_on_eval
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/string_ext')
- @n.require_relative('namespace/string_ext_eval_caller')
-
- assert_equal "yay", @n::Baz.yay
- end
-
- def test_method_added_in_namespace_are_available_on_eval_with_binding
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/string_ext')
- @n.require_relative('namespace/string_ext_eval_caller')
-
- assert_equal "yay, yay!", @n::Baz.yay_with_binding
- end
-
- def test_methods_and_constants_added_by_include
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/open_class_with_include')
-
- assert_equal "I'm saying foo 1", @n::OpenClassWithInclude.say
- assert_equal "I'm saying foo 1", @n::OpenClassWithInclude.say_foo
- assert_equal "I'm saying foo 1", @n::OpenClassWithInclude.say_with_obj("wow")
-
- assert_raise(NameError) { String::FOO }
-
- assert_equal "foo 1", @n::OpenClassWithInclude.refer_foo
- end
-end
-
-module ProcLookupTestA
- module B
- VALUE = 111
- end
-end
-
-class TestNamespace < Test::Unit::TestCase
- def make_proc_from_block(&b)
- b
- end
-
- def test_proc_from_main_works_with_global_definitions
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/procs')
-
- proc_and_labels = [
- [Proc.new { String.new.yay }, "Proc.new"],
- [proc { String.new.yay }, "proc{}"],
- [lambda { String.new.yay }, "lambda{}"],
- [->(){ String.new.yay }, "->(){}"],
- [make_proc_from_block { String.new.yay }, "make_proc_from_block"],
- [@n::ProcInNS.make_proc_from_block { String.new.yay }, "make_proc_from_block in @n"],
- ]
-
- proc_and_labels.each do |str_pr|
- pr, pr_label = str_pr
- assert_raise(NoMethodError, "NoMethodError expected: #{pr_label}, called in main") { pr.call }
- assert_raise(NoMethodError, "NoMethodError expected: #{pr_label}, called in @n") { @n::ProcInNS.call_proc(pr) }
- end
-
- const_and_labels = [
- [Proc.new { ProcLookupTestA::B::VALUE }, "Proc.new"],
- [proc { ProcLookupTestA::B::VALUE }, "proc{}"],
- [lambda { ProcLookupTestA::B::VALUE }, "lambda{}"],
- [->(){ ProcLookupTestA::B::VALUE }, "->(){}"],
- [make_proc_from_block { ProcLookupTestA::B::VALUE }, "make_proc_from_block"],
- [@n::ProcInNS.make_proc_from_block { ProcLookupTestA::B::VALUE }, "make_proc_from_block in @n"],
- ]
-
- const_and_labels.each do |const_pr|
- pr, pr_label = const_pr
- assert_equal 111, pr.call, "111 expected, #{pr_label} called in main"
- assert_equal 111, @n::ProcInNS.call_proc(pr), "111 expected, #{pr_label} called in @n"
- end
- end
-
- def test_proc_from_namespace_works_with_definitions_in_namespace
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/procs')
-
- proc_types = [:proc_new, :proc_f, :lambda_f, :lambda_l, :block]
-
- proc_types.each do |proc_type|
- assert_equal 222, @n::ProcInNS.make_const_proc(proc_type).call, "ProcLookupTestA::B::VALUE should be 222 in @n"
- assert_equal "foo", @n::ProcInNS.make_str_const_proc(proc_type).call, "String::FOO should be \"foo\" in @n"
- assert_equal "yay", @n::ProcInNS.make_str_proc(proc_type).call, "String#yay should be callable in @n"
- #
- # TODO: method calls not-in-methods nor procs can't handle the current namespace correctly.
- #
- # assert_equal "yay,foo,222",
- # @n::ProcInNS.const_get(('CONST_' + proc_type.to_s.upcase).to_sym).call,
- # "Proc assigned to constants should refer constants correctly in @n"
- end
- end
-
- def test_class_module_singleton_methods
- pend unless Namespace.enabled?
-
- @n.require_relative('namespace/singleton_methods')
-
- assert_equal "Good evening!", @n::SingletonMethods.string_greeing # def self.greeting
- assert_equal 42, @n::SingletonMethods.integer_answer # class << self; def answer
- assert_equal([], @n::SingletonMethods.array_blank) # def self.blank w/ instance methods
- assert_equal({status: 200, body: 'OK'}, @n::SingletonMethods.hash_http_200) # class << self; def ... w/ instance methods
-
- assert_equal([4, 4], @n::SingletonMethods.array_instance_methods_return_size([1, 2, 3, 4]))
- assert_equal([3, 3], @n::SingletonMethods.hash_instance_methods_return_size({a: 2, b: 4, c: 8}))
-
- assert_raise(NoMethodError) { String.greeting }
- assert_raise(NoMethodError) { Integer.answer }
- assert_raise(NoMethodError) { Array.blank }
- assert_raise(NoMethodError) { Hash.http_200 }
- end
-
- def test_add_constants_in_namespace
- pend unless Namespace.enabled?
-
- String.const_set(:STR_CONST0, 999)
- assert_equal 999, String::STR_CONST0
- assert_equal 999, String.const_get(:STR_CONST0)
-
- assert_raise(NameError) { String.const_get(:STR_CONST1) }
- assert_raise(NameError) { String::STR_CONST2 }
- assert_raise(NameError) { String::STR_CONST3 }
- assert_raise(NameError) { Integer.const_get(:INT_CONST1) }
-
- EnvUtil.suppress_warning do
- @n.require_relative('namespace/consts')
- end
- assert_equal 999, String::STR_CONST0
- assert_raise(NameError) { String::STR_CONST1 }
- assert_raise(NameError) { String::STR_CONST2 }
- assert_raise(NameError) { Integer::INT_CONST1 }
-
- assert_not_nil @n::ForConsts.refer_all
-
- assert_equal 112, @n::ForConsts.refer1
- assert_equal 112, @n::ForConsts.get1
- assert_equal 112, @n::ForConsts::CONST1
- assert_equal 222, @n::ForConsts.refer2
- assert_equal 222, @n::ForConsts.get2
- assert_equal 222, @n::ForConsts::CONST2
- assert_equal 333, @n::ForConsts.refer3
- assert_equal 333, @n::ForConsts.get3
- assert_equal 333, @n::ForConsts::CONST3
-
- EnvUtil.suppress_warning do
- @n::ForConsts.const_set(:CONST3, 334)
- end
- assert_equal 334, @n::ForConsts::CONST3
- assert_equal 334, @n::ForConsts.refer3
- assert_equal 334, @n::ForConsts.get3
-
- assert_equal 10, @n::ForConsts.refer_top_const
-
- # use Proxy object to use usual methods instead of singleton methods
- proxy = @n::ForConsts::Proxy.new
-
- assert_raise(NameError){ proxy.call_str_refer0 }
- assert_raise(NameError){ proxy.call_str_get0 }
-
- proxy.call_str_set0(30)
- assert_equal 30, proxy.call_str_refer0
- assert_equal 30, proxy.call_str_get0
- assert_equal 999, String::STR_CONST0
-
- proxy.call_str_remove0
- assert_raise(NameError){ proxy.call_str_refer0 }
- assert_raise(NameError){ proxy.call_str_get0 }
-
- assert_equal 112, proxy.call_str_refer1
- assert_equal 112, proxy.call_str_get1
- assert_equal 223, proxy.call_str_refer2
- assert_equal 223, proxy.call_str_get2
- assert_equal 333, proxy.call_str_refer3
- assert_equal 333, proxy.call_str_get3
-
- EnvUtil.suppress_warning do
- proxy.call_str_set3
- end
- assert_equal 334, proxy.call_str_refer3
- assert_equal 334, proxy.call_str_get3
-
- assert_equal 1, proxy.refer_int_const1
-
- assert_equal 999, String::STR_CONST0
- assert_raise(NameError) { String::STR_CONST1 }
- assert_raise(NameError) { String::STR_CONST2 }
- assert_raise(NameError) { String::STR_CONST3 }
- assert_raise(NameError) { Integer::INT_CONST1 }
- end
-
- def test_global_variables
- default_l = $-0
- default_f = $,
-
- pend unless Namespace.enabled?
-
- assert_equal "\n", $-0 # equal to $/, line splitter
- assert_equal nil, $, # field splitter
-
- @n.require_relative('namespace/global_vars')
-
- # read first
- assert_equal "\n", @n::LineSplitter.read
- @n::LineSplitter.write("\r\n")
- assert_equal "\r\n", @n::LineSplitter.read
- assert_equal "\n", $-0
-
- # write first
- @n::FieldSplitter.write(",")
- assert_equal ",", @n::FieldSplitter.read
- assert_equal nil, $,
-
- # used only in ns
- assert !global_variables.include?(:$used_only_in_ns)
- @n::UniqueGvar.write(123)
- assert_equal 123, @n::UniqueGvar.read
- assert_nil $used_only_in_ns
-
- # Kernel#global_variables returns the sum of all gvars.
- global_gvars = global_variables.sort
- assert_equal global_gvars, @n::UniqueGvar.gvars_in_ns.sort
- @n::UniqueGvar.write_only(456)
- assert_equal (global_gvars + [:$write_only_var_in_ns]).sort, @n::UniqueGvar.gvars_in_ns.sort
- assert_equal (global_gvars + [:$write_only_var_in_ns]).sort, global_variables.sort
- ensure
- EnvUtil.suppress_warning do
- $-0 = default_l
- $, = default_f
- end
- end
-
- def test_load_path_and_loaded_features
- pend unless Namespace.enabled?
-
- assert $LOAD_PATH.respond_to?(:resolve_feature_path)
-
- @n.require_relative('namespace/load_path')
-
- assert_not_equal $LOAD_PATH, @n::LoadPathCheck::FIRST_LOAD_PATH
-
- assert @n::LoadPathCheck::FIRST_LOAD_PATH_RESPOND_TO_RESOLVE
-
- namespace_dir = File.join(__dir__, 'namespace')
- # TODO: $LOADED_FEATURES in method calls should refer the current namespace in addition to the loading namespace.
- # assert @n::LoadPathCheck.current_loaded_features.include?(File.join(namespace_dir, 'blank1.rb'))
- # assert !@n::LoadPathCheck.current_loaded_features.include?(File.join(namespace_dir, 'blank2.rb'))
- # assert @n::LoadPathCheck.require_blank2
- # assert @n::LoadPathCheck.current_loaded_features.include?(File.join(namespace_dir, 'blank2.rb'))
-
- assert !$LOADED_FEATURES.include?(File.join(namespace_dir, 'blank1.rb'))
- assert !$LOADED_FEATURES.include?(File.join(namespace_dir, 'blank2.rb'))
- end
-
- def test_eval_basic
- pend unless Namespace.enabled?
-
- # Test basic evaluation
- result = @n.eval("1 + 1")
- assert_equal 2, result
-
- # Test string evaluation
- result = @n.eval("'hello ' + 'world'")
- assert_equal "hello world", result
- end
-
- def test_eval_with_constants
- pend unless Namespace.enabled?
-
- # Define a constant in the namespace via eval
- @n.eval("TEST_CONST = 42")
- assert_equal 42, @n::TEST_CONST
-
- # Constant should not be visible in main namespace
- assert_raise(NameError) { TEST_CONST }
- end
-
- def test_eval_with_classes
- pend unless Namespace.enabled?
-
- # Define a class in the namespace via eval
- @n.eval("class TestClass; def hello; 'from namespace'; end; end")
-
- # Class should be accessible in the namespace
- instance = @n::TestClass.new
- assert_equal "from namespace", instance.hello
-
- # Class should not be visible in main namespace
- assert_raise(NameError) { TestClass }
- end
-
- def test_eval_isolation
- pend unless Namespace.enabled?
-
- # Create another namespace
- n2 = Namespace.new
-
- # Define different constants in each namespace
- @n.eval("ISOLATION_TEST = 'first'")
- n2.eval("ISOLATION_TEST = 'second'")
-
- # Each namespace should have its own constant
- assert_equal "first", @n::ISOLATION_TEST
- assert_equal "second", n2::ISOLATION_TEST
-
- # Constants should not interfere with each other
- assert_not_equal @n::ISOLATION_TEST, n2::ISOLATION_TEST
- end
-
- def test_eval_with_variables
- pend unless Namespace.enabled?
-
- # Test local variable access (should work within the eval context)
- result = @n.eval("x = 10; y = 20; x + y")
- assert_equal 30, result
- end
-
- def test_eval_error_handling
- pend unless Namespace.enabled?
-
- # Test syntax error
- assert_raise(SyntaxError) { @n.eval("1 +") }
-
- # Test name error
- assert_raise(NameError) { @n.eval("undefined_variable") }
-
- # Test that namespace is properly restored after error
- begin
- @n.eval("raise RuntimeError, 'test error'")
- rescue RuntimeError
- # Should be able to continue using the namespace
- result = @n.eval("2 + 2")
- assert_equal 4, result
- end
- end
-end