activeldap 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. data/CHANGES +34 -0
  2. data/README +13 -0
  3. data/Rakefile +2 -1
  4. data/TODO +6 -0
  5. data/benchmark/bench-al.rb +68 -17
  6. data/examples/al-admin/app/helpers/application_helper.rb +3 -5
  7. data/examples/al-admin/app/views/layouts/_footer.html.erb +2 -0
  8. data/examples/al-admin/config/boot.rb +7 -7
  9. data/examples/al-admin/config/environment.rb +27 -12
  10. data/examples/al-admin/config/environments/development.rb +0 -1
  11. data/examples/al-admin/config/environments/production.rb +6 -1
  12. data/examples/al-admin/config/environments/test.rb +1 -1
  13. data/examples/al-admin/config/initializers/gettext.rb +15 -1
  14. data/examples/al-admin/po/en/al-admin.po +1 -1
  15. data/examples/al-admin/po/ja/al-admin.po +1 -1
  16. data/examples/al-admin/po/nl/al-admin.po +1 -1
  17. data/examples/al-admin/public/dispatch.cgi +0 -0
  18. data/examples/al-admin/public/dispatch.fcgi +0 -0
  19. data/examples/al-admin/public/dispatch.rb +0 -0
  20. data/examples/al-admin/public/javascripts/controls.js +73 -73
  21. data/examples/al-admin/public/javascripts/dragdrop.js +166 -165
  22. data/examples/al-admin/public/javascripts/effects.js +174 -166
  23. data/examples/al-admin/public/javascripts/prototype.js +362 -267
  24. data/examples/al-admin/script/about +0 -0
  25. data/examples/al-admin/script/console +0 -0
  26. data/examples/al-admin/script/dbconsole +3 -0
  27. data/examples/al-admin/script/destroy +0 -0
  28. data/examples/al-admin/script/generate +0 -0
  29. data/examples/al-admin/script/performance/benchmarker +0 -0
  30. data/examples/al-admin/script/performance/profiler +0 -0
  31. data/examples/al-admin/script/performance/request +0 -0
  32. data/examples/al-admin/script/plugin +0 -0
  33. data/examples/al-admin/script/process/inspector +0 -0
  34. data/examples/al-admin/script/process/reaper +0 -0
  35. data/examples/al-admin/script/process/spawner +0 -0
  36. data/examples/al-admin/script/runner +0 -0
  37. data/examples/al-admin/script/server +0 -0
  38. data/examples/al-admin/test/run-test.sh +0 -0
  39. data/examples/groupadd +0 -0
  40. data/examples/groupdel +0 -0
  41. data/examples/groupls +0 -0
  42. data/examples/groupmod +0 -0
  43. data/examples/lpasswd +0 -0
  44. data/examples/ouadd +0 -0
  45. data/examples/useradd +0 -0
  46. data/examples/useradd-binary +0 -0
  47. data/examples/userdel +0 -0
  48. data/examples/userls +0 -0
  49. data/examples/usermod +0 -0
  50. data/examples/usermod-binary-add +0 -0
  51. data/examples/usermod-binary-add-time +0 -0
  52. data/examples/usermod-binary-del +0 -0
  53. data/examples/usermod-lang-add +0 -0
  54. data/lib/active_ldap.rb +10 -4
  55. data/lib/active_ldap/action_controller/ldap_benchmarking.rb +28 -9
  56. data/lib/active_ldap/adapter/base.rb +30 -17
  57. data/lib/active_ldap/adapter/jndi.rb +5 -1
  58. data/lib/active_ldap/adapter/ldap.rb +5 -1
  59. data/lib/active_ldap/association/has_many_utils.rb +7 -1
  60. data/lib/active_ldap/associations.rb +10 -5
  61. data/lib/active_ldap/attributes.rb +6 -1
  62. data/lib/active_ldap/base.rb +154 -52
  63. data/lib/active_ldap/configuration.rb +1 -1
  64. data/lib/active_ldap/connection.rb +7 -4
  65. data/lib/active_ldap/get_text.rb +11 -3
  66. data/lib/active_ldap/ldif.rb +16 -4
  67. data/lib/active_ldap/operations.rb +13 -5
  68. data/lib/active_ldap/schema.rb +6 -2
  69. data/lib/active_ldap/schema/syntaxes.rb +15 -3
  70. data/lib/active_ldap/user_password.rb +4 -4
  71. data/lib/active_ldap/validations.rb +32 -44
  72. data/lib/active_ldap/xml.rb +125 -0
  73. data/po/en/active-ldap.po +740 -85
  74. data/po/ja/active-ldap.po +748 -547
  75. data/rails/README +54 -0
  76. data/rails/init.rb +33 -0
  77. data/rails/plugin/active_ldap/generators/README +2 -0
  78. data/rails/plugin/active_ldap/generators/model_active_ldap/model_active_ldap_generator.rb +1 -1
  79. data/rails/plugin/active_ldap/init.rb +3 -0
  80. data/rails_generators/model_active_ldap/USAGE +17 -0
  81. data/rails_generators/model_active_ldap/model_active_ldap_generator.rb +69 -0
  82. data/rails_generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
  83. data/rails_generators/model_active_ldap/templates/unit_test.rb +8 -0
  84. data/rails_generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
  85. data/rails_generators/scaffold_active_ldap/templates/ldap.yml +18 -0
  86. data/rails_generators/scaffold_al/scaffold_al_generator.rb +20 -0
  87. data/test-unit/History.txt +50 -1
  88. data/test-unit/Manifest.txt +22 -12
  89. data/test-unit/README.txt +31 -12
  90. data/test-unit/Rakefile +14 -1
  91. data/test-unit/TODO +5 -0
  92. data/test-unit/bin/testrb +0 -0
  93. data/test-unit/lib/test/unit.rb +62 -0
  94. data/test-unit/lib/test/unit/assertions.rb +419 -75
  95. data/test-unit/lib/test/unit/autorunner.rb +70 -13
  96. data/test-unit/lib/test/unit/collector.rb +1 -1
  97. data/test-unit/lib/test/unit/collector/load.rb +1 -1
  98. data/test-unit/lib/test/unit/color-scheme.rb +86 -0
  99. data/test-unit/lib/test/unit/color.rb +40 -5
  100. data/test-unit/lib/test/unit/diff.rb +14 -0
  101. data/test-unit/lib/test/unit/fixture.rb +7 -16
  102. data/test-unit/lib/test/unit/notification.rb +9 -0
  103. data/test-unit/lib/test/unit/omission.rb +14 -0
  104. data/test-unit/lib/test/unit/pending.rb +16 -0
  105. data/test-unit/lib/test/unit/priority.rb +17 -2
  106. data/test-unit/lib/test/unit/runner/console.rb +8 -2
  107. data/test-unit/lib/test/unit/testcase.rb +188 -2
  108. data/test-unit/lib/test/unit/ui/console/testrunner.rb +51 -26
  109. data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
  110. data/test-unit/lib/test/unit/version.rb +1 -1
  111. data/test-unit/sample/test_user.rb +22 -0
  112. data/test-unit/test/collector/{test_descendant.rb → test-descendant.rb} +0 -0
  113. data/test-unit/test/collector/{test_load.rb → test-load.rb} +1 -1
  114. data/test-unit/test/run-test.rb +0 -0
  115. data/test-unit/test/{test_attribute.rb → test-attribute.rb} +0 -0
  116. data/test-unit/test/test-color-scheme.rb +56 -0
  117. data/test-unit/test/{test_color.rb → test-color.rb} +10 -0
  118. data/test-unit/test/{test_diff.rb → test-diff.rb} +0 -0
  119. data/test-unit/test/{test_emacs_runner.rb → test-emacs-runner.rb} +0 -0
  120. data/test-unit/test/test-fixture.rb +287 -0
  121. data/test-unit/test/{test_notification.rb → test-notification.rb} +4 -4
  122. data/test-unit/test/{test_omission.rb → test-omission.rb} +6 -6
  123. data/test-unit/test/{test_pending.rb → test-pending.rb} +12 -6
  124. data/test-unit/test/{test_priority.rb → test-priority.rb} +30 -0
  125. data/test-unit/test/test_assertions.rb +411 -69
  126. data/test-unit/test/test_testcase.rb +70 -3
  127. data/test-unit/test/{testunit_test_util.rb → testunit-test-util.rb} +4 -2
  128. data/test-unit/test/ui/test_testrunmediator.rb +1 -1
  129. data/test-unit/test/util/test-method-owner-finder.rb +38 -0
  130. data/test/run-test.rb +0 -0
  131. data/test/test_adapter.rb +3 -0
  132. data/test/test_associations.rb +50 -7
  133. data/test/test_base.rb +193 -11
  134. data/test/test_connection_per_dn.rb +1 -1
  135. data/test/test_ldif.rb +86 -0
  136. data/test/test_load.rb +7 -0
  137. data/test/test_schema.rb +31 -1
  138. data/test/test_syntax.rb +20 -0
  139. data/test/test_user_password.rb +22 -14
  140. data/test/test_validation.rb +70 -29
  141. metadata +99 -77
  142. data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
  143. data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
  144. data/examples/al-admin/config/initializers/ralative_url_support.rb +0 -1
  145. data/examples/al-admin/lib/accept_http_rails_relative_url_root.rb +0 -9
  146. data/test-unit-ext/misc/rd2html.rb +0 -42
  147. data/test-unit/test/test_fixture.rb +0 -275
