Class: Oats::OatsData

Inherits:
Object
  • Object
show all
Defined in:
lib/oats/oats_data.rb

Constant Summary collapse

@@oats_def_file =
nil
@@resolve_path =
[]
@@define_always =

If no input, use default YAML file, overridden by user’s HOME or OATS_INI Specified oats_file becomes the overriding file. If specified, oats_default data is used instead of the default YAML contents. Returns loaded data in $oats

nil
@@include_hist =
[]

Class Method Summary collapse

Class Method Details

.history(omit = false) ⇒ Object

Returns Oats.data history files in an array.



210
211
212
213
214
215
216
# File 'lib/oats/oats_data.rb', line 210

def OatsData.history(omit=false)
  if omit
    Oats.data['_']['load_history'].select{|i| i.omit and i.in_result_dir}.collect{|i| i.file}
  else
    Oats.data['_']['load_history'].collect{|i| i.file}
  end
end

.include_yaml_file(incl_yamls, oats_file = nil) ⇒ Object

Handles include_yaml files. Calls OatsData.overlay to modify $oats. Returns nothing.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/oats/oats_data.rb', line 180

def OatsData.include_yaml_file(incl_yamls, oats_file = nil)
  return unless incl_yamls
  if incl_yamls
    incl_yamls = [incl_yamls] if incl_yamls.instance_of?(String)
    incl_yamls.each do |incl_yaml|
      begin
        incl_yaml_file = TestData.locate(incl_yaml, File.dirname(oats_file))
        Oats.assert incl_yaml_file,  "Can not locate file: #{incl_yaml}"

        hist = Oats.data['_']['load_history'].collect{|i| i.file} + @@include_hist
        Oats.assert ! hist.include?(incl_yaml_file), "Attempt to re-include #{incl_yaml_file} into #{hist.inspect}"
        begin
          @@include_hist.push(incl_yaml_file)
          OatsData.overlay(incl_yaml_file)
        ensure
          Oats.assert_equal incl_yaml_file, @@include_hist.pop
        end
      rescue
        msg = "While including [#{incl_yaml}]"
        msg += " from: " + oats_file if oats_file
        #          raise(OatsError, msg + $!)
        $log.error msg
        raise $!
      end
    end
    return
  end
end

.load(oats_file = , oats_default = nil) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/oats/oats_data.rb', line 94

def OatsData.load(oats_file = ENV['OATS_INI'] , oats_default = nil)
  @@define_always = nil
  @@oats_def_file ||= ENV['OATS_HOME'] + '/oats_ini.yml'

  if oats_file
    raise(OatsError, "Can not locate: #{oats_file}") unless File.exist?(oats_file)
  else
    oats_file = ENV['HOME'] ? File.join( ENV['HOME'] , 'oats_user.yml') : nil
    oats_file = nil unless oats_file and File.exist?(oats_file)
  end
  if oats_file
    begin
      oats_data = YAML.load_file(oats_file)
    rescue
      raise(OatsError, "While loading [#{oats_file}] " + $!)
    end
  end

  if oats_default # make a deep copy
    oats_default = Marshal.load(Marshal.dump(oats_default))
  else  # Only the first time, when reading the _ini files
    begin
      oats_default = YAML.load_file(@@oats_def_file)
    rescue
      raise(OatsError,"Error loading [#{@@oats_def_file}]: " + $!)
    end
    $oats = oats_default # So that resolve can resolve Oats.data calls
    begin
      OatsData.resolve(oats_default)
    rescue
      $log.error "While resolving variables in: " + @@oats_def_file
      #         raise(OatsError, $!.to_s)
      raise $!
    end
    # Use this hash to persist internally used oats_data
    oats_default['_'] = {}
    oats_default['_']['load_history']  = [ OatsDataLoadHistoryItem.new(@@oats_def_file) ]
    $oats = oats_default # $oats now has data resolved and has load_history
    # For some reason OCC/Ubuntu needed the environment but not Mac
    aut_dir_test = ENV['OATS_TESTS'] || oats_data['execution']['dir_tests'] || oats_default['execution']['dir_tests']
    if aut_dir_test
      aut_ini = aut_dir_test + '/aut_ini.yml'
      oats_default['include_yaml'] ||= aut_ini if File.exists?(aut_ini)
    end
    OatsData.include_yaml_file(oats_default['include_yaml'], @@oats_def_file) if oats_default['include_yaml']
    oats_default = $oats
  end

  if oats_data
    incl_yamls = oats_data['include_yaml']
    if incl_yamls and not oats_data['include_yaml_later']
      oats_data['include_yaml'] = nil
      OatsData.include_yaml_file(incl_yamls, oats_file)
    end
    begin
      @@oats_copy = Marshal.load(Marshal.dump($oats))
      merged = OatsData.merge($oats,oats_data)
    rescue OatsError
      $log.error "While merging: " + oats_file
      raise(OatsError, $!.to_s)
    rescue
      $log.error "While merging: " + oats_file
      raise
    end
    merged['_']['load_history'] << OatsDataLoadHistoryItem.new(oats_file)
    $oats = merged
    if incl_yamls and oats_data['include_yaml_later']
      merged['include_yaml'] = nil
      OatsData.include_yaml_file(incl_yamls, oats_file)
    end
    begin
      OatsData.resolve(merged)
    rescue
      $log.error "While resolving variables in: " + oats_file
      raise $!
    end
    result = $oats
  else
    $log.warn("Could not find oats-user.yml via OATS_INI or HOME definition. Using the system default.")
    result = oats_default
  end
  return result
