PageRenderTime 27ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/activesupport/test/core_ext/module_test.rb

https://gitlab.com/mpivaa/rails
Ruby | 509 lines | 455 code | 51 blank | 3 comment | 0 complexity | ac225ebeb4076005169a55fb70475953 MD5 | raw file
  1. require 'abstract_unit'
  2. require 'active_support/core_ext/module'
  3. module One
  4. Constant1 = "Hello World"
  5. Constant2 = "What's up?"
  6. end
  7. class Ab
  8. include One
  9. Constant1 = "Hello World" # Will have different object id than One::Constant1
  10. Constant3 = "Goodbye World"
  11. end
  12. module Yz
  13. module Zy
  14. class Cd
  15. include One
  16. end
  17. end
  18. end
  19. Somewhere = Struct.new(:street, :city) do
  20. attr_accessor :name
  21. end
  22. class Someone < Struct.new(:name, :place)
  23. delegate :street, :city, :to_f, :to => :place
  24. delegate :name=, :to => :place, :prefix => true
  25. delegate :upcase, :to => "place.city"
  26. delegate :table_name, :to => :class
  27. delegate :table_name, :to => :class, :prefix => true
  28. def self.table_name
  29. 'some_table'
  30. end
  31. FAILED_DELEGATE_LINE = __LINE__ + 1
  32. delegate :foo, :to => :place
  33. FAILED_DELEGATE_LINE_2 = __LINE__ + 1
  34. delegate :bar, :to => :place, :allow_nil => true
  35. end
  36. Invoice = Struct.new(:client) do
  37. delegate :street, :city, :name, :to => :client, :prefix => true
  38. delegate :street, :city, :name, :to => :client, :prefix => :customer
  39. end
  40. Project = Struct.new(:description, :person) do
  41. delegate :name, :to => :person, :allow_nil => true
  42. delegate :to_f, :to => :description, :allow_nil => true
  43. end
  44. Developer = Struct.new(:client) do
  45. delegate :name, :to => :client, :prefix => nil
  46. end
  47. Event = Struct.new(:case) do
  48. delegate :foo, :to => :case
  49. end
  50. Tester = Struct.new(:client) do
  51. delegate :name, :to => :client, :prefix => false
  52. def foo; 1; end
  53. end
  54. Product = Struct.new(:name) do
  55. delegate :name, :to => :manufacturer, :prefix => true
  56. delegate :name, :to => :type, :prefix => true
  57. def manufacturer
  58. @manufacturer ||= begin
  59. nil.unknown_method
  60. end
  61. end
  62. def type
  63. @type ||= begin
  64. nil.type_name
  65. end
  66. end
  67. end
  68. class ParameterSet
  69. delegate :[], :[]=, :to => :@params
  70. def initialize
  71. @params = {:foo => "bar"}
  72. end
  73. end
  74. class Name
  75. delegate :upcase, :to => :@full_name
  76. def initialize(first, last)
  77. @full_name = "#{first} #{last}"
  78. end
  79. end
  80. class SideEffect
  81. attr_reader :ints
  82. delegate :to_i, :to => :shift, :allow_nil => true
  83. delegate :to_s, :to => :shift
  84. def initialize
  85. @ints = [1, 2, 3]
  86. end
  87. def shift
  88. @ints.shift
  89. end
  90. end
  91. class ModuleTest < ActiveSupport::TestCase
  92. def setup
  93. @david = Someone.new("David", Somewhere.new("Paulina", "Chicago"))
  94. end
  95. def test_delegation_to_methods
  96. assert_equal "Paulina", @david.street
  97. assert_equal "Chicago", @david.city
  98. end
  99. def test_delegation_to_assignment_method
  100. @david.place_name = "Fred"
  101. assert_equal "Fred", @david.place.name
  102. end
  103. def test_delegation_to_index_get_method
  104. @params = ParameterSet.new
  105. assert_equal "bar", @params[:foo]
  106. end
  107. def test_delegation_to_index_set_method
  108. @params = ParameterSet.new
  109. @params[:foo] = "baz"
  110. assert_equal "baz", @params[:foo]
  111. end
  112. def test_delegation_down_hierarchy
  113. assert_equal "CHICAGO", @david.upcase
  114. end
  115. def test_delegation_to_instance_variable
  116. david = Name.new("David", "Hansson")
  117. assert_equal "DAVID HANSSON", david.upcase
  118. end
  119. def test_delegation_to_class_method
  120. assert_equal 'some_table', @david.table_name
  121. assert_equal 'some_table', @david.class_table_name
  122. end
  123. def test_missing_delegation_target
  124. assert_raise(ArgumentError) do
  125. Name.send :delegate, :nowhere
  126. end
  127. assert_raise(ArgumentError) do
  128. Name.send :delegate, :noplace, :tos => :hollywood
  129. end
  130. end
  131. def test_delegation_prefix
  132. invoice = Invoice.new(@david)
  133. assert_equal invoice.client_name, "David"
  134. assert_equal invoice.client_street, "Paulina"
  135. assert_equal invoice.client_city, "Chicago"
  136. end
  137. def test_delegation_custom_prefix
  138. invoice = Invoice.new(@david)
  139. assert_equal invoice.customer_name, "David"
  140. assert_equal invoice.customer_street, "Paulina"
  141. assert_equal invoice.customer_city, "Chicago"
  142. end
  143. def test_delegation_prefix_with_nil_or_false
  144. assert_equal Developer.new(@david).name, "David"
  145. assert_equal Tester.new(@david).name, "David"
  146. end
  147. def test_delegation_prefix_with_instance_variable
  148. assert_raise ArgumentError do
  149. Class.new do
  150. def initialize(client)
  151. @client = client
  152. end
  153. delegate :name, :address, :to => :@client, :prefix => true
  154. end
  155. end
  156. end
  157. def test_delegation_with_allow_nil
  158. rails = Project.new("Rails", Someone.new("David"))
  159. assert_equal rails.name, "David"
  160. end
  161. def test_delegation_with_allow_nil_and_nil_value
  162. rails = Project.new("Rails")
  163. assert_nil rails.name
  164. end
  165. # Ensures with check for nil, not for a falseish target.
  166. def test_delegation_with_allow_nil_and_false_value
  167. project = Project.new(false, false)
  168. assert_raise(NoMethodError) { project.name }
  169. end
  170. def test_delegation_with_allow_nil_and_invalid_value
  171. rails = Project.new("Rails", "David")
  172. assert_raise(NoMethodError) { rails.name }
  173. end
  174. def test_delegation_with_allow_nil_and_nil_value_and_prefix
  175. Project.class_eval do
  176. delegate :name, :to => :person, :allow_nil => true, :prefix => true
  177. end
  178. rails = Project.new("Rails")
  179. assert_nil rails.person_name
  180. end
  181. def test_delegation_without_allow_nil_and_nil_value
  182. david = Someone.new("David")
  183. assert_raise(Module::DelegationError) { david.street }
  184. end
  185. def test_delegation_to_method_that_exists_on_nil
  186. nil_person = Someone.new(nil)
  187. assert_equal 0.0, nil_person.to_f
  188. end
  189. def test_delegation_to_method_that_exists_on_nil_when_allowing_nil
  190. nil_project = Project.new(nil)
  191. assert_equal 0.0, nil_project.to_f
  192. end
  193. def test_delegation_does_not_raise_error_when_removing_singleton_instance_methods
  194. parent = Class.new do
  195. def self.parent_method; end
  196. end
  197. assert_nothing_raised do
  198. Class.new(parent) do
  199. class << self
  200. delegate :parent_method, :to => :superclass
  201. end
  202. end
  203. end
  204. end
  205. def test_delegation_line_number
  206. _, line = Someone.instance_method(:foo).source_location
  207. assert_equal Someone::FAILED_DELEGATE_LINE, line
  208. end
  209. def test_delegate_line_with_nil
  210. _, line = Someone.instance_method(:bar).source_location
  211. assert_equal Someone::FAILED_DELEGATE_LINE_2, line
  212. end
  213. def test_delegation_exception_backtrace
  214. someone = Someone.new("foo", "bar")
  215. someone.foo
  216. rescue NoMethodError => e
  217. file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE}"
  218. # We can't simply check the first line of the backtrace, because JRuby reports the call to __send__ in the backtrace.
  219. assert e.backtrace.any?{|a| a.include?(file_and_line)},
  220. "[#{e.backtrace.inspect}] did not include [#{file_and_line}]"
  221. end
  222. def test_delegation_exception_backtrace_with_allow_nil
  223. someone = Someone.new("foo", "bar")
  224. someone.bar
  225. rescue NoMethodError => e
  226. file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE_2}"
  227. # We can't simply check the first line of the backtrace, because JRuby reports the call to __send__ in the backtrace.
  228. assert e.backtrace.any?{|a| a.include?(file_and_line)},
  229. "[#{e.backtrace.inspect}] did not include [#{file_and_line}]"
  230. end
  231. def test_delegation_invokes_the_target_exactly_once
  232. se = SideEffect.new
  233. assert_equal 1, se.to_i
  234. assert_equal [2, 3], se.ints
  235. assert_equal '2', se.to_s
  236. assert_equal [3], se.ints
  237. end
  238. def test_delegation_doesnt_mask_nested_no_method_error_on_nil_receiver
  239. product = Product.new('Widget')
  240. # Nested NoMethodError is a different name from the delegation
  241. assert_raise(NoMethodError) { product.manufacturer_name }
  242. # Nested NoMethodError is the same name as the delegation
  243. assert_raise(NoMethodError) { product.type_name }
  244. end
  245. def test_parent
  246. assert_equal Yz::Zy, Yz::Zy::Cd.parent
  247. assert_equal Yz, Yz::Zy.parent
  248. assert_equal Object, Yz.parent
  249. end
  250. def test_parents
  251. assert_equal [Yz::Zy, Yz, Object], Yz::Zy::Cd.parents
  252. assert_equal [Yz, Object], Yz::Zy.parents
  253. end
  254. def test_local_constants
  255. assert_equal %w(Constant1 Constant3), Ab.local_constants.sort.map(&:to_s)
  256. end
  257. end
  258. module BarMethodAliaser
  259. def self.included(foo_class)
  260. foo_class.class_eval do
  261. include BarMethods
  262. alias_method_chain :bar, :baz
  263. end
  264. end
  265. end
  266. module BarMethods
  267. def bar_with_baz
  268. bar_without_baz << '_with_baz'
  269. end
  270. def quux_with_baz!
  271. quux_without_baz! << '_with_baz'
  272. end
  273. def quux_with_baz?
  274. false
  275. end
  276. def quux_with_baz=(v)
  277. send(:quux_without_baz=, v) << '_with_baz'
  278. end
  279. def duck_with_orange
  280. duck_without_orange << '_with_orange'
  281. end
  282. end
  283. class MethodAliasingTest < ActiveSupport::TestCase
  284. def setup
  285. Object.const_set :FooClassWithBarMethod, Class.new { def bar() 'bar' end }
  286. @instance = FooClassWithBarMethod.new
  287. end
  288. def teardown
  289. Object.instance_eval { remove_const :FooClassWithBarMethod }
  290. end
  291. def test_alias_method_chain
  292. assert @instance.respond_to?(:bar)
  293. feature_aliases = [:bar_with_baz, :bar_without_baz]
  294. feature_aliases.each do |method|
  295. assert !@instance.respond_to?(method)
  296. end
  297. assert_equal 'bar', @instance.bar
  298. FooClassWithBarMethod.class_eval { include BarMethodAliaser }
  299. feature_aliases.each do |method|
  300. assert_respond_to @instance, method
  301. end
  302. assert_equal 'bar_with_baz', @instance.bar
  303. assert_equal 'bar', @instance.bar_without_baz
  304. end
  305. def test_alias_method_chain_with_punctuation_method
  306. FooClassWithBarMethod.class_eval do
  307. def quux!; 'quux' end
  308. end
  309. assert !@instance.respond_to?(:quux_with_baz!)
  310. FooClassWithBarMethod.class_eval do
  311. include BarMethodAliaser
  312. alias_method_chain :quux!, :baz
  313. end
  314. assert_respond_to @instance, :quux_with_baz!
  315. assert_equal 'quux_with_baz', @instance.quux!
  316. assert_equal 'quux', @instance.quux_without_baz!
  317. end
  318. def test_alias_method_chain_with_same_names_between_predicates_and_bang_methods
  319. FooClassWithBarMethod.class_eval do
  320. def quux!; 'quux!' end
  321. def quux?; true end
  322. def quux=(v); 'quux=' end
  323. end
  324. assert !@instance.respond_to?(:quux_with_baz!)
  325. assert !@instance.respond_to?(:quux_with_baz?)
  326. assert !@instance.respond_to?(:quux_with_baz=)
  327. FooClassWithBarMethod.class_eval { include BarMethodAliaser }
  328. assert_respond_to @instance, :quux_with_baz!
  329. assert_respond_to @instance, :quux_with_baz?
  330. assert_respond_to @instance, :quux_with_baz=
  331. FooClassWithBarMethod.alias_method_chain :quux!, :baz
  332. assert_equal 'quux!_with_baz', @instance.quux!
  333. assert_equal 'quux!', @instance.quux_without_baz!
  334. FooClassWithBarMethod.alias_method_chain :quux?, :baz
  335. assert_equal false, @instance.quux?
  336. assert_equal true, @instance.quux_without_baz?
  337. FooClassWithBarMethod.alias_method_chain :quux=, :baz
  338. assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234)
  339. assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234)
  340. end
  341. def test_alias_method_chain_with_feature_punctuation
  342. FooClassWithBarMethod.class_eval do
  343. def quux; 'quux' end
  344. def quux?; 'quux?' end
  345. include BarMethodAliaser
  346. alias_method_chain :quux, :baz!
  347. end
  348. assert_nothing_raised do
  349. assert_equal 'quux_with_baz', @instance.quux_with_baz!
  350. end
  351. assert_raise(NameError) do
  352. FooClassWithBarMethod.alias_method_chain :quux?, :baz!
  353. end
  354. end
  355. def test_alias_method_chain_yields_target_and_punctuation
  356. args = nil
  357. FooClassWithBarMethod.class_eval do
  358. def quux?; end
  359. include BarMethods
  360. FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation|
  361. args = [target, punctuation]
  362. end
  363. end
  364. assert_not_nil args
  365. assert_equal 'quux', args[0]
  366. assert_equal '?', args[1]
  367. end
  368. def test_alias_method_chain_preserves_private_method_status
  369. FooClassWithBarMethod.class_eval do
  370. def duck; 'duck' end
  371. include BarMethodAliaser
  372. private :duck
  373. alias_method_chain :duck, :orange
  374. end
  375. assert_raise NoMethodError do
  376. @instance.duck
  377. end
  378. assert_equal 'duck_with_orange', @instance.instance_eval { duck }
  379. assert FooClassWithBarMethod.private_method_defined?(:duck)
  380. end
  381. def test_alias_method_chain_preserves_protected_method_status
  382. FooClassWithBarMethod.class_eval do
  383. def duck; 'duck' end
  384. include BarMethodAliaser
  385. protected :duck
  386. alias_method_chain :duck, :orange
  387. end
  388. assert_raise NoMethodError do
  389. @instance.duck
  390. end
  391. assert_equal 'duck_with_orange', @instance.instance_eval { duck }
  392. assert FooClassWithBarMethod.protected_method_defined?(:duck)
  393. end
  394. def test_alias_method_chain_preserves_public_method_status
  395. FooClassWithBarMethod.class_eval do
  396. def duck; 'duck' end
  397. include BarMethodAliaser
  398. public :duck
  399. alias_method_chain :duck, :orange
  400. end
  401. assert_equal 'duck_with_orange', @instance.duck
  402. assert FooClassWithBarMethod.public_method_defined?(:duck)
  403. end
  404. def test_delegate_with_case
  405. event = Event.new(Tester.new)
  406. assert_equal 1, event.foo
  407. end
  408. end