@@ -4,7 +4,9 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  require './lib/test/unit/version.rb'
6
6
 
7
- Hoe.new('test-unit', Test::Unit::VERSION) do |p|
7
+ version = Test::Unit::VERSION
8
+ ENV["VERSION"] = version
9
+ Hoe.new('test-unit', version) do |p|
8
10
  p.developer('Kouhei Sutou', 'kou@cozmixng.org')
9
11
  p.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
10
12
 
@@ -13,10 +15,21 @@ Hoe.new('test-unit', Test::Unit::VERSION) do |p|
13
15
  end
14
16
 
15
17
  task :check_manifest => :clean_test_result
18
+ task :check_manifest => :clean_coverage
16
19
 
17
20
  task :clean_test_result do
18
21
  test_results = Dir.glob("**/.test-result")
19
22
  sh("rm", "-rf", *test_results) unless test_results.empty?
20
23
  end
21
24
 
25
+ task :clean_coverage do
26
+ sh("rm", "-rf", "coverage")
27
+ end
28
+
29
+ task :tag do
30
+ message = "Released Test::Unit #{version}!"
31
+ base = "svn+ssh://#{ENV['USER']}@rubyforge.org/var/svn/test-unit/"
32
+ sh 'svn', 'copy', '-m', message, "#{base}trunk", "#{base}tags/#{version}"
33
+ end
34
+
22
35
  # vim: syntax=Ruby
