packspec 0.1.4 → 0.1.5

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 (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