moab-versioning 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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