@@ -0,0 +1,5 @@
1
+ * mock.
2
+ * data-driven test.
3
+ * port ruby trunk's assert_equal's intelligent inspection
4
+ when inspected expected and actual are same content
5
+ string.
File without changes
@@ -253,6 +253,68 @@ module Test # :nodoc:
253
253
  # the dynamic suite using the console TestRunner.
254
254
  #
255
255
  #
256
+ # == Configuration file
257
+ #
258
+ # Test::Unit reads 'test-unit.yml' in the current working
259
+ # directory as Test::Unit's configuration file. It can
260
+ # contain the following configurations:
261
+ #
262
+ # * color scheme definitions
263
+ # * test runner to be used
264
+ # * test runner options
265
+ # * test collector to be used
266
+ #
267
+ # Except color scheme definitions, all of them are
268
+ # specified by command line option.
269
+ #
270
+ # Here are sample color scheme definitions:
271
+ #
272
+ # color_schemes:
273
+ # inverted:
274
+ # success:
275
+ # name: red
276
+ # bold: true
277
+ # failure:
278
+ # name: green
279
+ # bold: true
280
+ # other_scheme:
281
+ # ...
282
+ #
283
+ # Here are the syntax of color scheme definitions:
284
+ #
285
+ # color_schemes:
286
+ # SCHEME_NAME:
287
+ # EVENT_NAME:
288
+ # name: COLOR_NAME
289
+ # intensity: BOOLEAN
290
+ # bold: BOOLEAN
291
+ # italic: BOOLEAN
292
+ # underline: BOOLEAN
293
+ # ...
294
+ # ...
295
+ #
296
+ # SCHEME_NAME:: the name of the color scheme
297
+ # EVENT_NAME:: one of [success, failure, pending,
298
+ # omission, notification, error]
299
+ # COLOR_NAME:: one of [black, red, green, yellow, blue,
300
+ # magenta, cyan, white]
301
+ # BOOLEAN:: true or false
302
+ #
303
+ # You can use the above 'inverted' color scheme with the
304
+ # following configuration:
305
+ #
306
+ # runner: console
307
+ # console_options:
308
+ # color_scheme: inverted
309
+ # color_schemes:
310
+ # inverted:
311
+ # success:
312
+ # name: red
313
+ # bold: true
314
+ # failure:
315
+ # name: green
316
+ # bold: true
317
+ #
256
318
  # == Questions?
