lib/atp/flow.rb in atp-1.0.0 vs lib/atp/flow.rb in atp-1.1.0
- old
+ new
@@ -96,29 +96,34 @@
# Returns a processed/optimized AST, this is the one that should be
# used to build and represent the given test flow
def ast(options = {})
options = {
- apply_relationships: true,
+ apply_relationships: true,
# Supply a unique ID to append to all IDs
- unique_id: nil,
+ unique_id: nil,
# Set to :smt, or :igxl
- optimization: :runner,
+ optimization: :runner,
+ # When true, will remove set_result nodes in an on_fail branch which contains a continue
+ implement_continue: true,
+ # When false, this will not optimize the use of a flag by nesting a dependent test within
+ # the parent test's on_fail branch if the on_fail contains a continue
+ optimize_flags_when_continue: true,
# These options are not intended for application use, but provide the ability to
# turn off certain processors during test cases
- add_ids: true,
- optimize_flags: true,
- one_flag_per_test: true,
- implement_continue: true
+ add_ids: true,
+ optimize_flags: true,
+ one_flag_per_test: true
}.merge(options)
###############################################################################
## Common pre-processing and validation
###############################################################################
ast = Processors::PreCleaner.new.run(raw)
Validators::DuplicateIDs.new(self).run(ast)
Validators::MissingIDs.new(self).run(ast)
Validators::Jobs.new(self).run(ast)
+ Validators::Flags.new(self).run(ast)
# Ensure everything has an ID, this helps later if condition nodes need to be generated
ast = Processors::AddIDs.new.run(ast) if options[:add_ids]
ast = Processors::FlowID.new.run(ast, options[:unique_id]) if options[:unique_id]
###############################################################################
@@ -130,11 +135,13 @@
ast = Processors::Relationship.new.run(ast) if options[:apply_relationships]
ast = Processors::Condition.new.run(ast)
unless options[:optimization] == :runner
ast = Processors::ContinueImplementer.new.run(ast) if options[:implement_continue]
end
- ast = Processors::FlagOptimizer.new.run(ast) if options[:optimize_flags]
+ if options[:optimize_flags]
+ ast = Processors::FlagOptimizer.new.run(ast, optimize_when_continue: options[:optimize_flags_when_continue])
+ end
ast = Processors::AdjacentIfCombiner.new.run(ast)
###############################################################################
## Optimization for a row-based target, e.g. UltraFLEX
###############################################################################
@@ -185,10 +192,21 @@
options = flags.pop if flags.last.is_a?(Hash)
flags = flags.flatten
@pipeline[0] = add_volatile_flags(@pipeline[0], flags)
end
+ # Record a description for a bin number
+ def describe_bin(number, description, options = {})
+ @pipeline[0] = add_bin_description(@pipeline[0], number, description, type: :hard)
+ end
+
+ # Record a description for a softbin number
+ def describe_soft_bin(number, description, options = {})
+ @pipeline[0] = add_bin_description(@pipeline[0], number, description, type: :soft)
+ end
+ alias_method :describe_softbin, :describe_soft_bin
+
# Group all tests generated within the given block
#
# @example
# flow.group "RAM Tests" do
# flow.test ...
@@ -238,10 +256,14 @@
end
if options.delete(:continue)
options[:on_fail] ||= {}
options[:on_fail][:continue] = true
end
+ if options.key?(:delayed)
+ options[:on_fail] ||= {}
+ options[:on_fail][:delayed] = options.delete(:delayed)
+ end
if f = options.delete(:flag_pass)
options[:on_pass] ||= {}
options[:on_pass][:set_flag] = f
end
if f = options.delete(:flag_fail)
@@ -274,16 +296,27 @@
levels.each do |l|
children << level(l[:name], l[:value], l[:unit] || l[:units])
end
end
- if lims = options[:limit] || options[:limits]
- lims = [lims] unless lims.is_a?(Array)
- lims.each do |l|
- if l.is_a?(Hash)
- children << limit(l[:value], l[:rule], l[:unit] || l[:units])
+ lims = options[:limit] || options[:limits]
+ if lims || options[:lo] || options[:low] || options[:hi] || options[:high]
+ if lims == :none || lims == 'none'
+ children << n0(:nolimits)
+ else
+ lims = Array(lims) unless lims.is_a?(Array)
+ if lo = options[:lo] || options[:low]
+ lims << { value: lo, rule: :gte }
end
+ if hi = options[:hi] || options[:high]
+ lims << { value: hi, rule: :lte }
+ end
+ lims.each do |l|
+ if l.is_a?(Hash)
+ children << n(:limit, [l[:value], l[:rule], l[:unit] || l[:units], l[:selector]])
+ end
+ end
end
end
if pins = options[:pin] || options[:pins]
pins = [pins] unless pins.is_a?(Array)
@@ -448,10 +481,14 @@
def inspect
"<ATP::Flow:#{object_id} #{name}>"
end
+ def ids(options = {})
+ ATP::AST::Extractor.new.process(raw, [:id]).map { |node| node.to_a[0] }
+ end
+
private
def flow_control_method(name, flag, options = {}, &block)
extract_meta!(options)
if flag.is_a?(Array)
@@ -615,10 +652,11 @@
end
if options[:set_run_flag] || options[:set_flag]
children << set_flag_node(options[:set_run_flag] || options[:set_flag])
end
children << n0(:continue) if options[:continue]
+ children << n1(:delayed, !!options[:delayed]) if options.key?(:delayed)
children << n1(:render, options[:render]) if options[:render]
n(:on_fail, children)
end
end
@@ -661,18 +699,10 @@
else
n2(:level, name, value)
end
end
- def limit(value, rule, units = nil)
- if units
- n(:limit, [value, rule, units])
- else
- n2(:limit, value, rule)
- end
- end
-
def pin(name)
n1(:pin, name)
end
def set_result(type, options = {})
@@ -713,9 +743,30 @@
flags.each do |flag|
new << n1(:flag, flag) unless existing.include?(flag)
end
v = v.updated(nil, v.children + new)
node.updated(nil, [name, v] + nodes)
+ end
+
+ # Ensures the flow ast has a bin descriptions node, then adds the
+ # given description to it
+ def add_bin_description(node, number, description, options)
+ @existing_bin_descriptions ||= { soft: {}, hard: {} }
+ return node if @existing_bin_descriptions[options[:type]][number]
+ @existing_bin_descriptions[options[:type]][number] = true
+ name, *nodes = *node
+ if nodes[0] && nodes[0].type == :volatile
+ v = nodes.shift
+ else
+ v = nil
+ end
+ if nodes[0] && nodes[0].type == :bin_descriptions
+ d = nodes.shift
+ else
+ d = n0(:bin_descriptions)
+ end
+ d = d.updated(nil, d.children + [n2(options[:type], number, description)])
+ node.updated(nil, [name, v, d].compact + nodes)
end
def n(type, children, options = {})
options[:file] ||= options.delete(:source_file) || source_file
options[:line_number] ||= options.delete(:source_line_number) || source_line_number