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
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+ require 'test/unit/color-scheme'
2
3
  require 'optparse'
3
4
 
4
5
  module Test
@@ -11,10 +12,24 @@ module Test
11
12
  class << self
12
13
  def register_runner(id, runner_builder=Proc.new)
13
14
  RUNNERS[id] = runner_builder
15
+ RUNNERS[id.to_s] = runner_builder
16
+ end
17
+
18
+ def runner(id)
19
+ RUNNERS[id.to_s]
14
20
  end
15
21
 
16
22
  def register_collector(id, collector_builder=Proc.new)
17
23
  COLLECTORS[id] = collector_builder
24
+ COLLECTORS[id.to_s] = collector_builder
25
+ end
26
+
27
+ def collector(id)
28
+ COLLECTORS[id.to_s]
29
+ end
30
+
31
+ def register_color_scheme(id, scheme)
32
+ ColorScheme[id] = scheme
18
33
  end
19
34
 
20
35
  def setup_option(option_builder=Proc.new)
@@ -76,6 +91,7 @@ module Test
76
91
 
77
92
  attr_reader :suite, :runner_options
78
93
  attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
94
+ attr_accessor :color_scheme
79
95
  attr_writer :runner, :collector
80
96
 
81
97
  def initialize(standalone)
@@ -85,8 +101,11 @@ module Test
85
101
  @collector = default_collector
86
102
  @filters = []
87
103
  @to_run = []
104
+ @color_scheme = ColorScheme.default
88
105
  @runner_options = {}
89
106
  @workdir = nil
107
+ default_config_file = "test-unit.yml"
108
+ load_config(default_config_file) if File.exist?(default_config_file)
90
109
  yield(self) if block_given?
91
110
  end
92
111
 
@@ -96,8 +115,7 @@ module Test
96
115
  rescue OptionParser::ParseError => e
97
116
  puts e
98
117
  puts options
99
- $! = nil
100
- abort
118
+ exit(false)
101
119
  else
102
120
  @filters << proc{false} unless(@filters.empty?)
103
121
  end
@@ -116,7 +134,7 @@ module Test
116
134
  @runner = r
117
135
  end
118
136
 
119
- if(@standalone)
137
+ if (@standalone)
120
138
  o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
121
139
  @base = b
122
140
  end
@@ -169,13 +187,19 @@ module Test
169
187
  end
170
188
 
171
189
  priority_filter = Proc.new do |test|
172
- Priority::Checker.new(test).need_to_run? or nil
190
+ if @filters.size > 2
191
+ nil
192
+ else
193
+ Priority::Checker.new(test).need_to_run? or nil
194
+ end
173
195
  end
174
196
  o.on("--[no-]priority-mode",
175
197
  "Runs some tests based on their priority.") do |priority_mode|
176
198
  if priority_mode
199
+ Priority.enable
177
200
  @filters |= [priority_filter]
178
201
  else
202
+ Priority.disable
179
203
  @filters -= [priority_filter]
180
204
  end
181
205
  end
@@ -185,6 +209,18 @@ module Test
185
209
  $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
186
210
  end
187
211
 
212
+ color_schemes = ColorScheme.all
213
+ o.on("--color-scheme=SCHEME", color_schemes,
214
+ "Use SCHEME as color scheme.",
215
+ "(#{keyword_display(color_schemes)})") do |scheme|
216
+ @color_scheme = scheme
217
+ end
218
+
219
+ o.on("--config=FILE",
220
+ "Use YAML fomat FILE content as configuration file.") do |file|
221
+ load_config(file)
222
+ end
223
+
188
224
  ADDITIONAL_OPTIONS.each do |option_builder|
189
225
  option_builder.call(self, o)
190
226
  end
@@ -201,13 +237,13 @@ module Test
201
237
 
202
238
  o.on_tail('--console', 'Console runner (use --runner).') do
203
239
  warn("Deprecated option (--console).")
204
- @runner = RUNNERS[:console]
240
+ @runner = self.class.runner(:console)
205
241
  end
206
242
 
207
243
  if RUNNERS[:fox]
208
244
  o.on_tail('--fox', 'Fox runner (use --runner).') do
209
245
  warn("Deprecated option (--fox).")
210
- @runner = RUNNERS[:fox]
246
+ @runner = self.class.runner(:fox)
211
247
  end
212
248
  end
213
249
 
@@ -215,10 +251,12 @@ module Test
215
251
  end
216
252
  end
217
253
 