257
319
  #
258
320
  # I'd really like to get feedback from all levels of Ruby
@@ -1,9 +1,11 @@
1
1
  # Author:: Nathaniel Talbott.
2
2
  # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
3
+ # Copyright (c) 2009 Kouhei Sutou.
3
4
  # License:: Ruby license.
4
5
 
5
6
  require 'test/unit/assertionfailederror'
6
7
  require 'test/unit/util/backtracefilter'
8
+ require 'test/unit/util/method-owner-finder'
7
9
  require 'test/unit/diff'
8
10
 
9
11
  module Test
@@ -77,21 +79,7 @@ module Test
77
79
 
78
80
  public
79
81
  def assert_equal(expected, actual, message=nil)
80
- diff = AssertionMessage.delayed_literal do
81
- if !expected.is_a?(String) or !actual.is_a?(String)
82
- expected = AssertionMessage.convert(expected)
83
- actual = AssertionMessage.convert(actual)
84
- end
85
- diff = Diff.readable(expected, actual)
86
- if /^[-+]/ !~ diff
87
- diff = ""
88
- elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff
89
- diff = "\n\ndiff:\n#{diff}"
90
- else
91
- diff = ""
92
- end
93
- diff
94
- end
82
+ diff = AssertionMessage.delayed_diff(expected, actual)
95
83
  full_message = build_message(message, <<EOT, expected, actual, diff)
96
84
  <?> expected but was
97
85
  <?>.?
@@ -99,53 +87,36 @@ EOT
99
87
  assert_block(full_message) { expected == actual }
100
88
  end
101
89
 
102
- private
103
- def _check_exception_class(args) # :nodoc:
104
- args.partition do |klass|
105
- next if klass.instance_of?(Module)
106
- assert(Exception >= klass, "Should expect a class of exception, #{klass}")
107
- true
108
- end
109
- end
110
-
111
- private
112
- def _expected_exception?(actual_exception, exceptions, modules) # :nodoc:
113
- exceptions.include?(actual_exception.class) or
114
- modules.any? {|mod| actual_exception.is_a?(mod)}
115
- end
116
-
117
90
  ##
118
- # Passes if the block raises one of the given exceptions.
91
+ # Passes if the block raises one of the expected
92
+ # exceptions. When an expected exception is an Exception
93
+ # object, passes if expected_exception == actual_exception.
119
94
  #
120
95
  # Example:
121
- # assert_raise RuntimeError, LoadError do
96
+ # assert_raise(RuntimeError, LoadError) do
122
97
  # raise 'Boom!!!'
123
- # end
124
-
98
+ # end # -> pass
99
+ #
100
+ # assert_raise do
101
+ # raise Exception, 'Any exception should be raised!!!'
102
+ # end # -> pass
103
+ #
104
+ # assert_raise(RuntimeError.new("XXX")) {raise "XXX"} # -> pass
105
+ # assert_raise(MyError.new("XXX")) {raise "XXX"} # -> fail
106
+ # assert_raise(RuntimeError.new("ZZZ")) {raise "XXX"} # -> fail
125
107
  public
126
- def assert_raise(*args)
127
- _wrap_assertion do
128
- if Module === args.last
129
- message = ""
130
- else
131
- message = args.pop
132
- end
133
- exceptions, modules = _check_exception_class(args)
134
- expected = args.size == 1 ? args.first : args
135
- actual_exception = nil
136
- full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
108
+ def assert_raise(*args, &block)
109
+ assert_expected_exception = Proc.new do |*_args|
110
+ message, assert_exception_helper, actual_exception = _args
111
+ expected = assert_exception_helper.expected_exceptions
112
+ full_message = build_message(message,
113
+ "<?> exception expected but was\n?",
114
+ expected, actual_exception)
137
115
  assert_block(full_message) do
138
- begin
139
- yield
140
- rescue Exception => actual_exception
141
- break
142
- end
143
- false
116
+ expected == [] or assert_exception_helper.expected?(actual_exception)
144
117
  end
