packspec 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cli.rb +138 -50
  3. data/packspec.gemspec +1 -1
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a91d9d00afdded57bbe22fe3524fb9106d818fa2
4
- data.tar.gz: bb680cb5a60150401afa898ef8b0e99fdd36e55f
3
+ metadata.gz: 0531ed015b0fcc81e3aa62bac12011f33b69ce9b
4
+ data.tar.gz: cc8de8f4ac4d27cc08b2fa006bce54a6400c918d
5
5
  SHA512:
6
- metadata.gz: 8125e9ad5e50615a9bfd050e1d4ae0757f519531f8eb9e13c4da1c328004e6369c51d30d9d4505ed6c1c8e0c4e723e0b94599f838f35ac26cac47b7d9a51a99f
7
- data.tar.gz: 5cf94612ce34a3565a64287aa0a27218a8c18ea5ed979226756fdb0f298969b96991e6a89c288761c6453dfa96f94a1a3667bcda3677afee177a3b2588452449
6
+ metadata.gz: e924e041feab6d6b9c1befc1db57246e3597509eebbf8ee09fe3af06a77c461ad2cf05ef8d605a50b7a076e5339cd47f0bc45288ff01129fb1c3c82540bbdc9f
7
+ data.tar.gz: a41c8cfd6b471370cba5fe506898ddfdc3fb98c9d8d25243b559be03e023d3fcc8fa6af871d2e647e2d1b6e430b8757ff57fb7f22741a60b47d9f2644493f441
data/lib/cli.rb CHANGED
@@ -13,22 +13,59 @@ def parse_specs(path)
13
13
 
14
14
  # Specs
15
15
  specmap = {}
16
- for path in Dir.glob("#{path}/**/*.yml")
17
- spec = parse_spec(File.read(path))
16
+ for filepath in Dir.glob("#{path}/**/*.yml")
17
+ spec = parse_spec(File.read(filepath))
18
18
  if !spec
19
19
  next
20
20
  elsif !specmap.include?(spec['package'])
21
21
  specmap[spec['package']] = spec
22
22
  else
23
23
  specmap[spec['package']]['features'].merge!(spec['features'])
24
+ specmap[spec['package']]['scope'].merge!(spec['scope'])
24
25
  end
25
26
  end
26
27
 
27
28
  # Hooks
28
- # TODO: implement
29
+ hookmap = {}
30
+ for filepath in Dir.glob("#{path}/**/packspec.rb")
31
+ begin
32
+ eval(File.read(filepath))
33
+ hook_scope = Packspec::User.new()
34
+ for name in hook_scope.public_methods
35
+ # TODO: filter ruby builtin methods
36
+ hookmap["$#{name}"] = hook_scope.public_method(name)
37
+ end
38
+ rescue Exception
39
+ end
40
+ end
29
41
 
30
42
  # Result
31
43
  specs = Array(specmap.sort.to_h.each_value)
44
+ for spec in specs
45
+ skip = false
46
+ spec['ready'] = !spec['scope'].empty?
47
+ spec['stats'] = {'features' => 0, 'comments' => 0, 'skipped' => 0, 'tests' => 0}
48
+ for feature, index in spec['features'].dup.each_with_index
49
+ if feature['assign'] == 'PACKAGE'
50
+ if index > 0
51
+ spec['features'].delete_at(index)
52
+ end
53
+ end
54
+ spec['stats']['features'] += 1
55
+ if feature['comment']
56
+ skip = feature['skip']
57
+ spec['stats']['comments'] += 1
58
+ end
59
+ feature['skip'] = skip || feature['skip']
60
+ if !feature['comment']
61
+ spec['stats']['tests'] += 1
62
+ if feature['skip']
63
+ spec['stats']['skipped'] += 1
64
+ end
65
+ end
66
+ end
67
+ spec['scope'].merge!(hookmap)
68
+ end
32
69
 
33
70
  return specs
34
71
 
@@ -44,6 +81,15 @@ def parse_spec(spec)
44
81
  package = feature['result']
45
82
  assert_equal(feature['assign'], 'PACKAGE')
46
83
  assert_equal(feature['skip'], nil)
84
+ if package.is_a?(String)
85
+ package = {'default' => [package]}
86
+ elsif package.is_a?(Array)
87
+ package = {'default' => package}
88
+ elsif package.is_a?(Hash)
89
+ for key, value in package.each_pair()
90
+ package[key] = value.is_a?(Array) ? value : [value]
91
+ end
92
+ end
47
93
  rescue Exception
48
94
  return nil
49
95
  end
@@ -57,19 +103,28 @@ def parse_spec(spec)
57
103
 
58
104
  # Scope