218
- def keyword_display(array)
219
- list = array.collect {|e, *| e.to_s}
220
- Array === array or list.sort!
221
- list.collect {|e| e.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')}.join(", ")
254
+ def keyword_display(keywords)
255
+ keywords.collect do |keyword, _|
256
+ keyword.to_s
257
+ end.uniq.sort.collect do |keyword|
258
+ keyword.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')
259
+ end.join(", ")
222
260
  end
223
261
 
224
262
  def run
@@ -226,21 +264,40 @@ module Test
226
264
  return false if suite.nil?
227
265
  runner = @runner[self]
228
266
  return false if runner.nil?
267
+ @runner_options[:color_scheme] ||= @color_scheme
229
268
  Dir.chdir(@workdir) if @workdir
230
269
  runner.run(suite, @runner_options).passed?
231
270
  end
232
271
 
272
+ def load_config(file)
273
+ require 'yaml'
274
+ config = YAML.load(File.read(file))
275
+ runner_name = config["runner"]
276
+ @runner = self.class.runner(runner_name) || @runner
277
+ @collector = self.class.collector(config["collector"]) || @collector
278
+ (config["color_schemes"] || {}).each do |name, options|
279
+ ColorScheme[name] = options
280
+ end
281
+ runner_options = {}
282
+ (config["#{runner_name}_options"] || {}).each do |key, value|
283
+ key = key.to_sym
284
+ value = ColorScheme[value] if key == :color_scheme
285
+ runner_options[key.to_sym] = value
286
+ end
287
+ @runner_options = @runner_options.merge(runner_options)
288
+ end
289
+
233
290
  private
234
291
  def default_runner
235
292
  if ENV["EMACS"] == "t"
236
- RUNNERS[:emacs]
293
+ self.class.runner(:emacs)
237
294
  else
238
- RUNNERS[:console]
295
+ self.class.runner(:console)
239
296
  end
240
297
  end
241
298
 
242
299
  def default_collector
243
- COLLECTORS[@standalone ? :load : :descendant]
300
+ self.class.collector(@standalone ? :load : :descendant)
244
301
  end
245
302
  end
246
303
  end
@@ -36,7 +36,7 @@ module Test
36
36
  end
37
37
 
38
38
  def sort(suites)
39
- suites.sort_by{|s| s.name}
39
+ suites.sort_by {|suite| suite.name || suite.to_s}
40
40
  end
41
41
  end
42
42
  end
@@ -15,7 +15,7 @@ module Test
15
15
  super
16
16
  @system_excludes = [/~\z/, /\A\.\#/]
17
17
  @system_directory_excludes = [/\A(?:CVS|\.svn)\z/]
18
- @patterns = [/\Atest_.+\.rb\z/m]
18
+ @patterns = [/\Atest[_\-].+\.rb\z/m]
19
19
  @excludes = []
20
20
  @base = nil
21
21
  end
@@ -0,0 +1,86 @@
1
+ require 'test/unit/color'
2
+
3
+ module Test
4
+ module Unit
5
+ class ColorScheme
6
+ include Enumerable
7
+
8
+ class << self
9
+ @@default = nil
10
+ def default
11
+ @@default ||= new("success" => Color.new("green", :bold => true),
12
+ "failure" => Color.new("red", :bold => true),
13
+ "pending" => Color.new("magenta", :bold => true),
14
+ "omission" => Color.new("blue", :bold => true),
15
+ "notification" => Color.new("cyan", :bold => true),
16
+ "error" => Color.new("yellow", :bold => true) +
17
+ Color.new("black", :foreground => false))
18
+ end
19
+
20
+ @@schemes = {}
21
+ def all
22
+ @@schemes.merge("default" => default)
23
+ end
24
+
25
+ def [](id)
26
+ @@schemes[id.to_s]
27
+ end
28
+
29
+ def []=(id, scheme_or_spec)
30
+ if scheme_or_spec.is_a?(self)
31
+ scheme = scheme_or_spec
32
+ else
33
+ scheme = new(scheme_or_spec)
34
+ end
35
+ @@schemes[id.to_s] = scheme
36
+ end
37
+ end
38
+
39
+ def initialize(scheme_spec)
40
+ @scheme = {}
41
+ scheme_spec.each do |key, color_spec|
42
+ self[key] = color_spec
43
+ end
44
+ end
45
+
46
+ def [](name)
47
+ @scheme[name.to_s]
48
+ end
49
+
50
+ def []=(name, color_spec)
51
+ @scheme[name.to_s] = make_color(color_spec)
52
+ end
53
+
54
+ def each(&block)
55
+ @scheme.each(&block)
56
+ end
57
+
58
+ def to_hash
59
+ hash = {}
60
+ @scheme.each do |key, color|
61
+ hash[key] = color
62
+ end
63
+ hash
64
+ end
65
+
66
+ private
67
+ def make_color(color_spec)
68
+ if color_spec.is_a?(Color) or color_spec.is_a?(MixColor)
69
+ color_spec
70
+ else
71
+ color_name = nil
72
+ normalized_color_spec = {}
73
+ color_spec.each do |key, value|
74
+ key = key.to_sym
75
+ if key == :name
76
+ color_name = value
77
+ else
78
+ normalized_color_spec[key] = value
79
+ end
80
+ end
81
+ Color.new(color_name, normalized_color_spec)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -3,6 +3,8 @@ module Test
3
3
  class Color
4
4
  NAMES = ["black", "red", "green", "yellow",
5
5
  "blue", "magenta", "cyan", "white"]
6
+
7
+ attr_reader :name
6
8
  def initialize(name, options={})
7
9
  @name = name
8
10
  @foreground = options[:foreground]
@@ -13,19 +15,47 @@ module Test
13
15
  @underline = options[:underline]
14
16
  end
15
17
 
18
+ def foreground?
19
+ @foreground
20
+ end
21
+
22
+ def intensity?
23
+ @intensity
24
+ end
25
+
26
+ def bold?
27
+ @bold
28
+ end
29
+
30
+ def italic?
31
+ @italic
32
+ end
33
+
34
+ def underline?
35
+ @underline
36
+ end
37
+
38
+ def ==(other)
39
+ self.class === other and
40
+ [name, foreground?, intensity?,
41
+ bold?, italic?, underline?] ==
42
+ [other.name, other.foreground?, other.intensity?,
43
+ other.bold?, other.italic?, other.underline?]
44
+ end
45
+
16
46
  def sequence
17
47
  sequence = []
18
48
  if @name == "none"
19
49
  elsif @name == "reset"
20
50
  sequence << "0"
21
51
  else
22
- foreground_parameter = @foreground ? 3 : 4
23
- foreground_parameter += 6 if @intensity
52
+ foreground_parameter = foreground? ? 3 : 4
53
+ foreground_parameter += 6 if intensity?
24
54
  sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
25
55
  end
26
- sequence << "1" if @bold
27
- sequence << "3" if @italic
28
- sequence << "4" if @underline
56
+ sequence << "1" if bold?
57
+ sequence << "3" if italic?
58
+ sequence << "4" if underline?
29
59
  sequence
30
60
  end
31
61
 
@@ -39,6 +69,7 @@ module Test
39
69
  end
40
70
 
41
71
  class MixColor
72
+ attr_reader :colors
42
73
  def initialize(colors)
43
74
  @colors = colors
44
75
  end
@@ -56,6 +87,10 @@ module Test
56
87
  def +(other)
57
88
  self.class.new([self, other])
58
89
  end
90
+
91
+ def ==(other)
92
+ self.class === other and colors == other.colors
93
+ end
59
94
  end
60
95
  end
61
96
  end
@@ -507,6 +507,20 @@ module Test
507
507
  end
508
508
 
509
509
  module_function
510
+ def need_fold?(diff)
511
+ /^[-+].{79}/ =~ diff
512
+ end
513
+
514
+ def fold(string)
515
+ string.split(/\r?\n/).collect do |line|
516
+ line.gsub(/(.{78})/, "\\1\n")
517
+ end.join("\n")
518
+ end
519
+
520
+ def folded_readable(from, to, options={})
521
+ readable(fold(from), fold(to), options)
522
+ end
523
+
510
524
  def readable(from, to, options={})
511
525
  diff(ReadableDiffer, from, to, options)
512
526
  end
@@ -90,17 +90,14 @@ module Test
90
90
  end
91
91
 
92
92
  def add_fixture_method_name(how, variable_name, method_name)
93
- unless self.instance_variable_defined?(variable_name)
94
- self.instance_variable_set(variable_name, [])
95
- end
96
- methods = self.instance_variable_get(variable_name)
93
+ methods = instance_eval("#{variable_name} ||= []")
97
94
 
98
95
  if how == :prepend
99
96
  methods = [method_name] | methods
100
97
  else
101
98
  methods = methods | [method_name]
102
99
  end
103
- self.instance_variable_set(variable_name, methods)
100
+ instance_variable_set(variable_name, methods)
104
101
  end
105
102
 
106
103
  def registered_methods_variable_name(fixture, order)
@@ -144,19 +141,13 @@ module Test
144
141
  interested_ancestors.inject([]) do |result, ancestor|
145
142
  if ancestor.is_a?(Class)
146
143
  ancestor.class_eval do
147
- methods = []
148
- unregistered_methods = []
149
- if instance_variable_defined?(methods_variable)
150
- methods = instance_variable_get(methods_variable)
151
- end
152
- if instance_variable_defined?(unregistered_methods_variable)
153
- unregistered_methods =
154
- instance_variable_get(unregistered_methods_variable)
155
- end
156
- result + methods - unregistered_methods
144
+ methods = instance_eval("#{methods_variable} ||= []")
145
+ unregistered_methods =
146
+ instance_eval("#{unregistered_methods_variable} ||= []")
147
+ (result | methods) - unregistered_methods
157
148
  end
158
149
  else
159
- []
150
+ result
160
151
  end
161
152
  end
162
153
  end
@@ -56,6 +56,15 @@ module Test
56
56
  end
57
57
  end
58
58
 
59
+ # Notify some information.
60
+ #
61
+ # Example:
62
+ # def test_notification
63
+ # notify("I'm here!")
64
+ # # Reached here
65
+ # notify("Special!") if special_case?
66
+ # # Reached here too
67
+ # end
59
68
  def notify(message, &block)
60
69
  notification = Notification.new(name, filter_backtrace(caller), message)
61
70
  add_notification(notification)