145
- full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
146
- assert_block(full_message) {_expected_exception?(actual_exception, exceptions, modules)}
147
- actual_exception
148
118
  end
119
+ _assert_raise(assert_expected_exception, *args, &block)
149
120
  end
150
121
 
151
122
  ##
@@ -158,6 +129,30 @@ EOT
158
129
  assert_raise(*args, &block)
159
130
  end
160
131
 
132
+ ##
133
+ # Passes if the block raises one of the given
134
+ # exceptions or sub exceptions of the given exceptions.
135
+ #
136
+ # Example:
137
+ # assert_raise_kind_of(SystemCallError) do
138
+ # raise Errno::EACCES
139
+ # end
140
+ def assert_raise_kind_of(*args, &block)
141
+ assert_expected_exception = Proc.new do |*_args|
142
+ message, assert_exception_helper, actual_exception = _args
143
+ expected = assert_exception_helper.expected_exceptions
144
+ full_message = build_message(message,
145
+ "<?> family exception expected " +
146
+ "but was\n?",
147
+ expected, actual_exception)
148
+ assert_block(full_message) do
149
+ assert_exception_helper.expected?(actual_exception, :kind_of?)
150
+ end
151
+ end
152
+ _assert_raise(assert_expected_exception, *args, &block)
153
+ end
154
+
155
+
161
156
  ##
162
157
  # Passes if +object+ .instance_of? +klass+
163
158
  #
@@ -215,17 +210,18 @@ EOT
215
210
  public
216
211
  def assert_respond_to(object, method, message="")
217
212
  _wrap_assertion do
218
- full_message = build_message(nil, "<?>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to\\?(:to_str).", method)
219
-
213
+ full_message = build_message(message,
214
+ "<?>.kind_of\\?(Symbol) or\n" +
215
+ "<?>.respond_to\\?(:to_str) expected",
216
+ method, method)
220
217
  assert_block(full_message) do
221
- method.kind_of?(Symbol) || method.respond_to?(:to_str)
218
+ method.kind_of?(Symbol) or method.respond_to?(:to_str)
222
219
  end
223
- full_message = build_message(message, <<EOT, object, object.class, method)
224
- <?>
225
- of type <?>
226
- expected to respond_to\\?<?>.
227
- EOT
228
- assert_block(full_message) { object.respond_to?(method) }
220
+ full_message = build_message(message,
221
+ "<?>.respond_to\\?(?) expected\n" +
222
+ "(Class: <?>)",
223
+ object, method, object.class)
224
+ assert_block(full_message) {object.respond_to?(method)}
229
225
  end
230
226
  end
231
227
 
@@ -301,18 +297,20 @@ EOT
301
297
  public
302
298
  def assert_nothing_raised(*args)
303
299
  _wrap_assertion do
304
- if Module === args.last
305
- message = ""
306
- else
300
+ if args.last.is_a?(String)
307
301
  message = args.pop
302
+ else
303
+ message = ""
308
304
  end
309
- exceptions, modules = _check_exception_class(args)
305
+
306
+ assert_exception_helper = AssertExceptionHelper.new(self, args)
310
307
  begin
311
308
  yield
312
309
  rescue Exception => e
313
310
  if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
314
- _expected_exception?(e, exceptions, modules))
315
- assert_block(build_message(message, "Exception raised:\n?", e)){false}
311
+ assert_exception_helper.expected?(e))
312
+ failure_message = build_message(message, "Exception raised:\n?", e)
313
+ assert_block(failure_message) {false}
316
314
  else
317
315
  raise
318
316
  end
@@ -398,12 +396,12 @@ EOT
398
396
  # Passes if the block throws +expected_object+
399
397
  #
400
398
  # Example:
401
- # assert_throws :done do
402
- # throw :done
399
+ # assert_throw(:done) do
400
+ # throw(:done)
403
401
  # end
404
402
 
405
403
  public
406
- def assert_throws(expected_object, message="", &proc)
404
+ def assert_throw(expected_object, message="", &proc)
407
405
  _wrap_assertion do
408
406
  begin
409
407
  catch([]) {}
@@ -411,7 +409,7 @@ EOT
411
409
  assert_instance_of(Symbol, expected_object,
412
410
  "assert_throws expects the symbol that should be thrown for its first argument")
413
411
  end
