File: tc_container.rb

package info (click to toggle)
libneedle-ruby 1.2.0-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 1,436 kB
  • ctags: 886
  • sloc: ruby: 4,464; makefile: 52
file content (455 lines) | stat: -rw-r--r-- 13,415 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
#--
# =============================================================================
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
# All rights reserved.
#
# This source file is distributed as part of the Needle dependency injection
# library for Ruby. This file (and the library as a whole) may be used only as
# allowed by either the BSD license, or the Ruby license (or, by association
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
# distribution for the texts of these licenses.
# -----------------------------------------------------------------------------
# needle website : http://needle.rubyforge.org
# project website: http://rubyforge.org/projects/needle
# =============================================================================
#++

$:.unshift "../lib"

require 'test/unit'

require 'needle/container'
require 'needle/definition-context'
require 'needle/interceptor'
require 'needle/lifecycle/deferred'
require 'needle/lifecycle/initialize'
require 'needle/lifecycle/singleton'
require 'needle/lifecycle/threaded'
require 'needle/log-factory'
require 'needle/logging-interceptor'
require 'needle/pipeline/interceptor'

class TC_Container < Test::Unit::TestCase

  class CustomContainer < Needle::Container
  end

  class CustomBuilder < Needle::DefinitionContext
  end

  class CustomInterceptor < Needle::Interceptor
  end

  def new_container( *args )
    container = Needle::Container.new( *args )

    container.register( :pipeline_elements, :pipeline=>[] ) { Hash.new }
    container.pipeline( :pipeline_elements ).add( :singleton,
      Needle::Lifecycle::Singleton )

    container[:pipeline_elements].update(
      :singleton   => Needle::Lifecycle::Singleton,
      :initialize  => Needle::Lifecycle::Initialize,
      :deferred    => Needle::Lifecycle::Deferred,
      :interceptor => Needle::Pipeline::InterceptorElement,
      :threaded    => Needle::Lifecycle::Threaded
    )

    container.register( :service_models, :pipeline=>[:singleton] ) { Hash.new }
    container[:service_models].update(
      :prototype                     => [],
      :prototype_initialize          => [ :initialize ],
      :prototype_deferred            => [ :deferred ],
      :prototype_deferred_initialize => [ :deferred, :initialize ],
      :singleton                     => [ :singleton ],
      :singleton_initialize          => [ :singleton, :initialize ],
      :singleton_deferred            => [ :singleton, :deferred ],
      :singleton_deferred_initialize => [ :singleton, :deferred, :initialize ],
      :threaded                      => [ :threaded ],
      :threaded_initialize           => [ :threaded, :initialize ],
      :threaded_deferred             => [ :threaded, :deferred ],
      :threaded_deferred_initialize  => [ :threaded, :deferred, :initialize ]
    )

    container.register( :definition_context_factory ) { Needle::DefinitionContext }
    container.register( :namespace_impl_factory ) { Needle::Container }
    container.register( :interceptor_impl_factory ) { Needle::Interceptor }

    container.register( :logs ) { LogFactory.new( opts[:logs] || {} ) }
    container.register( :logging_interceptor ) { Needle::LoggingInterceptor }

    container
  end

  def test_default
    container = new_container
    assert_nil container.parent
    assert_nil container.name
    assert_equal container, container.root
    assert_equal "", container.fullname
  end

  def test_named
    container = new_container( nil, "name" )
    assert_nil container.parent
    assert_equal "name", container.name
    assert_equal container, container.root
    assert_equal "name", container.fullname
  end

  def test_nested
    outer = new_container
    inner = new_container( outer )
    assert_same outer, inner.parent
    assert_equal outer, inner.root
  end

  def test_root
    outer = new_container
    middle = new_container( outer )
    inner = new_container( middle )
    assert_same middle, inner.parent
    assert_equal outer, inner.root
  end

  def test_nested_named
    outer = new_container( nil, "outer" )
    inner = new_container( outer, "inner" )
    assert_equal "inner", inner.name
    assert_equal "outer.inner", inner.fullname
  end

  def test_service_not_found
    container = new_container
    assert_raise( Needle::ServiceNotFound ) do
      container[:test]
    end
  end

  def test_register
    container = new_container
    container.register( :test, :pipeline=>[] ) { Hash.new }

    assert_nothing_raised { container[:test] }
    assert_nothing_raised { container.test }

    assert_instance_of Hash, container[:test]
    assert_instance_of Hash, container.test

    assert container.respond_to?(:test)
  end

  def test_builder
    container = new_container
    b1 = container.builder
    b2 = container.builder

    assert_same b1.__id__, b2.__id__
  end

  def test_define_block
    container = new_container

    container.define do |b|
      b.test( :pipeline=>[] ) { Hash.new }
      b.namespace_define :subitem, :pipeline=>[] do |b2|
        b2.test2( :pipeline=>[] ) { Hash.new }
      end
    end

    assert container.has_key?( :test )
    assert_instance_of Hash, container.test
    assert container.subitem.has_key?( :test2 )
    assert_instance_of Hash, container.subitem.test2
  end

  def test_define_noblock
    container = new_container
    container.define.test( :pipeline=>[] ) { Hash.new }
    assert container.has_key?( :test )
    assert_instance_of Hash, container.test
  end

  def test_define!
    container = new_container

    container.define! do
      test( :pipeline=>[] ) { Hash.new }
      namespace! :subitem, :pipeline=>[] do
        test2( :pipeline=>[] ) { Hash.new }
      end
    end

    assert container.has_key?( :test )
    assert_instance_of Hash, container.test
    assert container.subitem.has_key?( :test2 )
    assert_instance_of Hash, container.subitem.test2
  end

  def test_namespace
    container = new_container
    container.namespace( :test, :pipeline=>[] )
    assert_instance_of Needle::Container, container.test

    container.namespace( :test2, :pipeline=>[] ) do |ns|
      assert_instance_of Needle::Container, ns
    end

    assert_instance_of Needle::Container, container.test2
  end

  def test_namespace_define
    container = new_container
    container.namespace_define( :test, :pipeline=>[] ) do |b|
      b.item( :pipeline=>[] ) { Hash.new }
    end
    assert container.has_key?( :test )
    assert container.test.has_key?( :item )
  end

  def test_namespace_define!
    container = new_container
    container.namespace_define!( :test, :pipeline=>[] ) do
      item( :pipeline=>[] ) { Hash.new }
    end
    assert container.has_key?( :test )
    assert container.test.has_key?( :item )
  end

  def test_namespace!
    container = new_container
    container.namespace!( :test, :pipeline=>[] ) do
      item( :pipeline=>[] ) { Hash.new }
    end
    assert container.has_key?( :test )
    assert container.test.has_key?( :item )
  end

  def test_has_key
    container = new_container

    assert !container.has_key?(:test)
    container.register( :test, :pipeline=>[] ) { Hash.new }
    assert container.has_key?(:test)
  end

  def test_knows_key
    container = new_container

    assert !container.knows_key?(:test)
    container.register( :test, :pipeline=>[] ) { Hash.new }
    assert container.knows_key?(:test)
  end

  def test_parent_knows_key
    outer = new_container
    inner = new_container( outer )

    outer.register( :test, :pipeline=>[] ) { Hash.new }
    assert !inner.has_key?(:test)
    assert inner.knows_key?(:test)
  end

  def test_service_in_parent
    outer = new_container
    inner = new_container( outer )

    outer.register( :test, :pipeline=>[] ) { Hash.new }
    assert_nothing_raised do
      inner[:test]
    end
  end

  def test_service_not_in_parent
    outer = new_container
    inner = new_container( outer )

    assert_raise( Needle::ServiceNotFound ) do
      inner[:test]
    end
  end

  def test_intercept_not_found
    container = new_container
    assert_raise( Needle::ServiceNotFound ) do
      container.intercept( :test )
    end
  end

  def test_intercept
    container = new_container
    container.register( :test ) { Hash.new }

    filtered = false
    container.intercept( :test ).doing { |chain,ctx| filtered = true; chain.process_next(ctx) }

    assert !filtered
    svc = container.test
    svc[:hello] = :world
    assert filtered
  end

  def test_find_definition_missing
    container = new_container
    assert_nil container.find_definition( :bogus )
  end

  def test_find_definition_found_local
    container = new_container
    container.register( :test, :pipeline=>[] ) { Object.new }
    assert_not_nil container.find_definition( :test )
  end

  def test_find_definition_found_ancestor
    outer = new_container
    inner = new_container( outer )
    outer.register( :test, :pipeline=>[] ) { Object.new }
    assert_not_nil inner.find_definition( :test )
  end

  def test_pipeline
    container = new_container
    container.register( :test, :pipeline=>[] ) { Object.new }
    assert_instance_of Needle::Pipeline::Collection, container.pipeline( :test )

    p1 = container.pipeline(:test)
    p2 = container.pipeline(:test)
    assert_same p1, p2
  end

  def test_require_default
    container = new_container
    container.register( :service_models, :pipeline=>[] ) { Hash[ :singleton => [] ] }
    container.require( "services", "A::B::C" )
    
    assert_not_nil container[:foo]
    assert_not_nil container[:foo][:bar]
  end

  def test_require_custom
    container = new_container
    container.register( :service_models , :pipeline=>[] ) { Hash[ :singleton => [] ] }
    container.require( "services", "A::B::C", :register_other_services )
    
    assert_not_nil container[:blah]
    assert_not_nil container[:blah][:baz]
  end

  def test_custom_namespace_impl
    container = new_container
    container.namespace :subspace

    subspace = container.subspace
    subspace.register( :namespace_impl_factory ) { CustomContainer }
    subspace.namespace :custom_namespace
    ns = subspace.custom_namespace

    assert_instance_of Needle::Container, subspace
    assert_instance_of CustomContainer, ns
  end

  def test_custom_builder_impl
    container = new_container
    container.namespace :subspace

    subspace = container.subspace
    subspace.register( :definition_context_factory ) { CustomBuilder }

    assert_equal Needle::DefinitionContext, container.builder.class
    assert_equal CustomBuilder, subspace.builder.class
  end

  def test_custom_interceptor_impl
    container = new_container
    container.namespace :subspace

    subspace = container.subspace
    subspace.register( :interceptor_impl_factory ) { CustomInterceptor }

    assert_equal Needle::Interceptor, container.intercept( :logs ).class
    assert_equal CustomInterceptor, subspace.intercept( :logs ).class
  end

  def test_descended_from?
    outer = new_container
    middle = new_container( outer )
    inner = new_container( middle )
    assert inner.descended_from?( outer )
    assert inner.descended_from?( middle )
    assert inner.descended_from?( inner )
    assert !outer.descended_from?( inner )
  end

  def test_defaults_inherited
    root = new_container
    root.defaults[:hello] = :world
    c1   = new_container( root )
    assert_equal :world, c1.defaults[:hello]
    root.defaults[:hello] = :jisang
    assert_equal :world, c1.defaults[:hello]
  end

  def test_defaults_used
    root = new_container
    root.define.foo { Object.new }
    root.defaults[:model] = :prototype
    root.define.bar { Object.new }
    f1 = root.foo
    f2 = root.foo
    assert_same f1, f2
    b1 = root.bar
    b2 = root.bar
    assert_not_same b1, b2
  end

  def test_use_bang_without_block
    root = new_container
    original = root.use! :model => :prototype
    assert original.empty?
    o2 = root.use! :pipeline => [ :threaded ]
    assert_nil root.defaults[:model]
    assert_equal [ :threaded ], root.defaults[:pipeline]
    root.use! o2
    assert_nil root.defaults[:pipeline]
    assert_equal :prototype, root.defaults[:model]
  end

  def test_use_bang_with_block
    root = new_container
    root.use! :model => :prototype do |r|
      assert_same root, r
      assert_equal :prototype, root.defaults[:model]
      root.use! :pipeline => [ :threaded ] do
        assert_nil root.defaults[:model]
        assert_equal [ :threaded ], root.defaults[:pipeline]
      end
      assert_nil root.defaults[:pipeline]
      assert_equal :prototype, root.defaults[:model]
    end
    assert_nil root.defaults[:model]
  end

  def test_use_without_block
    root = new_container
    o1 = root.use :model => :prototype
    o2 = root.use :pipeline => [ :threaded ]
    assert_equal :prototype, root.defaults[:model]
    assert_equal [ :threaded ], root.defaults[:pipeline]
  end

  def test_use_with_block
    root = new_container
    root.use :model => :prototype do |r|
      assert_same root, r
      assert_equal :prototype, root.defaults[:model]
      root.use :pipeline => [ :threaded ] do
        assert_equal :prototype, root.defaults[:model]
        assert_equal [ :threaded ], root.defaults[:pipeline]
      end
      assert_nil root.defaults[:pipeline]
      assert_equal :prototype, root.defaults[:model]
    end
    assert_nil root.defaults[:model]
  end

end