alki 0.1.0

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 (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +4 -0
  6. data/Rakefile +29 -0
  7. data/alki.gemspec +24 -0
  8. data/lib/alki/class_builder.rb +41 -0
  9. data/lib/alki/dsl_builder.rb +43 -0
  10. data/lib/alki/group_builder.rb +25 -0
  11. data/lib/alki/group_dsl.rb +98 -0
  12. data/lib/alki/loader.rb +32 -0
  13. data/lib/alki/overlay_delegator.rb +33 -0
  14. data/lib/alki/package.rb +33 -0
  15. data/lib/alki/package_builder.rb +2 -0
  16. data/lib/alki/package_executor.rb +120 -0
  17. data/lib/alki/package_processor.rb +167 -0
  18. data/lib/alki/service_delegator.rb +14 -0
  19. data/lib/alki/standard_package.rb +19 -0
  20. data/lib/alki/test.rb +28 -0
  21. data/lib/alki/util.rb +35 -0
  22. data/lib/alki/version.rb +3 -0
  23. data/lib/alki.rb +27 -0
  24. data/test/feature/create_package_test.rb +17 -0
  25. data/test/fixtures/config.rb +6 -0
  26. data/test/fixtures/example/config/handlers.rb +29 -0
  27. data/test/fixtures/example/config/package.rb +35 -0
  28. data/test/fixtures/example/config/settings.rb +11 -0
  29. data/test/fixtures/example/lib/array_output.rb +11 -0
  30. data/test/fixtures/example/lib/echo_handler.rb +9 -0
  31. data/test/fixtures/example/lib/example.rb +3 -0
  32. data/test/fixtures/example/lib/num_handler.rb +11 -0
  33. data/test/fixtures/example/lib/range_handler.rb +11 -0
  34. data/test/fixtures/example/lib/switch_handler.rb +9 -0
  35. data/test/integration/class_builder_test.rb +130 -0
  36. data/test/integration/loader_test.rb +36 -0
  37. data/test/test_helper.rb +1 -0
  38. data/test/unit/application_settings_test.rb +56 -0
  39. data/test/unit/application_test.rb +159 -0
  40. data/test/unit/package_processor_test.rb +319 -0
  41. metadata +129 -0
@@ -0,0 +1,159 @@
1
+ require_relative '../test_helper'
2
+
3
+ require 'alki/application'
4
+
5
+ describe Alki::Application do
6
+ before do
7
+ @settings = {test: 1}
8
+ @app = Alki::Application.new @settings
9
+ end
10
+
11
+ describe :settings do
12
+ it 'should return settings passed into new' do
13
+ @app.settings.must_be_same_as @settings
14
+ end
15
+ end
16
+
17
+ describe :configure do
18
+ it 'should allow calling methods as a DSL' do
19
+ @app.configure do
20
+ service :test_m do
21
+ :test
22
+ end
23
+ end
24
+ @app.test_m.must_equal :test
25
+ end
26
+ end
27
+
28
+ describe :root do
29
+ it 'should allow extracting the root group from the application' do
30
+ @app.service(:test_m) { :test }
31
+ @app.root.test_m.must_equal :test
32
+ end
33
+ end
34
+
35
+ describe :service do
36
+ it 'should create method that gets result of block' do
37
+ @app.service(:test_m) { :test }
38
+ @app.respond_to?(:test_m).must_equal true
39
+ @app.test_m.must_equal :test
40
+ end
41
+
42
+ it 'generated method should run on demand' do
43
+ count = 0
44
+ @app.service(:test_m){ count += 1; :test }
45
+ count.must_equal 0
46
+ @app.test_m
47
+ count.must_equal 1
48
+ end
49
+
50
+ it 'generated method should run only once' do
51
+ count = 0
52
+ @app.service(:test_m){ count += 1; :test }
53
+ @app.test_m
54
+ @app.test_m
55
+ count.must_equal 1
56
+ end
57
+ end
58
+
59
+ describe :group do
60
+ it 'should create group with block' do
61
+ @app.configure do
62
+ group :g1 do
63
+ end
64
+ end
65
+ @app.g1.wont_be_nil
66
+ end
67
+
68
+ it 'should add services to group' do
69
+ @app.configure do
70
+ group :g1 do
71
+ service(:testm1) { :test1 }
72
+ end
73
+ group :g1 do
74
+ service(:testm2) { :test2 }
75
+ end
76
+ end
77
+ @app.g1.testm1.must_equal :test1
78
+ @app.g1.testm2.must_equal :test2
79
+ end
80
+
81
+ it 'should allow creation of subgroups' do
82
+ @app.configure do
83
+ group :g1 do
84
+ group :g2 do
85
+ service(:test_m) { :test }
86
+ end
87
+ end
88
+ end
89
+ @app.g1.g2.test_m.must_equal :test
90
+ end
91
+
92
+ it 'should allow calling services of parent groups' do
93
+ @app.configure do
94
+ service(:test1) { :test1 }
95
+ group :g1 do
96
+ service(:test2) { :test2 }
97
+ group :g2 do
98
+ service(:test3) { [test1,test2] }
99
+ end
100
+ end
101
+ end
102
+ @app.g1.g2.test3.must_equal [:test1,:test2]
103
+ end
104
+
105
+ it 'should allow aliasing groups' do
106
+ @app.configure do
107
+ group :g1 do
108
+ service(:test_m) { :test }
109
+ end
110
+ end
111
+ @app.group(:g2,@app.g1)
112
+ @app[:g2].test_m.must_equal :test
113
+ end
114
+
115
+ it 'should allow moving groups to other applications' do
116
+ app2 = Alki::Application.new
117
+ app2.service(:test_m) { :test }
118
+ @app.group(:other,app2.root)
119
+ @app.other.test_m.must_equal :test
120
+ end
121
+
122
+ it 'should raise ArgumentError if non-group is provided' do
123
+ assert_raises ArgumentError do
124
+ @app.group(:test, {})
125
+ end
126
+ end
127
+ end
128
+
129
+ describe :lookup do
130
+ it 'should allow lookups of services by string' do
131
+ @app.service(:test_m) { :test }
132
+ @app.lookup('test_m').must_equal :test
133
+ end
134
+
135
+ it 'should allow looking up services in groups using dot separators' do
136
+ @app.configure do
137
+ group :g1 do
138
+ service(:test_m) { :test1 }
139
+ group :g2 do
140
+ service(:test_m) { :test2 }
141
+ end
142
+ end
143
+ end
144
+ @app.lookup('g1.test_m').must_equal :test1
145
+ @app.lookup('g1.g2.test_m').must_equal :test2
146
+ end
147
+ end
148
+
149
+ describe :delegate do
150
+ it 'should allow service reference cycles' do
151
+ @app.configure do
152
+ service(:all) { {print_all: delegate(:print_all)} }
153
+ service(:print_all) { list = all.keys; ->{ p list } }
154
+ end
155
+
156
+ @app.print_all.call.must_equal [:print_all]
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,319 @@
1
+ require_relative '../test_helper'
2
+ require 'alki/package_processor'
3
+
4
+ describe Alki::PackageProcessor do
5
+ def pkg(pkg,overrides ={})
6
+ {
7
+ type: :package,
8
+ children: pkg,
9
+ overrides: overrides
10
+ }
11
+ end
12
+ def group(children={})
13
+ {
14
+ type: :group,
15
+ children: children
16
+ }
17
+ end
18
+ def svc(sym)
19
+ {
20
+ type: :service,
21
+ block: -> { sym }
22
+ }
23
+ end
24
+ def factory(sym)
25
+ {
26
+ type: :factory,
27
+ block: -> { sym }
28
+ }
29
+ end
30
+ before do
31
+ @pe = Alki::PackageProcessor.new
32
+ @pkg1 = {
33
+ a: svc(:orig1_a),
34
+ b: svc(:orig1_b),
35
+ c: group
36
+ }
37
+ @desc = {
38
+ a: group(
39
+ test: svc(:a_test)
40
+ ),
41
+ b: svc(:b),
42
+ test: svc(:test),
43
+ pkg1: pkg(
44
+ @pkg1,
45
+ b: svc(:orig1_b_or)
46
+ )
47
+ }
48
+ end
49
+
50
+ describe :lookup do
51
+ it 'should identify services and return their block and a scope' do
52
+ pkg = {
53
+ a: svc(:a)
54
+ }
55
+ result = @pe.lookup(pkg,[:a])
56
+ result[:type].must_equal :service
57
+ result[:block].call.must_equal :a
58
+ result[:scope].must_be_instance_of Hash
59
+ end
60
+
61
+ it 'should identify factory and return their block and a scope' do
62
+ pkg = {
63
+ a: factory(:a)
64
+ }
65
+ result = @pe.lookup(pkg,[:a])
66
+ result[:type].must_equal :factory
67
+ result[:block].call.must_equal :a
68
+ result[:scope].must_be_instance_of Hash
69
+ end
70
+
71
+ it 'should identify groups and return their children' do
72
+ pkg2 = {
73
+ e: svc(:e)
74
+ }
75
+ pkg = {
76
+ a: svc(:a),
77
+ b: group(
78
+ c: svc(:c),
79
+ d: pkg(
80
+ pkg2,
81
+ f: svc(:f)
82
+ )
83
+ ),
84
+ }
85
+ @pe.lookup(pkg,[]).must_equal(
86
+ type: :group, children: {a: [:a], b: [:b]})
87
+ @pe.lookup(pkg,[:b]).must_equal(
88
+ type: :group, children: {c: [:b,:c],d: [:b,:d]})
89
+ @pe.lookup(pkg,[:b,:d]).must_equal(
90
+ type: :group, children: {e: [:b,:d,:e],f: [:b,:d,:f]})
91
+ @pe.lookup(pkg,[:b,:d,:orig]).must_equal(
92
+ type: :group, children: {e: [:b,:d,:orig,:e]})
93
+ end
94
+ end
95
+
96
+ describe :lookup_scope do
97
+ def scope(pkg,path)
98
+ @pe.lookup(pkg,path)[:scope]
99
+ end
100
+
101
+ it 'should contain a root item for the tree root' do
102
+ pkg = {
103
+ a: svc(:a)
104
+ }
105
+ scope(pkg,[:a]).must_equal(root: [],a: [:a])
106
+ end
107
+
108
+ it 'should return all visible items for the given context' do
109
+ pkg = {
110
+ a: svc(:a),
111
+ b: group(
112
+ c: svc(:c),
113
+ d: svc(:d),
114
+ )
115
+ }
116
+ scope(pkg,[:b,:c]).must_equal(root: [], a: [:a], b: [:b], c: [:b,:c], d: [:b,:d])
117
+ end
118
+
119
+ it 'should respect shadowing of symbols' do
120
+ pkg = {
121
+ a: svc(:a),
122
+ b: group(
123
+ a: svc(:a),
124
+ c: svc(:c),
125
+ )
126
+ }
127
+ scope(pkg,[:b,:c]).must_equal(root: [], a: [:b,:a], b: [:b], c: [:b,:c])
128
+ end
129
+
130
+ it 'should hide parent scope of context is in a package' do
131
+ pkg = {
132
+ a: svc(:a),
133
+ b: pkg(
134
+ c: svc(:c),
135
+ d: svc(:d),
136
+ )
137
+ }
138
+ scope(pkg,[:b,:c]).must_equal(root: [:b], c: [:b,:c], d: [:b,:d])
139
+ end
140
+
141
+ it 'should respect package overrides' do
142
+ pkg2 = {
143
+ c: svc(:c),
144
+ }
145
+ pkg = {
146
+ a: svc(:a),
147
+ b: pkg(
148
+ pkg2,
149
+ d: svc(:d),
150
+ )
151
+ }
152
+ scope(pkg,[:b,:c]).must_equal(root: [:b], c: [:b,:c], d: [:b,:d])
153
+ end
154
+
155
+ it 'should not change root and should add :orig symbol to override contexts' do
156
+ pkg2 = {
157
+ d: svc(:d),
158
+ }
159
+ pkg = {
160
+ a: svc(:a),
161
+ b: pkg(
162
+ pkg2,
163
+ c: svc(:c),
164
+ )
165
+ }
166
+ scope(pkg,[:b,:c]).must_equal(root: [],pkg: [:b,:orig], c: [:b,:c], a: [:a], b: [:b])
167
+ end
168
+
169
+ it 'should respect :orig symbol in path to access non-overriden services' do
170
+ pkg2 = {
171
+ c: svc(:c),
172
+ d: svc(:d),
173
+ }
174
+ pkg = {
175
+ a: svc(:a),
176
+ b: pkg(
177
+ pkg2,
178
+ c: svc(:c),
179
+ )
180
+ }
181
+ scope(pkg,[:b,:orig,:c]).must_equal(root: [:b], c: [:b,:c], d: [:b,:d])
182
+ end
183
+
184
+ it 'should handle nested packages' do
185
+ pkg2 = {
186
+ e: svc(:e),
187
+ }
188
+ pkg = {
189
+ a: svc(:a),
190
+ b: pkg(
191
+ c: svc(:c),
192
+ d: pkg(
193
+ pkg2,
194
+ f: svc(:f),
195
+ )
196
+ )
197
+ }
198
+ scope(pkg,[:b,:d,:e]).must_equal(root: [:b,:d], e: [:b,:d,:e], f: [:b,:d,:f])
199
+ scope(pkg,[:b,:d,:f]).must_equal(root: [:b], pkg: [:b,:d,:orig], d: [:b,:d], c: [:b,:c], f: [:b,:d,:f])
200
+ end
201
+
202
+ it 'should handle nested packages in overrides' do
203
+ pkg2 = {
204
+ c: svc(:c),
205
+ }
206
+ pkg3 = {
207
+ e: svc(:e),
208
+ }
209
+ pkg = {
210
+ a: svc(:a),
211
+ b: pkg(
212
+ pkg2,
213
+ d: pkg(
214
+ pkg3,
215
+ f: svc(:f)
216
+ )
217
+ )
218
+ }
219
+ scope(pkg,[:b,:d,:e]).must_equal(root: [:b,:d], e: [:b,:d,:e], f: [:b,:d,:f])
220
+ end
221
+ end
222
+
223
+ describe :lookup_overlays do
224
+ def overlays(pkg,path)
225
+ @pe.lookup(pkg,path)[:overlays].map{|o| o[:block]}
226
+ end
227
+
228
+ it 'should contain a root item for the tree root' do
229
+ pkg = {
230
+ a: svc(:a)
231
+ }
232
+ overlays(pkg,[:a]).must_equal([])
233
+ end
234
+
235
+ it 'should contain a root item for the tree root2' do
236
+ pkg = {
237
+ 'overlays' => [:o1,:o2],
238
+ a: svc(:a)
239
+ }
240
+ overlays(pkg,[:a]).must_equal([:o1,:o2])
241
+ end
242
+
243
+ it 'should contain a root item for the tree root3' do
244
+ pkg = {
245
+ 'overlays' => [:o1,:o2],
246
+ a: svc(:a),
247
+ b: group(
248
+ 'overlays' => [:o3,:o4],
249
+ c: svc(:c)
250
+ )
251
+ }
252
+ overlays(pkg,[:b,:c]).must_equal([:o1,:o2,:o3,:o4])
253
+ end
254
+
255
+ it 'should contain a root item for the tree root4' do
256
+ pkg = {
257
+ 'overlays' => [:o1],
258
+ a: svc(:a),
259
+ b: pkg(
260
+ 'overlays' => [:o3,:o4],
261
+ c: svc(:c)
262
+ )
263
+ }
264
+ overlays(pkg,[:b,:c]).must_equal([:o1,:o3,:o4])
265
+ end
266
+
267
+ it 'should contain a root item for the tree root5' do
268
+ pkg2 = {
269
+ 'overlays' => [:o3],
270
+ d: svc(:d),
271
+ }
272
+ pkg = {
273
+ 'overlays' => [:o1],
274
+ a: svc(:a),
275
+ b: pkg(pkg2,
276
+ 'overlays' => [:o2],
277
+ c: svc(:c)
278
+ )
279
+ }
280
+ overlays(pkg,[:b,:c]).must_equal([:o1,:o2,:o3])
281
+ overlays(pkg,[:b,:d]).must_equal([:o1,:o2,:o3])
282
+ end
283
+
284
+ it 'should contain a root item for the tree root6' do
285
+ pkg2 = {
286
+ 'overlays' => [:o3],
287
+ d: svc(:d),
288
+ }
289
+ pkg = {
290
+ 'overlays' => [:o1],
291
+ a: svc(:a),
292
+ b: pkg(pkg2,
293
+ 'overlays' => [:clear,:o2],
294
+ c: svc(:c)
295
+ )
296
+ }
297
+ overlays(pkg,[:b,:c]).must_equal([:o2,:o3])
298
+ overlays(pkg,[:b,:d]).must_equal([:o2,:o3])
299
+ end
300
+
301
+ it 'should contain a root item for the tree root7' do
302
+ pkg2 = {
303
+ 'overlays' => [:clear,:o3],
304
+ d: svc(:d),
305
+ }
306
+ pkg = {
307
+ 'overlays' => [:o1],
308
+ a: svc(:a),
309
+ b: pkg(pkg2,
310
+ 'overlays' => [:o2],
311
+ c: svc(:c)
312
+ )
313
+ }
314
+ overlays(pkg,[:b,:c]).must_equal([:o3])
315
+ overlays(pkg,[:b,:d]).must_equal([:o3])
316
+ end
317
+
318
+ end
319
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alki
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Edlefsen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Base library for building applications. Provides tools for organizing
42
+ and connection application units.
43
+ email:
44
+ - matt@xforty.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - alki.gemspec
55
+ - lib/alki.rb
56
+ - lib/alki/class_builder.rb
57
+ - lib/alki/dsl_builder.rb
58
+ - lib/alki/group_builder.rb
59
+ - lib/alki/group_dsl.rb
60
+ - lib/alki/loader.rb
61
+ - lib/alki/overlay_delegator.rb
62
+ - lib/alki/package.rb
63
+ - lib/alki/package_builder.rb
64
+ - lib/alki/package_executor.rb
65
+ - lib/alki/package_processor.rb
66
+ - lib/alki/service_delegator.rb
67
+ - lib/alki/standard_package.rb
68
+ - lib/alki/test.rb
69
+ - lib/alki/util.rb
70
+ - lib/alki/version.rb
71
+ - test/feature/create_package_test.rb
72
+ - test/fixtures/config.rb
73
+ - test/fixtures/example/config/handlers.rb
74
+ - test/fixtures/example/config/package.rb
75
+ - test/fixtures/example/config/settings.rb
76
+ - test/fixtures/example/lib/array_output.rb
77
+ - test/fixtures/example/lib/echo_handler.rb
78
+ - test/fixtures/example/lib/example.rb
79
+ - test/fixtures/example/lib/num_handler.rb
80
+ - test/fixtures/example/lib/range_handler.rb
81
+ - test/fixtures/example/lib/switch_handler.rb
82
+ - test/integration/class_builder_test.rb
83
+ - test/integration/loader_test.rb
84
+ - test/test_helper.rb
85
+ - test/unit/application_settings_test.rb
86
+ - test/unit/application_test.rb
87
+ - test/unit/package_processor_test.rb
88
+ homepage: https://gitlab.xforty.com/matt/base-alki
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.5.1
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Base library for building applications.
112
+ test_files:
113
+ - test/feature/create_package_test.rb
114
+ - test/fixtures/config.rb
115
+ - test/fixtures/example/config/handlers.rb
116
+ - test/fixtures/example/config/package.rb
117
+ - test/fixtures/example/config/settings.rb
118
+ - test/fixtures/example/lib/array_output.rb
119
+ - test/fixtures/example/lib/echo_handler.rb
120
+ - test/fixtures/example/lib/example.rb
121
+ - test/fixtures/example/lib/num_handler.rb
122
+ - test/fixtures/example/lib/range_handler.rb
123
+ - test/fixtures/example/lib/switch_handler.rb
124
+ - test/integration/class_builder_test.rb
125
+ - test/integration/loader_test.rb
126
+ - test/test_helper.rb
127
+ - test/unit/application_settings_test.rb
128
+ - test/unit/application_test.rb
129
+ - test/unit/package_processor_test.rb