414
- assert_block("Should have passed a block to assert_throws.") do
412
+ assert_block("Should have passed a block to assert_throw.") do
415
413
  block_given?
416
414
  end
417
415
  caught = true
@@ -437,6 +435,14 @@ EOT
437
435
  end
438
436
  end
439
437
 
438
+ ##
439
+ # Alias of assert_throw.
440
+ #
441
+ # Will be deprecated in 1.9, and removed in 2.0.
442
+ def assert_throws(*args, &block)
443
+ assert_throw(*args, &block)
444
+ end
445
+
440
446
  ##
441
447
  # Passes if block does not throw anything.
442
448
  #
@@ -559,6 +565,180 @@ EOT
559
565
  end
560
566
  end
561
567
 
568
+ ##
569
+ # Passes if expression "+expected+ +operator+
570
+ # +actual+" is true.
571
+ #
572
+ # Example:
573
+ # assert_compare(1, "<", 10) # -> pass
574
+ # assert_compare(1, ">=", 10) # -> fail
575
+ def assert_compare(expected, operator, actual, message=nil)
576
+ _wrap_assertion do
577
+ assert_send([["<", "<=", ">", ">="], :include?, operator.to_s])
578
+ case operator.to_s
579
+ when "<"
580
+ operator_description = "less than"
581
+ when "<="
582
+ operator_description = "less than or equal to"
583
+ when ">"
584
+ operator_description = "greater than"
585
+ when ">="
586
+ operator_description = "greater than or equal to"
587
+ end
588
+ template = <<-EOT
589
+ <?> #{operator} <?> should be true
590
+ <?> expected #{operator_description}
591
+ <?>.
592
+ EOT
593
+ full_message = build_message(message, template,
594
+ expected, actual,
595
+ expected, actual)
596
+ assert_block(full_message) do
597
+ expected.send(operator, actual)
598
+ end
599
+ end
600
+ end
601
+
602
+ ##
603
+ # Passes if assertion is failed in block.
604
+ #
605
+ # Example:
606
+ # assert_fail_assertion {assert_equal("A", "B")} # -> pass
607
+ # assert_fail_assertion {assert_equal("A", "A")} # -> fail
608
+ def assert_fail_assertion(message=nil)
609
+ _wrap_assertion do
610
+ full_message = build_message(message,
611
+ "Failed assertion was expected.")
612
+ assert_block(full_message) do
613
+ begin
614
+ yield
615
+ false
616
+ rescue AssertionFailedError
617
+ true
618
+ end
619
+ end
620
+ end
621
+ end
622
+
623
+ ##
624
+ # Passes if an exception is raised in block and its
625
+ # message is +expected+.
626
+ #
627
+ # Example:
628
+ # assert_raise_message("exception") {raise "exception"} # -> pass
629
+ # assert_raise_message(/exc/i) {raise "exception"} # -> pass
630
+ # assert_raise_message("exception") {raise "EXCEPTION"} # -> fail
631
+ # assert_raise_message("exception") {} # -> fail
632
+ def assert_raise_message(expected, message=nil)
633
+ _wrap_assertion do
634
+ full_message = build_message(message,
635
+ "<?> exception message expected " +
636
+ "but none was thrown.",
637
+ expected)
638
+ exception = nil
639
+ assert_block(full_message) do
640
+ begin
641
+ yield
642
+ false
643
+ rescue Exception => exception
644
+ true
645
+ end
646
+ end
647
+
648
+ actual = exception.message
649
+ diff = AssertionMessage.delayed_diff(expected, actual)
650
+ full_message =
651
+ build_message(message,
652
+ "<?> exception message expected but was\n" +
653
+ "<?>.?", expected, actual, diff)
654
+ assert_block(full_message) do
655
+ if expected.is_a?(Regexp)
656
+ expected =~ actual
657
+ else
658
+ expected == actual
659
+ end
660
+ end
661
+ end
662
+ end
663
+
664
+ ##
665
+ # Passes if +object+.const_defined?(+constant_name+)
666
+ #
667
+ # Example:
668
+ # assert_const_defined(Test, :Unit) # -> pass
669
+ # assert_const_defined(Object, :Nonexistent) # -> fail
670
+ def assert_const_defined(object, constant_name, message=nil)
671
+ _wrap_assertion do
672
+ full_message = build_message(message,
673
+ "<?>.const_defined\\?(<?>) expected.",
674
+ object, constant_name)
675
+ assert_block(full_message) do
676
+ object.const_defined?(constant_name)
677
+ end
678
+ end
679
+ end
680
+
681
+ ##
682
+ # Passes if !+object+.const_defined?(+constant_name+)
683
+ #
684
+ # Example:
685
+ # assert_not_const_defined(Object, :Nonexistent) # -> pass
686
+ # assert_not_const_defined(Test, :Unit) # -> fail
687
+ def assert_not_const_defined(object, constant_name, message=nil)
688
+ _wrap_assertion do
689
+ full_message = build_message(message,
690
+ "!<?>.const_defined\\?(<?>) expected.",
691
+ object, constant_name)
692
+ assert_block(full_message) do
693
+ !object.const_defined?(constant_name)
694
+ end
695
+ end
696
+ end
697
+
698
+ ##
699
+ # Passes if +object+.+predicate+
700
+ #
701
+ # Example:
702
+ # assert_predicate([], :empty?) # -> pass
703
+ # assert_predicate([1], :empty?) # -> fail
704
+ def assert_predicate(object, predicate, message=nil)
705
+ _wrap_assertion do
706
+ assert_respond_to(object, predicate, message)
707
+ actual = object.send(predicate)
708
+ full_message = build_message(message,
709
+ "<?>.? is true value expected but was\n" +
710
+ "<?>",
711
+ object,
712
+ AssertionMessage.literal(predicate),
713
+ actual)
714
+ assert_block(full_message) do
715
+ actual
716
+ end
717
+ end
718
+ end
719
+
720
+ ##
721
+ # Passes if +object+.+predicate+
722
+ #
723
+ # Example:
724
+ # assert_not_predicate([1], :empty?) # -> pass
725
+ # assert_not_predicate([], :empty?) # -> fail
726
+ def assert_not_predicate(object, predicate, message=nil)
727
+ _wrap_assertion do
728
+ assert_respond_to(object, predicate, message)
729
+ actual = object.send(predicate)
730
+ full_message = build_message(message,
731
+ "<?>.? is false value expected but was\n" +
732
+ "<?>",
733
+ object,
734
+ AssertionMessage.literal(predicate),
735
+ actual)
736
+ assert_block(full_message) do
737
+ not actual
738
+ end
739
+ end
740
+ end
741
+
562
742
  ##
