raise('`attack_technique` element is required')unlessyaml.has_key?('attack_technique')
raise('`attack_technique` element must be an array')unlessyaml['attack_technique'].is_a?(String)
raise('`display_name` element is required')unlessyaml.has_key?('display_name')
raise('`display_name` element must be an array')unlessyaml['display_name'].is_a?(String)
raise('`atomic_tests` element is required')unlessyaml.has_key?('atomic_tests')
raise('`atomic_tests` element must be an array')unlessyaml['atomic_tests'].is_a?(Array)
raise('`atomic_tests` element is empty - you have no tests')unlessyaml['atomic_tests'].count>0
yaml['atomic_tests'].each_with_indexdo|atomic,i|
raise("`atomic_tests[#{i}].name` element is required")unlessatomic.has_key?('name')
raise("`atomic_tests[#{i}].name` element must be a string")unlessatomic['name'].is_a?(String)
raise("`atomic_tests[#{i}].description` element is required")unlessatomic.has_key?('description')
raise("`atomic_tests[#{i}].description` element must be a string")unlessatomic['description'].is_a?(String)
raise("`atomic_tests[#{i}].supported_platforms` element is required")unlessatomic.has_key?('supported_platforms')
raise("`atomic_tests[#{i}].supported_platforms` element must be an Array (was a #{atomic['supported_platforms'].class.name})")unlessatomic['supported_platforms'].is_a?(Array)
raise("`atomic_tests[#{i}].input_arguments[#{iai}].description` element is required")unlessarg.has_key?('description')
raise("`atomic_tests[#{i}].input_arguments[#{iai}].description` element must be a string")unlessarg['description'].is_a?(String)
raise("`atomic_tests[#{i}].input_arguments[#{iai}].type` element is required")unlessarg.has_key?('type')
raise("`atomic_tests[#{i}].input_arguments[#{iai}].type` element must be a string")unlessarg['type'].is_a?(String)
raise("`atomic_tests[#{i}].input_arguments[#{iai}].type` element must be lowercased and underscored (was #{arg['type']})")unlessarg['type']=~/[a-z_]+/
# TODO: determine if we think default values are required for EVERY input argument
# raise("`atomic_tests[#{i}].input_arguments[#{iai}].default` element is required") unless arg.has_key?('default')
# raise("`atomic_tests[#{i}].input_arguments[#{iai}].default` element must be a string (was a #{arg['default'].class.name})") unless arg['default'].is_a?(String)
end
raise("`atomic_tests[#{i}].executor` element is required")unlessatomic.has_key?('executor')
executor=atomic['executor']
raise("`atomic_tests[#{i}].executor.name` element is required")unlessexecutor.has_key?('name')
raise("`atomic_tests[#{i}].executor.name` element must be a string")unlessexecutor['name'].is_a?(String)
raise("`atomic_tests[#{i}].executor.name` element must be lowercased and underscored (was #{executor['name']})")unlessexecutor['name']=~/[a-z_]+/