end

.map_file_contents(oats_data, test_data, file_contents) ⇒ Object

Helper method to replace HTML file contents based on oats and test data mappings. Returns true if substitutions are made



384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/oats/oats_data.rb', line 384

def OatsData.map_file_contents(oats_data, test_data, file_contents)
  return false unless test_data
  changed = false
  test_data.each do |key,val|
    repVal = oats_data[key]
    next if val.nil? or repVal.nil?
    if val.class == Hash
      changed = changed or map_file_contents( repVal, val, file_contents)
    else
      changed = changed or file_contents.sub!(val, repVal)
      test_data[key] = repVal
    end
  end
end

.merge(config_ini, custom_ini) ⇒ Object

Overrides config_ini hash tree with custom_ini. At each level keep only the items specified by the include_list array

Raises:



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/oats/oats_data.rb', line 220

def OatsData.merge(config_ini, custom_ini)
  merged_config = config_ini
  raise(OatsError, "Original YAML is not a hash: "  + config_ini.inspect) unless config_ini.class == Hash
  return config_ini unless custom_ini # If input YAML is empty
  raise(OatsError, "Override YAML is not a hash: "  + custom_ini.inspect) unless custom_ini.class == Hash
  include_array = []
  include_list_exists = false
  @@define_always = custom_ini['define_always'] if custom_ini.include?('define_always')
  custom_ini.each do |key, val|
    if config_ini.has_key?(key)
      old_val = config_ini[key]
      unless old_val.nil? or val.nil?
        if (old_val.class != val.class)
          if val.instance_of?(FalseClass)  # If new value is different and false set it to nil
            val = nil
          elsif not ( (val.instance_of?(TrueClass) or val.instance_of?(FalseClass)) and
                (old_val.instance_of?(TrueClass) or old_val.instance_of?(FalseClass)) )
            $log.error "Entry [#{key}] was previously set to [#{old_val}] with type [" + old_val.class.to_s + "]"
            $log.error "  now being set to [#{val}] with type [" + val.class.to_s + "]"
            $log.error "  entry [#{old_val}] of the original YAML entry is part of: " + config_ini.inspect
            $log.error "  entry [#{val}] of over-ride YAML entry is part of: " + custom_ini.inspect
            raise(OatsError, "Attempt to override OATS data with a different type.")
          end
        end
      end
    else
      if key == "include_list"
        raise(OatsError, "The include_list " + val.inspect + " is not an Array") unless val.class == Array
        include_array = val
        include_list_exists = true
      else
        add_key = key.sub(/\s*\(define\)\s*/,'')
        if add_key == key and ! @@define_always
          raise(OatsError, "Override YAML key [#{key}] is not defined in the master YAML: " + @@oats_def_file)
        else
          if merged_config.has_key?(add_key)
            key = add_key
            old_val = config_ini[key]
          else
            merged_config[add_key] = val
            merged_config.delete(key) unless add_key == key
            next
          end
        end
      end
    end
    case val
    when Hash then merged_config[key] = merge( old_val, val) # Deep copy for Hashes
    when Array then # Only shallow copy for Arrays
      new_arr = []
      val.each { |e| new_arr << e }
      merged_config[key] = new_arr
    when String then merged_config[key] = val.dup
    else
      unless (val.nil? and (old_val.class == Hash) ) || key == "include_list"
        merged_config[key] = val
      end
    end
  end
  if include_list_exists
    return nil if  include_array.nil?
    merged_config.delete_if { |key,value| not include_array.include?(key) }
  end
  merged_config
end

.overlay(oats_file) ⇒ Object

Overlays $oats with contents of oats_file. Performs no compatibility checking.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/oats/oats_data.rb', line 286