563
743
  # Builds a failure message. +head+ is added before the +template+ and
564
744
  # +arguments+ replaces the '?'s positionally in the template.
@@ -601,8 +781,37 @@ EOT
601
781
  def self.use_pp=(value)
602
782
  AssertionMessage.use_pp = value
603
783
  end
604
-
784
+
605
785
  # :stopdoc:
786
+ private
787
+ def _assert_raise(assert_expected_exception, *args, &block)
788
+ _wrap_assertion do
789
+ if args.last.is_a?(String)
790
+ message = args.pop
791
+ else
792
+ message = ""
793
+ end
794
+
795
+ assert_exception_helper = AssertExceptionHelper.new(self, args)
796
+ expected = assert_exception_helper.expected_exceptions
797
+ actual_exception = nil
798
+ full_message = build_message(message,
799
+ "<?> exception expected " +
800
+ "but none was thrown.",
801
+ expected)
802
+ assert_block(full_message) do
803
+ begin
804
+ yield
805
+ false
806
+ rescue Exception => actual_exception
807
+ true
808
+ end
809
+ end
810
+ assert_expected_exception.call(message, assert_exception_helper,
811
+ actual_exception)
812
+ actual_exception
813
+ end
814
+ end
606
815
 
607
816
  class AssertionMessage
608
817
  @use_pp = true
@@ -617,6 +826,31 @@ EOT
617
826
  DelayedLiteral.new(block)
618
827
  end
619
828
 
829
+ def delayed_diff(from, to)
830
+ delayed_literal do
831
+ if !from.is_a?(String) or !to.is_a?(String)
832
+ from = convert(from)
833
+ to = convert(to)
834
+ end
835
+
836
+ diff = Diff.readable(from, to)
837
+ if /^[-+]/ !~ diff
838
+ diff = ""
839
+ elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff
840
+ diff = "\n\ndiff:\n#{diff}"
841
+ else
842
+ diff = ""
843
+ end
844
+
845
+ if Diff.need_fold?(diff)
846
+ folded_diff = Diff.folded_readable(from, to)
847
+ diff << "\n\nfolded diff:\n#{folded_diff}"
848
+ end
849
+
850
+ diff
851
+ end
852
+ end
853
+
620
854
  def convert(object)
