moab-versioning 1.3.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 (39) hide show
  1. checksums.yaml +7 -0
  2. data/lib/moab.rb +59 -0
  3. data/lib/moab/bagger.rb +289 -0
  4. data/lib/moab/config.rb +21 -0
  5. data/lib/moab/exceptions.rb +18 -0
  6. data/lib/moab/file_group.rb +244 -0
  7. data/lib/moab/file_group_difference.rb +336 -0
  8. data/lib/moab/file_group_difference_subset.rb +45 -0
  9. data/lib/moab/file_instance.rb +82 -0
  10. data/lib/moab/file_instance_difference.rb +54 -0
  11. data/lib/moab/file_inventory.rb +279 -0
  12. data/lib/moab/file_inventory_difference.rb +132 -0
  13. data/lib/moab/file_manifestation.rb +85 -0
  14. data/lib/moab/file_signature.rb +200 -0
  15. data/lib/moab/signature_catalog.rb +195 -0
  16. data/lib/moab/signature_catalog_entry.rb +61 -0
  17. data/lib/moab/storage_object.rb +220 -0
  18. data/lib/moab/storage_object_version.rb +333 -0
  19. data/lib/moab/storage_repository.rb +57 -0
  20. data/lib/moab/storage_services.rb +104 -0
  21. data/lib/moab/verification_result.rb +83 -0
  22. data/lib/moab/version_metadata.rb +38 -0
  23. data/lib/moab/version_metadata_entry.rb +64 -0
  24. data/lib/moab/version_metadata_event.rb +47 -0
  25. data/lib/moab_stanford.rb +18 -0
  26. data/lib/monkey_patches.rb +65 -0
  27. data/lib/serializer.rb +36 -0
  28. data/lib/serializer/manifest.rb +76 -0
  29. data/lib/serializer/serializable.rb +178 -0
  30. data/lib/stanford/active_fedora_object.rb +34 -0
  31. data/lib/stanford/content_inventory.rb +236 -0
  32. data/lib/stanford/dor_metadata.rb +49 -0
  33. data/lib/stanford/storage_repository.rb +46 -0
  34. data/lib/stanford/storage_services.rb +66 -0
  35. data/lib/tasks/yard.rake +34 -0
  36. data/lib/tools/api_doc_generator.rb +396 -0
  37. data/lib/tools/spec_generator.rb +410 -0
  38. data/lib/tools/spec_generator_old.rb +49 -0
  39. metadata +252 -0