59
105
  scope = {}
60
- require(package)
61
- for item in ObjectSpace.each_object
62
- if package == String(item).downcase
63
- begin
64
- namespace = Kernel.const_get(item)
65
- rescue Exception
66
- next
67
- end
68
- for name in namespace.constants
69
- scope[String(name)] = namespace.const_get(name)
106
+ packages = []
107
+ attributes = {}
108
+ for namespace, module_names in package.each_pair
109
+ packages.push(*module_names)
110
+ namespace_scope = scope
111
+ if namespace != 'default'
112
+ if !scope.key?(namespace) then scope[namespace] = {} end
113
+ namespace_scope = scope[namespace]
114
+ end
115
+ for module_name in module_names
116
+ attributes = get_module_attributes(module_name)
117
+ namespace_scope.merge!(attributes)
118
+ if !attributes.empty?
119
+ break
70
120
  end
71
121
  end
122
+ if attributes.empty?
123
+ scope = {}
124
+ break
125
+ end
72
126
  end
127
+ package = packages.sort().join('/')
73
128
 
74
129
  return {
75
130
  'package' => package,
@@ -81,8 +136,16 @@ end
81
136
 
82
137
 
83
138
  def parse_feature(feature)
139
+
140
+ # General
84
141
  if feature.is_a?(String)
85
- return {'comment' => feature}
142
+ match = /^(?:(.*):)?(\w.*)$/.match(feature)
143
+ skip, comment = match[1], match[2]
144
+ if !!skip
145
+ filters = skip.split(':')
146
+ skip = (filters[0] == 'not') == (filters.include?('rb'))
147
+ end
148
+ return {'assign' => nil, 'comment' => comment, 'skip' => skip}
86
149
  end
87
150
  left, right = Array(feature.each_pair)[0]
88
151
 
@@ -94,7 +157,7 @@ def parse_feature(feature)
94
157
  filters = skip.split(':')
95
158
  skip = (filters[0] == 'not') == (filters.include?('rb'))
96
159
  end
97
- if !assign and !property
160
+ if !assign && !property
98
161
  raise Exception.new('Non-valid feature')
99
162
  end
100
163
  if !!property
@@ -143,7 +206,7 @@ def parse_feature(feature)
143
206
  text = "#{text}(#{items.join(', ')})"
144
207
  end
145
208
  if !!result && !assign
146
- text = "#{text} == #{JSON.generate(result)}"
209
+ text = "#{text} == #{result == 'ERROR' ? result : JSON.generate(result)}"
147
210
  end
148
211
  text = text.gsub(/{"([^{}]*?)": null}/, '\1')
149
212
 
@@ -176,7 +239,6 @@ end
176
239
 
177
240
  def test_spec(spec)
178
241
  passed = 0
179
- amount = spec['features'].length
180
242
  message = Emoji.find_by_alias('heavy_minus_sign').raw * 3 + "\n\n"
181
243
  puts(message)
182
244
  for feature in spec['features']
@@ -185,14 +247,14 @@ def test_spec(spec)
185
247
  passed += 1
186
248
  end
187
249
  end
188
- success = (passed == amount)
250
+ success = (passed == spec['stats']['features'])
189
251
  color = 'green'
190
252
  message = ("\n " + Emoji.find_by_alias('heavy_check_mark').raw + ' ').green.bold
191
253
  if !success
192
254
  color = 'red'
193
255
  message = ("\n " + Emoji.find_by_alias('x').raw + ' ').red.bold
194
256
  end
195
- message += "#{spec['package']}: #{passed}/#{amount}\n".colorize(color).bold
257
+ message += "#{spec['package']}: #{passed - spec['stats']['comments'] - spec['stats']['skipped']}/#{spec['stats']['tests'] - spec['stats']['skipped']}\n".colorize(color).bold
196
258
  puts(message)
197
259
  return success
198
260
  end
@@ -215,8 +277,16 @@ def test_feature(feature, scope)
215
277
  return true
216
278
  end
217
279
 
280
+ # Dereference
281
+ # TODO: deepcopy feature
282
+ if !!feature['call']
283
+ feature['args'] = dereference_value(feature['args'], scope)
284
+ feature['kwargs'] = dereference_value(feature['kwargs'], scope)
285
+ end
286
+ feature['result'] = dereference_value(feature['result'], scope)
287
+
218
288
  # Execute
219
- # TODO: dereference feature
289
+ exception = nil
220
290
  result = feature['result']
221
291
  if !!feature['property']
222
292
  begin
@@ -225,16 +295,23 @@ def test_feature(feature, scope)
225
295
  property = get_property(property, name)
226
296
  end
227
297
  if !!feature['call']
228
- # TODO: support kwargs
298
+ args = feature['args'].dup
299
+ if !feature['kwargs'].empty?
300
+ args.push(Hash[feature['kwargs'].map{|k, v| [k.to_sym, v]}])
301
+ end
229
302
  if property.respond_to?('new')
230
- result = property.new(*feature['args'])
303
+ result = property.new(*args)
231
304
  else
232
- result = property.call(*feature['args'])
305
+ result = property.call(*args)
233
306
  end
234
307
  else
235
308
  result = property
309
+ if result.is_a?(Method)
310
+ result = result.call()
311
+ end
236
312
  end
237
- rescue Exception
313
+ rescue Exception => exc
314
+ exception = exc
238
315
  result = 'ERROR'
239
316
  end
240
317
  end
@@ -251,7 +328,6 @@ def test_feature(feature, scope)
251
328
  end
252
329
 
253
330
  # Compare
254
- # TODO: isoformat value
255
331
  if feature['result'] != nil
256
332
  success = result == feature['result']
257
333
  else
@@ -268,7 +344,12 @@ def test_feature(feature, scope)
268
344
  result_text = result.to_s
269
345
  end
270
346
  message = " #{Emoji.find_by_alias('x').raw} ".red
271
- message += "#{feature['text']} # #{result_text}"
347
+ message += "#{feature['text']}\n"
348
+ if exception
349
+ message += "Exception: #{exception}".red.bold
350
+ else
351
+ message += "Assertion: #{result_text} != #{JSON.generate(feature['result'])}".red.bold
352
+ end
272
353
  puts(message)
273
354
  end
274
355
 
@@ -277,20 +358,31 @@ def test_feature(feature, scope)
277
358
  end
278
359
 
279
360
 
280
- def dereference_feature(feature, scope)
281
- #TODO: deepcopy feature
282
- if !!feature['call']
283
- feature['args'] = dereference_value(feature['args'], scope)
284
- feature['kwargs'] = dereference_value(feature['kwargs'], scope)
361
+ def get_module_attributes(module_name)
362
+ attributes = {}
363
+ begin
364
+ require(module_name)
365
+ rescue Exception
366
+ return {}
367
+ end
368
+ for item in ObjectSpace.each_object
369
+ if module_name == String(item).downcase
370
+ begin
371
+ module_scope = Kernel.const_get(item)
372
+ rescue Exception
373
+ next
374
+ end
375
+ for name in module_scope.constants
376
+ attributes[String(name)] = module_scope.const_get(name)
377
+ end
285
378
  end
286
- feature['result'] = dereference_value(feature['result'], scope)
287
- return feature
379
+ end
380
+ return attributes
288
381
  end
289
382
 
290
383
 
291
384
  def dereference_value(value, scope)
292
- #TODO: deepcopy value
293
- if value.is_a?(Hash) && value.lengh == 1 && Array(value.each_value)[0] == nil
385
+ if value.is_a?(Hash) && value.length == 1 && Array(value.each_value)[0] == nil
294
386
  result = scope
295
387
  for name in Array(value.each_key)[0].split('.')
296
388
  result = get_property(result, name)
@@ -309,30 +401,26 @@ def dereference_value(value, scope)
309
401
  end
310
402
 
311
403
 
312
- def isoformat_value(value)
313
- # TODO: implement
314
- return value
315
- end
316
-
317
-
318
404
  def get_property(owner, name)
319
- # TODO: review
320
- result = nil
321
- if owner.is_a?(Hash)
322
- result = owner[name]
405
+ if owner.is_a?(Method)
406
+ owner = owner.call()
323
407
  end
324
- if !result
325
- result = owner.method(name)
408
+ if owner.class == Hash
409
+ return owner[name]
410
+ elsif owner.class == Array
411
+ return owner[name.to_i]
326
412
  end
327
- return result
413
+ return owner.method(name)
328
414
  end
329
415
 
330
416
 
331
417
  def set_property(owner, name, value)
332
- # TODO: review
333
- if owner.is_a?(Hash)
418
+ if owner.class == Hash
334
419
  owner[name] = value
335
420
  return
421
+ elsif owner.class == Array
422
+ owner[name.to_i] = value
423
+ return
336
424
  end
337
425
  return owner.const_set(name, value)
338
426
  end
data/packspec.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "packspec"
7
- spec.version = "0.1.4"
7
+ spec.version = "0.1.5"
8
8
  spec.authors = ["Evgeny Karev\n"]
9
9
  spec.email = ["eskarev@gmail.com"]
10
10
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - |
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-06-04 00:00:00.000000000 Z
12
+ date: 2017-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler