lib/atp/flow.rb in atp-0.2.0 vs lib/atp/flow.rb in atp-0.2.1

- old
+ new

@@ -1,23 +1,26 @@ module ATP # Implements the main user API for building and interacting # with an abstract test program class Flow - attr_reader :program + attr_reader :program, :name # Returns the raw AST attr_reader :raw - def initialize(program) + def initialize(program, name = nil) @program = program + @name = name @builder = AST::Builder.new @raw = builder.flow end # Returns a processed/optimized AST, this is the one that should be # used to build and represent the given test flow def ast ast = Processors::PreCleaner.new.process(raw) + Validators::DuplicateIDs.new(self).process(ast) + Validators::MissingIDs.new(self).process(ast) ast = Processors::Condition.new.process(ast) ast = Processors::Relationship.new.process(ast) ast = Processors::PostCleaner.new.process(ast) end @@ -42,64 +45,90 @@ # @option options [String] :description A description of what the test does, usually formatted in markdown # @option options [Hash] :on_fail What action to take if the test fails, e.g. assign a bin # @option options [Hash] :on_pass What action to take if the test passes # @option options [Hash] :conditions What conditions must be met to execute the test def test(instance, options = {}) + extract_meta!(options) r = options.delete(:return) - if options[:context] == :current - options[:conditions] = builder.context[:conditions] - end - # Allows any continue, bin, or soft bin argument passed in at the options top-level to be assumed - # to be the action to take if the test fails - if b = options.delete(:bin) - options[:on_fail] ||= {} - options[:on_fail][:bin] = b - end - if b = options.delete(:softbin) || b = options.delete(:sbin) || b = options.delete(:soft_bin) - options[:on_fail] ||= {} - options[:on_fail][:softbin] = b - end - if options.delete(:continue) - options[:on_fail] ||= {} - options[:on_fail][:continue] = true - end - builder.new_context - - t = builder.test(instance, options) - unless options[:context] == :current - open_conditions.each do |conditions| - t = builder.apply_conditions(t, conditions) + t = apply_open_conditions(options) do |options| + # Allows any continue, bin, or soft bin argument passed in at the options top-level to be assumed + # to be the action to take if the test fails + if b = options.delete(:bin) + options[:on_fail] ||= {} + options[:on_fail][:bin] = b end + if b = options.delete(:softbin) || b = options.delete(:sbin) || b = options.delete(:soft_bin) + options[:on_fail] ||= {} + options[:on_fail][:softbin] = b + end + if options.delete(:continue) + options[:on_fail] ||= {} + options[:on_fail][:continue] = true + end + builder.test(instance, options) end append(t) unless r t end def bin(number, options = {}) - fail 'A :type option set to :pass or :fail is required when calling bin' unless options[:type] - options[:bin] = number - options[:softbin] ||= options[:soft_bin] || options[:sbin] - append builder.set_result(options[:type], options) + extract_meta!(options) + t = apply_open_conditions(options) do |options| + fail 'A :type option set to :pass or :fail is required when calling bin' unless options[:type] + options[:bin] = number + options[:softbin] ||= options[:soft_bin] || options[:sbin] + builder.set_result(options[:type], options) + end + append(t) end def cz(instance, cz_setup, options = {}) - options[:return] = true - append(builder.cz(cz_setup, test(instance, options))) + extract_meta!(options) + t = apply_open_conditions(options) do |options| + conditions = options.delete(:conditions) + options[:return] = true + builder.cz(cz_setup, test(instance, options), conditions: conditions) + end + append(t) end alias_method :characterize, :cz # Append a log message line to the flow def log(message, options = {}) - append builder.log(message) + extract_meta!(options) + t = apply_open_conditions(options) do |options| + builder.log(message, options) + end + append(t) end + # Enable a flow control variable + def enable(var, options = {}) + extract_meta!(options) + t = apply_open_conditions(options) do |options| + builder.enable_flow_flag(var, options) + end + append(t) + end + + # Disable a flow control variable + def disable(var, options = {}) + extract_meta!(options) + t = apply_open_conditions(options) do |options| + builder.disable_flow_flag(var, options) + end + append(t) + end + # Insert explicitly rendered content in to the flow def render(str, options = {}) + extract_meta!(options) append builder.render(str) end def with_condition(options) + extract_meta!(options) open_conditions.push(options) yield open_conditions.pop end alias_method :with_conditions, :with_condition @@ -109,9 +138,28 @@ Formatters::Datalog.run_and_format(ast, options) nil end private + + def apply_open_conditions(options) + if options[:context] == :current + options[:conditions] = builder.context[:conditions] + end + builder.new_context + t = yield(options) + unless options[:context] == :current + open_conditions.each do |conditions| + t = builder.apply_conditions(t, conditions) + end + end + t + end + + def extract_meta!(options) + builder.source_file = options.delete(:source_file) if options[:source_file] + builder.source_line_number = options.delete(:source_line_number) if options[:source_line_number] + end # For testing def raw=(ast) @raw = ast end