@@ -0,0 +1,410 @@
1
+ require 'rubygems'
2
+ require 'hashery/orderedhash' if RUBY_VERSION < '1.9'
3
+ require 'pathname'
4
+ require 'yard'
5
+ include YARD
6
+
7
+ class String
8
+ def snake_case
9
+ self.gsub(/::/, '/').
10
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
11
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
12
+ tr("-", "_").
13
+ downcase
14
+ end
15
+ end
16
+
17
+ class Symbol
18
+ def snake_case
19
+ self.to_s.snake_case
20
+ end
21
+ end
22
+
23
+ class SpecGenerator
24
+
25
+ def initialize(rootpath)
26
+ @rootpath = rootpath
27
+ @ios = $stdout
28
+ end
29
+
30
+ def generate_tests
31
+ spec_pathname = Pathname(@rootpath).join('spec', 'temp', "temp_unit_tests")
32
+ classes = get_classes
33
+ classes.each do |cls|
34
+ test_pathname = spec_pathname.join(cls.path.snake_case + "_spec.rb")
35
+ test_pathname.parent.mkpath
36
+ #puts test_pathname.to_s
37
+ unless test_pathname.exist?
38
+ begin
39
+ @constructor_params = Array.new
40
+ @indent = 0
41
+ @ios = test_pathname.open("w")
42
+ process_class(cls)
43
+ ensure
44
+ @ios.close
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def get_classes()
51
+ yardoc = File.join(@rootpath, '.yardoc')
52
+ Registry.load!(yardoc) # loads all objects into memory
53
+ Registry.all(:class) # Array
54
+ end
55
+
56
+ # @param string [String]
57
+ def output(string)
58
+ @ios.puts " "*@indent + string
59
+ end
60
+
61
+ # @param cls [CodeObjects::ClassObject]
62
+ def process_class(cls)
63
+ output %q{require File.join('..', '..','spec_helper')}
64
+ output ""
65
+ output "# Unit tests for class {#{cls.path}}"
66
+ output "describe '#{cls.path}' do"
67
+ @indent += 1
68
+ mhash = categorize_members(cls)
69
+ if mhash[:class_attributes].size > 0
70
+ process_attributes(cls, :class, mhash[:class_attributes])
71
+ end
72
+ if mhash[:class_methods].size > 0
73
+ process_methods(cls, :class, mhash)
74
+ end
75
+
76
+ process_constructor(cls, mhash)
77
+
78
+ if mhash[:instance_attributes].size > 0
79
+ process_attributes(cls, :instance, mhash[:instance_attributes])
80
+ end
81
+ if mhash[:instance_methods].size > 0
82
+ process_methods(cls, :instance, mhash)
83
+ end
84
+
85
+ @indent -= 1
86
+ output ""
87
+ output "end"
88
+ end
89
+
90
+ # @param cls [CodeObjects::ClassObject]
91
+ def categorize_members(cls)
92
+ mhash = {
93
+ :class_attributes => OrderedHash.new,
94
+ :instance_attributes => OrderedHash.new,
95
+ :class_methods => Array.new,
96
+ :instance_methods => Array.new
97
+ }
98
+ cls.children.each do |member|
99
+ attr_symbol = member.name.to_s.gsub(/=$/, '').to_sym
100
+ if member.name == :initialize
101
+ mhash[:constructor] = member
102
+ elsif cls.class_attributes[attr_symbol]
103
+ mhash[:class_attributes][attr_symbol] = cls.class_attributes[attr_symbol]
104
+ elsif member.name.to_s[0..1] == '@@'
105
+ #mhash[:class_attributes][attr_symbol] = cls.class_attributes[attr_symbol]
106
+ elsif cls.instance_attributes[attr_symbol]
107
+ mhash[:instance_attributes][attr_symbol] = cls.instance_attributes[attr_symbol]
108
+ elsif not member.respond_to?(:scope)
109
+ #puts 'huh?'
110
+ elsif member.scope == :class
111
+ mhash[:class_methods] << member
112
+ elsif member.scope == :instance
113
+ mhash[:instance_methods] << member
114
+ end
115
+ end
116
+ mhash
117
+ end
118
+
119
+ def process_constructor(cls, mhash)
120
+ output ""
121
+ output "describe '=========================== CONSTRUCTOR ===========================' do"
122
+
123
+ @indent += 1
124
+ method = mhash[:constructor]
125
+ if method.respond_to?(:docstring)
126
+ @constructor_params = method.docstring.tags(:param)
127
+
128
+ output ""
129
+ output "# Unit test for constructor: {#{method.path}}"
130
+ output "# Which returns an instance of: [#{cls.path}]"
131
+ output "# For input parameters:"
132
+ @constructor_params.each do |p|
133
+ output "# * #{p.name} [#{p.types.join(', ')}] = #{p.text.gsub(/\n/, ' ')} "
134
+ end
135
+ output "specify '#{method.path}' do"
136
+ @indent += 1
137
+
138
+ cls_instance = cls.name.snake_case
139
+ param_list = (@constructor_params.collect { |p| p.name }).join(', ')
140
+
141
+ output " "
142
+ output "# test initialization with required parameters (if any)"
143
+ @constructor_params.each do |p|
144
+ if p.name == 'opts'
145
+ output "opts = {}"
146
+ else
147
+ output "#{p.name} = #{value_for(p.name, p.types[0])} "
148
+ end
149
+ end
150
+ output "#{cls_instance} = #{cls.name}.new(#{param_list})"
151
+ output "#{cls_instance}.should be_instance_of(#{cls.name})"
152
+ @constructor_params.each do |p|
153
+ unless p.name == 'opts'
154
+ output "#{cls_instance}.#{p.name}.should == #{p.name}"
155
+ end
156
+ end
157
+
158
+ arrays_and_hashes = attribute_arrays_and_hashes(mhash)
159
+ if arrays_and_hashes.size > 0
160
+ output " "
161
+ output "# test initialization of arrays and hashes"
162
+ arrays_and_hashes.each do |attr_name, type|
163
+ output "#{cls_instance}.#{attr_name}.should be_kind_of(#{type})"
164
+ end
165
+ end
166
+
167
+ @constructor_params.each do |p|
168
+ if p.name == 'opts'
169
+ output " "
170
+ output "# test initialization with options hash"
171
+ output "opts = OrderedHash.new"
172
+ attribute_name_type_pairs(mhash).each do |name, type|
173
+ output "opts[:#{name}] = #{value_for(name, type)}"
174
+ end
175
+ output "#{cls_instance} = #{cls.name}.new(#{param_list})"
176
+ attribute_name_type_pairs(mhash).each do |name, type|
177
+ output "#{cls_instance}.#{name}.should == opts[:#{name}]"
178
+ end
179
+ end
180
+ end
181
+
182
+ output_source(method)
183
+ @indent -= 1
184
+
185
+ output "end"
186
+
187
+ end
188
+ @indent -= 1
189
+ output ""
190
+ output "end"
191
+ end
192
+
193
+ def process_attributes(cls, scope, attributes)
194
+ output ""
195
+ output "describe '=========================== #{scope.to_s.upcase} ATTRIBUTES ===========================' do"
196
+ @indent += 1
197
+
198
+ if scope == :instance
199
+ output ""
200
+ output "before(:all) do"
201
+ @indent += 1
202
+ @constructor_params.each do |p|
203
+ if p.name == 'opts'
204
+ output "opts = {}"
205
+ else
206
+ output "#{p.name} = #{value_for(p.name, p.types[0])} "
207
+ end
208
+ end
209
+ cls_instance = cls.name.snake_case
210
+ param_list = (@constructor_params.collect { |p| p.name }).join(', ')
211
+ output "@#{cls_instance} = #{cls.name}.new(#{param_list})"
212
+ @indent -= 1
213
+ output "end"
214
+ end
215
+
216
+ attributes.values.each do |attribute|
217
+ if attribute.nil?
218
+ puts "huh?"
219
+ end
220
+ write = attribute[:write]
221
+ read = attribute[:read]
222
+ return_tag = read.docstring.tag(:return)
223
+ return_type = return_tag.types[0]
224
+ output ""
225
+ output "# Unit test for attribute: {#{read.path}}"
226
+ output "# Which stores: [#{return_type}] #{return_tag.text.gsub(/\n/, ' ')}"
227
+ output "specify '#{read.path}' do"
228
+
229
+ @indent += 1
230
+ output "value = #{value_for(read.name, return_type)}"
231
+ case scope
232
+ when :class
233
+ output "#{write.path} value"
234
+ output "#{read.path}.should == value"
235
+ when :instance
236
+ output "@#{cls.name.snake_case}.#{write.name} value"
237
+ output "@#{cls.name.snake_case}.#{read.name}.should == value"
238
+ end
239
+
240
+ output_source(write)
241
+ output_source(read)
242
+
243
+ @indent -= 1
244
+ output "end"
245
+ end
246
+ @indent -= 1
247
+
248
+ output ""
249
+ output "end"
250
+ end
251
+
252
+ def process_methods(cls, scope, mhash)
253
+ output ""
254
+ output "describe '=========================== #{scope.to_s.upcase} METHODS ===========================' do"
255
+ @indent += 1
256
+
257
+ if scope == :instance
258
+ output ""
259
+ output "before(:each) do"
260
+ @indent += 1
261
+ @constructor_params.each do |p|
262
+ if p.name == 'opts'
263
+ output "@opts = {}"
264
+ else
265
+ output "@#{p.name} = #{value_for(p.name, p.types[0])} "
266
+ end
267
+ end
268
+ cls_instance = cls.name.snake_case
269
+ param_list = (@constructor_params.collect { |p| '@'+p.name }).join(', ')
270
+ output "@#{cls_instance} = #{cls.name}.new(#{param_list})"
271
+ output ""
272
+ attribute_name_type_pairs(mhash).each do |name, type|
273
+ output "@#{cls_instance}.#{name} = #{value_for(name, type)}"
274
+ end
275
+ @indent -= 1
276
+ output "end"
277
+ end
278
+
279
+ case scope
280
+ when :class
281
+ methods =mhash[:class_methods]
282
+ when :instance
283
+ methods =mhash[:instance_methods]
284
+ end
285
+
286
+ methods.each do |method|
287
+ begin
288
+ return_tag = method.docstring.tag(:return)
289
+ return_type = return_tag.types[0]
290
+
291
+
292
+ params = method.docstring.tags(:param)
293
+
294
+ output ""
295
+ output "# Unit test for method: {#{method.path}}"
296
+ output "# Which returns: [#{return_type}] #{return_tag.text.gsub(/\n/, ' ')}"
297
+ if params.length > 0
298
+ output "# For input parameters:"
299
+ params.each do |p|
300
+ output "# * #{p.name} [#{p.types.join(', ')}] = #{p.text.gsub(/\n/, ' ')} "
301
+ end
302
+ else
303
+ output "# For input parameters: (None)"
304
+ end
305
+
306
+ output "specify '#{method.path}' do"
307
+
308
+ @indent += 1
309
+ params.each do |p|
310
+ output "#{p.name} = #{value_for(p.name, p.types[0])} "
311
+ end
312
+ param_list = (params.collect { |p| p.name }).join(', ')
313
+ if return_type == 'void'
314
+ case scope
315
+ when :class
316
+ output "#{method.path}(#{param_list})"
317
+ when :instance
318
+ output "@#{cls.name.snake_case}.#{method.name}(#{param_list})"
319
+ end
320
+ else
321
+ case scope
322
+ when :class
323
+ output "#{method.path}(#{param_list}).should == "
324
+ when :instance
325
+ output "@#{cls.name.snake_case}.#{method.name}(#{param_list}).should == "
326
+ end
327
+ end
328
+
329
+ output_source(method)
330
+ @indent -= 1
331
+
332
+ output "end"
333
+
334
+ rescue Exception => e
335
+ raise "Error processing method: #{method.path} - " + e.message
336
+ e.backtrace
337
+ end
338
+ end
339
+ @indent -= 1
340
+
341
+ output ""
342
+ output "end"
343
+ end
344
+
345
+
346
+ def value_for(name, return_type)
347
+ case return_type
348
+ when 'Symbol'
349
+ ":test_#{name}"
350
+ when 'Integer'
351
+ rand(100).to_s
352
+ when 'String'
353
+ "'Test #{name}'"
354
+ when 'Boolean'
355
+ "true"
356
+ when 'Pathname'
357
+ "Pathname.new('/test/#{name}')"
358
+ when 'Time'
359
+ "Time.now"
360
+ else
361
+ type = return_type.split(/[<>]/)
362
+ if type.length > 1
363
+ case type[0]
364
+ when 'Array'
365
+ "[#{value_for(name, type[1])}]"
366
+ when 'Hash', 'OrderedHash'
367
+ key, value = type[1].split(/[,]/)
368
+ "{#{value_for(name, key)} => #{value_for(name, value)}}"
369
+ else
370
+ "double(#{return_type}.name)"
371
+ end
372
+ else
373
+ "double(#{return_type}.name)"
374
+ end
375
+ end
376
+ end
377
+
378
+ def attribute_arrays_and_hashes(mhash)
379
+ arrays_and_hashes = OrderedHash.new
380
+ attribute_name_type_pairs(mhash).each do |name, type|
381
+ if type.include?('Array')
382
+ arrays_and_hashes[name] = 'Array'
383
+ elsif type.include?('Hash')
384
+ arrays_and_hashes[name] = 'Hash'
385
+ end
386
+ end
387
+ arrays_and_hashes
388
+ end
389
+
390
+ def attribute_name_type_pairs(mhash)
391
+ pairs = OrderedHash.new
392
+ mhash[:instance_attributes].values.each do |attribute|
393
+ read = attribute[:read]
394
+ return_tag = read.docstring.tag(:return)
395
+ pairs[read.name] =return_tag.types[0]
396
+ end
397
+ pairs
398
+ end
399
+
400
+ def output_source(method)
401
+ output " "
402
+ lines = method.source.split(/\n/)
403
+ lines.each { |line| output "# #{line}" }
404
+ end
405
+
406
+ end
407
+
408
+
409
+ sg = SpecGenerator.new(File.expand_path(File.join(File.dirname(__FILE__), '..', '..')))
410
+ sg.generate_tests
@@ -0,0 +1,49 @@
1
+ rootpath = File.expand_path(File.join(File.dirname(__FILE__), '..'))
2
+ puts rootpath
3
+ lib = File.join(rootpath,'lib')
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'moab'
6
+ #spec_helper = File.join(rootpath,'spec','spec_helper')
7
+
8
+ class SpecGeneratorOld
9
+
10
+ attr_accessor :c
11
+ attr_accessor :members
12
+
13
+ def initialize(c)
14
+ @c=c
15
+ #require camel_to_snake_case(c.name)
16
+ i_members = c.instance_methods(include_super=false)
17
+ i_setters = i_members.grep /[^=][=]$/
18
+ i_getters = i_setters.collect { |s| s.gsub(/[=]$/,'') }
19
+ @members = Hash.new
20
+ @members['Instance Variables'] = (i_getters).sort
21
+ @members['Instance Methods'] = (i_members - i_setters - i_getters).sort
22
+ @members['Class Methods'] = c.methods(include_super=false).sort
23
+ end
24
+
25
+ def generate
26
+ puts "require 'spec_helper'"
27
+ puts ""
28
+ puts "describe '#{@c.name}' do"
29
+ puts ""
30
+ ['Instance Variables','Instance Methods','Class Methods'].each do |type |
31
+ puts " context '#{type}' do"
32
+ puts ""
33
+ @members[type].each do |member|
34
+ puts " describe '##{member}' do"
35
+ puts " pending"
36
+ puts " end"
37
+ puts ""
38
+ end
39
+ puts " end"
40
+ puts ""
41
+ end
42
+ puts "end"
43
+ end
44
+
45
+ def camel_to_snake_case(camel)
46
+ camel.gsub(/(.)([A-Z])/,'\1_\2').downcase
47
+ end
48
+
49
+ end