621
855
  case object
622
856
  when Exception
@@ -715,8 +949,118 @@ EOM
715
949
  end
716
950
  end
717
951
 
718
- # :startdoc:
952
+ class AssertExceptionHelper
953
+ class WrappedException
954
+ def initialize(exception)
955
+ @exception = exception
956
+ end
957
+
958
+ def inspect
959
+ if default_inspect?
960
+ "#{@exception.class.inspect}(#{@exception.message.inspect})"
961
+ else
962
+ @exception.inspect
963
+ end
964
+ end
965
+
966
+ def method_missing(name, *args, &block)
967
+ @exception.send(name, *args, &block)
968
+ end
969
+
970
+ private
971
+ def default_inspect?
972
+ inspect_method = @exception.method(:inspect)
973
+ if inspect_method.respond_to?(:owner) and
974
+ inspect_method.owner == Exception
975
+ true
976
+ else
977
+ default_inspect_method = Exception.instance_method(:inspect)
978
+ default_inspect_method.bind(@exception).call == @exception.inspect
979
+ end
980
+ end
981
+ end
982
+
983
+ def initialize(test_case, expected_exceptions)
984
+ @test_case = test_case
985
+ @expected_exceptions = expected_exceptions
986
+ @expected_classes, @expected_modules, @expected_objects =
987
+ split_expected_exceptions(expected_exceptions)
988
+ end
989
+
990
+ def expected_exceptions
991
+ exceptions = @expected_exceptions.collect do |exception|
992
+ if exception.is_a?(Exception)
993
+ WrappedException.new(exception)
994
+ else
995
+ exception
996
+ end
997
+ end
998
+ if exceptions.size == 1
999
+ exceptions[0]
1000
+ else
1001
+ exceptions
1002
+ end
1003
+ end
1004
+
1005
+ def expected?(actual_exception, equality=nil)
1006
+ equality ||= :instance_of?
1007
+ expected_class?(actual_exception, equality) or
1008
+ expected_module?(actual_exception) or
1009
+ expected_object?(actual_exception)
1010
+ end
719
1011
 
1012
+ private
1013
+ def split_expected_exceptions(expected_exceptions)
1014
+ exception_modules = []
1015
+ exception_objects = []
1016
+ exception_classes = []
1017
+ expected_exceptions.each do |exception_type|
1018
+ if exception_type.instance_of?(Module)
1019
+ exception_modules << exception_type
1020
+ elsif exception_type.is_a?(Exception)
1021
+ exception_objects << exception_type
1022
+ else
1023
+ @test_case.send(:assert,
1024
+ Exception >= exception_type,
1025
+ "Should expect a class of exception, " +
1026
+ "#{exception_type}")
1027
+ exception_classes << exception_type
1028
+ end
1029
+ end
1030
+ [exception_classes, exception_modules, exception_objects]
1031
+ end
1032
+
1033
+ def expected_class?(actual_exception, equality)
1034
+ @expected_classes.any? do |expected_class|
1035
+ actual_exception.send(equality, expected_class)
1036
+ end
1037
+ end
1038
+
1039
+ def expected_module?(actual_exception)
1040
+ @expected_modules.any? do |expected_module|
1041
+ actual_exception.is_a?(expected_module)
1042
+ end
1043
+ end
1044
+
1045
+ def expected_object?(actual_exception)
1046
+ @expected_objects.any? do |expected_object|
1047
+ expected_object == actual_exception or
1048
+ fallback_exception_object_equal(expected_object, actual_exception)
1049
+ end
1050
+ end
1051
+
1052
+ def fallback_exception_object_equal(expected_object, actual_exception)
1053
+ owner = Util::MethodOwnerFinder.find(expected_object, :==)
1054
+ if owner == Kernel or owner == Exception
1055
+ expected_object.class == actual_exception.class and
1056
+ expected_object.message == actual_exception.message
1057
+ else
1058
+ false
1059
+ end
1060
+ end
1061
+ end
1062
+
1063
+ # :startdoc:
720
1064
  end
721
1065
  end
722
1066
  end