def OatsData.overlay(oats_file)
  if oats_file.instance_of?(Hash)
    oats_overlay = oats_file
    oats_file = oats_overlay.keys.first + '_' + oats_overlay.values.first.keys.first
  else
    if oats_file
      raise(OatsError, "Can not locate [#{oats_file}]") unless File.exist?(oats_file)
    else
      raise(OatsError, "Must specify a oats_file")
    end
    begin
      oats_overlay = YAML.load_file(oats_file)
    rescue
      raise(OatsError, "While loading [#{oats_file}] " + $!)
    end
  end
  incl_yamls = oats_overlay['include_yaml']
  if incl_yamls and not oats_overlay['include_yaml_later']
    oats_overlay['include_yaml'] = nil
    OatsData.include_yaml_file(incl_yamls, oats_file)
  end
  # Clone it, don't change the original
  oats_new = Marshal.load(Marshal.dump($oats))
  begin
    OatsData.overlay_data(oats_overlay, oats_new)
  rescue OatsError
    $log.error "While overlaying: " + oats_file
    raise(OatsError, $!.to_s)
  rescue Exception
    $log.error "While overlaying: " + oats_file
    raise
  end
  oats_new['_']['load_history'] << OatsDataLoadHistoryItem.new(oats_file)

  $oats = oats_new
  if incl_yamls and oats_overlay['include_yaml_later']
    oats_overlay['include_yaml'] = nil
    OatsData.include_yaml_file(incl_yamls, oats_file)
  end
  begin
    OatsData.resolve(oats_new)
  rescue
    $log.error "While resolving variables in: " + oats_file
    raise $!
  end
  oats_new = $oats
  return oats_new
end

.overlay_data(overlay, oats_data) ⇒ Object

Recurse thru matching hash only, replace rest by overlay



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/oats/oats_data.rb', line 336

def OatsData.overlay_data(overlay, oats_data)
  overlay.each do |key, val|
    default_key = key.sub(/\s*\((default|define)\)\s*/,'')
    if default_key == key
      default_key = nil
    else
      key = default_key
    end
    if val.instance_of?(Hash)
      if oats_data[key].instance_of?(Hash)
        OatsData.overlay_data(val, oats_data[key])
      else
        oats_data[key] = val if oats_data[key] == nil
        OatsData.overlay_data(val, oats_data[key])
      end
    else
      if default_key
        oats_data[key] = val unless oats_data[key]
      else
        oats_data[key] = val
      end
    end
  end
end

.regenerate_file(file_in) ⇒ Object

Regenerates input file based on YAML. Assumes input is absolute path and exists. Return generated file path or nil if nothing is generated.



363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/oats/oats_data.rb', line 363

def OatsData.regenerate_file(file_in)
  file_in_root = file_in.sub(/(.*)\..*$/,'\1')
  file_in_extn = File.extname(file_in)
  yaml_in = file_in_root + '.yml'
  return nil unless File.exist?(yaml_in)
  file_gen = file_in_root + '.gen' + file_in_extn
  yml_out = file_in_root + '.gen.yml'
  $log.debug "Regenerating [#{file_in}] into [#{file_gen}] based on [#{yaml_in}]"
  file_contents = IO.read(file_in)
  test_data = YAML.load_file(yaml_in)
  if OatsData.map_file_contents(Oats.data, test_data, file_contents)
    File.open( file_gen, 'w' ) { |out| out.print file_contents }
    File.open( yml_out, 'w' ) { |out| YAML.dump( test_data, out ) }
    return file_gen
  else
    return nil
  end
end

.resolve(oats_data = nil) ⇒ Object

Resolves ENV[ entries in a oats_data



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/oats/oats_data.rb', line 19

def OatsData.resolve(oats_data = nil)
  oats_data = $oats unless oats_data
  changed = false
  oats_data.each do |key, val|
    if val.instance_of?(String)
      begin
        next unless /Oats\.|ENV\[/ =~ val  # skip if no need for change
        new_val = eval(val)
        next if new_val.instance_of?(String) and /Oats\.|ENV\[/ =~ new_val # skip if change did not help
        #          new_key = key.sub(/\s*\(wait4definition\)\s*/,'')
        #          next unless new_key == key or new_val # skip if wait4defs in effect
        #          oats_data[new_key] = new_val
        oats_data[key] = if new_val == 'previous_oats_value'
          oc = @@oats_copy
          @@resolve_path.each { |k| oc = oc[k] }
          oc[key]
        else
          new_val
        end
        changed = true
        #          oats_data.delete(key) unless new_key == key
      rescue Exception =>e
        $log.error "While evaluating Oats.data #{key}: #{val}"
        raise e
      end
    elsif val.instance_of?(Array)
      val.each_with_index do | item, index |
        if item.instance_of?(String)
          begin
            next unless /Oats\.|ENV\[/ =~ item  # skip if no need for change
            new_val = eval(item)
            next if /Oats\.|ENV\[/ =~ new_val # skip if change did not help
            val[index] = if new_val == 'previous_oats_value'
              oc = @@oats_copy
              @@resolve_path.each { |k| oc = oc[k] }
              oc[key]
            else
              new_val
            end
            changed = true
          rescue Exception =>exc
            $log.error "While evaluating [#{item}] for [#{index}]th entry in Rat.data #{key}: #{val}"
            raise exc
          end
        elsif item.instance_of?(Hash)
          begin
            @@resolve_path.push(key)
            res_return = resolve(item)
          ensure
            @@resolve_path.pop
          end
          changed = res_return || changed
        end
      end
    elsif val.instance_of?(Hash)
      begin
        @@resolve_path.push(key)
        res_return = resolve(val)
      ensure
        @@resolve_path.pop
      end
      changed = res_return || changed
    end
  end
  while changed
    changed = resolve(oats_data)
  end
  changed
end