origen_testers 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. checksums.yaml +7 -0
  2. data/config/application.rb +140 -0
  3. data/config/commands.rb +73 -0
  4. data/config/development.rb +12 -0
  5. data/config/environment.rb +1 -0
  6. data/config/shared_commands.rb +47 -0
  7. data/config/users.rb +18 -0
  8. data/config/version.rb +8 -0
  9. data/lib/commands/build.rb +69 -0
  10. data/lib/origen_testers.rb +23 -0
  11. data/lib/origen_testers/api.rb +258 -0
  12. data/lib/origen_testers/basic_test_setups.rb +105 -0
  13. data/lib/origen_testers/callback_handlers.rb +58 -0
  14. data/lib/origen_testers/generator.rb +279 -0
  15. data/lib/origen_testers/generator/flow_control_api.rb +611 -0
  16. data/lib/origen_testers/generator/identity_map.rb +23 -0
  17. data/lib/origen_testers/generator/placeholder.rb +11 -0
  18. data/lib/origen_testers/generator/test_numberer.rb +23 -0
  19. data/lib/origen_testers/igxl_based_tester.rb +12 -0
  20. data/lib/origen_testers/igxl_based_tester/base.rb +641 -0
  21. data/lib/origen_testers/igxl_based_tester/base/flow.rb +171 -0
  22. data/lib/origen_testers/igxl_based_tester/base/flow_line.rb +322 -0
  23. data/lib/origen_testers/igxl_based_tester/base/generator.rb +217 -0
  24. data/lib/origen_testers/igxl_based_tester/base/patgroup.rb +109 -0
  25. data/lib/origen_testers/igxl_based_tester/base/patgroups.rb +38 -0
  26. data/lib/origen_testers/igxl_based_tester/base/patset.rb +68 -0
  27. data/lib/origen_testers/igxl_based_tester/base/patset_pattern.rb +56 -0
  28. data/lib/origen_testers/igxl_based_tester/base/patsets.rb +38 -0
  29. data/lib/origen_testers/igxl_based_tester/base/patsubr.rb +68 -0
  30. data/lib/origen_testers/igxl_based_tester/base/patsubr_pattern.rb +56 -0
  31. data/lib/origen_testers/igxl_based_tester/base/patsubrs.rb +38 -0
  32. data/lib/origen_testers/igxl_based_tester/base/test_instance.rb +326 -0
  33. data/lib/origen_testers/igxl_based_tester/base/test_instance_group.rb +58 -0
  34. data/lib/origen_testers/igxl_based_tester/base/test_instances.rb +179 -0
  35. data/lib/origen_testers/igxl_based_tester/files.rb +43 -0
  36. data/lib/origen_testers/igxl_based_tester/j750.rb +248 -0
  37. data/lib/origen_testers/igxl_based_tester/j750/flow.rb +10 -0
  38. data/lib/origen_testers/igxl_based_tester/j750/flow_line.rb +19 -0
  39. data/lib/origen_testers/igxl_based_tester/j750/generator.rb +19 -0
  40. data/lib/origen_testers/igxl_based_tester/j750/patgroup.rb +9 -0
  41. data/lib/origen_testers/igxl_based_tester/j750/patgroups.rb +10 -0
  42. data/lib/origen_testers/igxl_based_tester/j750/patset.rb +9 -0
  43. data/lib/origen_testers/igxl_based_tester/j750/patset_pattern.rb +18 -0
  44. data/lib/origen_testers/igxl_based_tester/j750/patsets.rb +10 -0
  45. data/lib/origen_testers/igxl_based_tester/j750/patsubr.rb +9 -0
  46. data/lib/origen_testers/igxl_based_tester/j750/patsubr_pattern.rb +18 -0
  47. data/lib/origen_testers/igxl_based_tester/j750/patsubrs.rb +10 -0
  48. data/lib/origen_testers/igxl_based_tester/j750/templates/flow.txt.erb +9 -0
  49. data/lib/origen_testers/igxl_based_tester/j750/templates/instances.txt.erb +16 -0
  50. data/lib/origen_testers/igxl_based_tester/j750/templates/patgroups.txt.erb +8 -0
  51. data/lib/origen_testers/igxl_based_tester/j750/templates/patsets.txt.erb +10 -0
  52. data/lib/origen_testers/igxl_based_tester/j750/templates/patsubrs.txt.erb +10 -0
  53. data/lib/origen_testers/igxl_based_tester/j750/test_instance.rb +547 -0
  54. data/lib/origen_testers/igxl_based_tester/j750/test_instance_group.rb +9 -0
  55. data/lib/origen_testers/igxl_based_tester/j750/test_instances.rb +10 -0
  56. data/lib/origen_testers/igxl_based_tester/j750_hpt.rb +34 -0
  57. data/lib/origen_testers/igxl_based_tester/j750_hpt/flow.rb +9 -0
  58. data/lib/origen_testers/igxl_based_tester/j750_hpt/flow_line.rb +9 -0
  59. data/lib/origen_testers/igxl_based_tester/j750_hpt/generator.rb +19 -0
  60. data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroup.rb +9 -0
  61. data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroups.rb +9 -0
  62. data/lib/origen_testers/igxl_based_tester/j750_hpt/patset.rb +9 -0
  63. data/lib/origen_testers/igxl_based_tester/j750_hpt/patset_pattern.rb +9 -0
  64. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsets.rb +9 -0
  65. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr.rb +9 -0
  66. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr_pattern.rb +9 -0
  67. data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubrs.rb +9 -0
  68. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance.rb +515 -0
  69. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance_group.rb +9 -0
  70. data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instances.rb +9 -0
  71. data/lib/origen_testers/igxl_based_tester/parser.rb +102 -0
  72. data/lib/origen_testers/igxl_based_tester/parser/ac_spec.rb +9 -0
  73. data/lib/origen_testers/igxl_based_tester/parser/ac_specs.rb +0 -0
  74. data/lib/origen_testers/igxl_based_tester/parser/dc_spec.rb +33 -0
  75. data/lib/origen_testers/igxl_based_tester/parser/dc_specs.rb +48 -0
  76. data/lib/origen_testers/igxl_based_tester/parser/descriptions.rb +339 -0
  77. data/lib/origen_testers/igxl_based_tester/parser/flow.rb +109 -0
  78. data/lib/origen_testers/igxl_based_tester/parser/flow_line.rb +203 -0
  79. data/lib/origen_testers/igxl_based_tester/parser/flows.rb +21 -0
  80. data/lib/origen_testers/igxl_based_tester/parser/pattern_set.rb +92 -0
  81. data/lib/origen_testers/igxl_based_tester/parser/pattern_sets.rb +31 -0
  82. data/lib/origen_testers/igxl_based_tester/parser/test_instance.rb +341 -0
  83. data/lib/origen_testers/igxl_based_tester/parser/test_instances.rb +24 -0
  84. data/lib/origen_testers/igxl_based_tester/parser/timeset.rb +13 -0
  85. data/lib/origen_testers/igxl_based_tester/parser/timesets.rb +0 -0
  86. data/lib/origen_testers/igxl_based_tester/ultraflex.rb +477 -0
  87. data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +10 -0
  88. data/lib/origen_testers/igxl_based_tester/ultraflex/flow_line.rb +19 -0
  89. data/lib/origen_testers/igxl_based_tester/ultraflex/generator.rb +19 -0
  90. data/lib/origen_testers/igxl_based_tester/ultraflex/patgroup.rb +9 -0
  91. data/lib/origen_testers/igxl_based_tester/ultraflex/patgroups.rb +10 -0
  92. data/lib/origen_testers/igxl_based_tester/ultraflex/patset.rb +9 -0
  93. data/lib/origen_testers/igxl_based_tester/ultraflex/patset_pattern.rb +18 -0
  94. data/lib/origen_testers/igxl_based_tester/ultraflex/patsets.rb +10 -0
  95. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr.rb +9 -0
  96. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr_pattern.rb +18 -0
  97. data/lib/origen_testers/igxl_based_tester/ultraflex/patsubrs.rb +10 -0
  98. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/flow.txt.erb +9 -0
  99. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/instances.txt.erb +16 -0
  100. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patgroups.txt.erb +9 -0
  101. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patsets.txt.erb +10 -0
  102. data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patsubrs.txt.erb +10 -0
  103. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance.rb +270 -0
  104. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance_group.rb +9 -0
  105. data/lib/origen_testers/igxl_based_tester/ultraflex/test_instances.rb +10 -0
  106. data/lib/origen_testers/interface.rb +183 -0
  107. data/lib/origen_testers/parser.rb +22 -0
  108. data/lib/origen_testers/parser/description_lookup.rb +62 -0
  109. data/lib/origen_testers/parser/searchable_array.rb +30 -0
  110. data/lib/origen_testers/parser/searchable_hash.rb +30 -0
  111. data/lib/origen_testers/pattern_compilers.rb +116 -0
  112. data/lib/origen_testers/pattern_compilers/assembler.rb +88 -0
  113. data/lib/origen_testers/pattern_compilers/job.rb +96 -0
  114. data/lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb +599 -0
  115. data/lib/origen_testers/program_generators.rb +55 -0
  116. data/lib/origen_testers/smartest_based_tester.rb +8 -0
  117. data/lib/origen_testers/smartest_based_tester/base.rb +411 -0
  118. data/lib/origen_testers/smartest_based_tester/base/flow.rb +188 -0
  119. data/lib/origen_testers/smartest_based_tester/base/flow_node.rb +476 -0
  120. data/lib/origen_testers/smartest_based_tester/base/generator.rb +123 -0
  121. data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +23 -0
  122. data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +47 -0
  123. data/lib/origen_testers/smartest_based_tester/base/test_method.rb +143 -0
  124. data/lib/origen_testers/smartest_based_tester/base/test_methods.rb +73 -0
  125. data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +33 -0
  126. data/lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb +38 -0
  127. data/lib/origen_testers/smartest_based_tester/base/test_methods/custom_tml.rb +19 -0
  128. data/lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb +147 -0
  129. data/lib/origen_testers/smartest_based_tester/base/test_methods/limits.rb +43 -0
  130. data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +166 -0
  131. data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +58 -0
  132. data/lib/origen_testers/smartest_based_tester/v93k.rb +8 -0
  133. data/lib/origen_testers/smartest_based_tester/v93k/builder.rb +89 -0
  134. data/lib/origen_testers/smartest_based_tester/v93k/builder/flow.rb +169 -0
  135. data/lib/origen_testers/smartest_based_tester/v93k/builder/pattern_master.rb +54 -0
  136. data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +10 -0
  137. data/lib/origen_testers/smartest_based_tester/v93k/flow_node.rb +9 -0
  138. data/lib/origen_testers/smartest_based_tester/v93k/generator.rb +19 -0
  139. data/lib/origen_testers/smartest_based_tester/v93k/pattern_compiler.rb +10 -0
  140. data/lib/origen_testers/smartest_based_tester/v93k/pattern_master.rb +10 -0
  141. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.aiv.erb +17 -0
  142. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.flow.erb +201 -0
  143. data/lib/origen_testers/smartest_based_tester/v93k/templates/template.pmfl.erb +13 -0
  144. data/lib/origen_testers/smartest_based_tester/v93k/test_method.rb +9 -0
  145. data/lib/origen_testers/smartest_based_tester/v93k/test_methods.rb +9 -0
  146. data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +9 -0
  147. data/lib/origen_testers/smartest_based_tester/v93k/test_suites.rb +9 -0
  148. data/lib/origen_testers/test/basic_interface.rb +17 -0
  149. data/lib/origen_testers/test/block.rb +21 -0
  150. data/lib/origen_testers/test/dut.rb +184 -0
  151. data/lib/origen_testers/test/dut2.rb +76 -0
  152. data/lib/origen_testers/test/j750_base_interface.rb +119 -0
  153. data/lib/origen_testers/test/j750_hpt_interface.rb +8 -0
  154. data/lib/origen_testers/test/j750_interface.rb +8 -0
  155. data/lib/origen_testers/test/nvm.rb +94 -0
  156. data/lib/origen_testers/test/ultraflex_interface.rb +110 -0
  157. data/lib/origen_testers/test/v93k_interface.rb +115 -0
  158. data/lib/origen_testers/timing.rb +362 -0
  159. data/lib/origen_testers/vector.rb +203 -0
  160. data/lib/origen_testers/vector_based_tester.rb +42 -0
  161. data/lib/origen_testers/vector_generator.rb +623 -0
  162. data/lib/origen_testers/vector_pipeline.rb +288 -0
  163. data/pattern/dc_instr.rb +7 -0
  164. data/pattern/delay.rb +7 -0
  165. data/pattern/mem_test.rb +8 -0
  166. data/pattern/multi_vector.rb +117 -0
  167. data/pattern/multi_vector_plus1.rb +125 -0
  168. data/pattern/nvm/j750/add_late_pins.rb +3 -0
  169. data/pattern/nvm/j750/iterator_postfix_test_x_bx.rb +8 -0
  170. data/pattern/nvm/j750/iterator_test_x_bx.rb +8 -0
  171. data/pattern/nvm/j750/j750_halt.rb +159 -0
  172. data/pattern/nvm/j750/j750_workout.rb +202 -0
  173. data/pattern/nvm/j750/timing.rb +73 -0
  174. data/pattern/nvm/v93k/v93k_workout.rb +136 -0
  175. data/pattern/read_write_reg.rb +58 -0
  176. data/pattern/reset.rb +4 -0
  177. data/pattern/subroutines.rb +38 -0
  178. data/program/_additional_erase.rb +7 -0
  179. data/program/_efa_resources.rb +7 -0
  180. data/program/_erase.rb +25 -0
  181. data/program/_erase_vfy.rb +5 -0
  182. data/program/_iv_resources.rb +10 -0
  183. data/program/basic_interface.rb +5 -0
  184. data/program/components/_prb2_main.rb +6 -0
  185. data/program/flow_control.rb +164 -0
  186. data/program/prb1.rb +226 -0
  187. data/program/prb1_resources.rb +28 -0
  188. data/program/prb2.rb +40 -0
  189. data/program/test.rb +20 -0
  190. data/templates/example.txt.erb +53 -0
  191. data/templates/j750/_vt_flow.txt.erb +8 -0
  192. data/templates/j750/_vt_instances.txt.erb +4 -0
  193. data/templates/j750/program_sheet.txt.erb +9 -0
  194. data/templates/manifest/v93k.yaml.erb +22 -0
  195. data/templates/web/index.md.erb +51 -0
  196. data/templates/web/layouts/_basic.html.erb +15 -0
  197. data/templates/web/partials/_navbar.html.erb +22 -0
  198. data/templates/web/release_notes.md.erb +5 -0
  199. metadata +332 -0
@@ -0,0 +1,105 @@
1
+ module OrigenTesters
2
+ # Including this module in a class will create a basic test program interface that
3
+ # can generate programs for all ATE platforms supported by the Testers plugin.
4
+ #
5
+ # It provides a number of methods that can be called from a test program flow file
6
+ # to do basic things like a functional test.
7
+ #
8
+ # @example How to setup and use
9
+ # # lib/myapp/program_interface.rb
10
+ # module MyApp
11
+ # class Interface
12
+ # include OrigenTesters::BasicTestSetups
13
+ # end
14
+ # end
15
+ #
16
+ # # program/prb1.rb
17
+ # Flow.create interface: 'MyApp::Interface' do
18
+ #
19
+ # functional :my_pattern_1, bin: 10
20
+ # functional :my_pattern_2, bin: 11
21
+ #
22
+ # end
23
+ module BasicTestSetups
24
+ include OrigenTesters::ProgramGenerators
25
+
26
+ # Execute a functional test
27
+ #
28
+ # @param [Symbol, String] name the name of the test.
29
+ # @param [Hash] options the options to customize the test.
30
+ # @option options [Integer] :bin The bin number
31
+ # @option options [Integer] :sbin The soft bin number
32
+ # @option options [String] :pattern The pattern name, if not specified the test
33
+ # name will be used
34
+ # @option options [String] :pin_levels ('Lvl') The name of the pin levels
35
+ # @option options [String] :time_set ('Tim') The name of the time set
36
+ #
37
+ # @see http://origen.freescale.net/origen/latest/guides/program/flowapi/ The options associated with the flow control API are fully supported
38
+ #
39
+ # @example Customizing a test from the flow
40
+ # functional :erase, pattern: 'erase_all_nosrc', sbin: 150
41
+ #
42
+ # @example Applying global customization from the interface
43
+ # include OrigenTesters::BasicTestSetups
44
+ #
45
+ # def functional(name, options = {})
46
+ # # Apply custom defaults before calling
47
+ # options = {
48
+ # bin: 3,
49
+ # levels: 'nvm',
50
+ # }.merge(options)
51
+ # # Now call the generator
52
+ # super
53
+ # end
54
+ #
55
+ # @return [Hash] all generated components of the test will be returned. The key
56
+ # naming will depend on what platform the test has been generated for, but for
57
+ # example this will contain :flow_line, :test_instance and :patset objects in
58
+ # the case of an IG-XL-based platform.
59
+ #
60
+ # @example Adding a custom interpose function for J750
61
+ # include OrigenTesters::BasicTestSetups
62
+ #
63
+ # # Override the default J750 test instance to add an interpose function
64
+ # def functional(name, options = {})
65
+ # components = super
66
+ # if tester.j750?
67
+ # components[:test_instance].post_test_func = 'delayedBinning'
68
+ # end
69
+ # end
70
+ def functional(name, options = {})
71
+ options = {
72
+ pin_levels: 'Lvl',
73
+ time_set: 'Tim'
74
+ }.merge(options)
75
+ pattern = extract_pattern(name, options)
76
+ if tester.j750? || tester.j750_hpt? || tester.ultraflex?
77
+ ins = test_instances.functional(name, options)
78
+ pname = "#{pattern}_pset"
79
+ pset = patsets.add(pname, [{ pattern: "#{pattern}.PAT" }])
80
+ ins.pattern = pname
81
+ line = flow.test(ins, options)
82
+ { test_instance: ins, flow_line: line, patset: pset }
83
+ elsif tester.v93k?
84
+ tm = test_methods.ac_tml.ac_test.functional_test
85
+ ts = test_suites.run(name, options)
86
+ ts.test_method = tm
87
+ ts.pattern = pattern
88
+ node = flow.test(ts, options)
89
+ { test_method: tm, test_suite: ts, node: node }
90
+ else
91
+ fail "Unsupported tester: #{tester.class}"
92
+ end
93
+ end
94
+
95
+ # Extract the pattern name from the given options, falling back to the given
96
+ # test name if a :pattern option is not present.
97
+ #
98
+ # It will also strip any extension if one is present.
99
+ def extract_pattern(name, options = {})
100
+ p = options[:pattern] || name
101
+ p = p.to_s.sub(/\..*$/, '')
102
+ p
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,58 @@
1
+ module OrigenTesters
2
+ class CallbackHandlers
3
+ include Origen::PersistentCallbacks
4
+
5
+ # Snoop the pattern path that was just created and then compile it
6
+ # if the compiler was passed on the command line
7
+ def pattern_generated(path_to_generated_pattern)
8
+ current_compiler = select_compiler
9
+ run_compiler(current_compiler, path_to_generated_pattern)
10
+ end
11
+
12
+ # Listen for a pattern with .atp or .atp.gz extension. If found then compile the fileand kill the 'origen g' command
13
+ def before_pattern_lookup(requested_pattern)
14
+ path = Pathname.new(requested_pattern)
15
+ patname = path.basename
16
+ dir = path.dirname
17
+ if patname.to_s.match(/.atp/)
18
+ if patname.extname == '.atp' || patname.extname == '.gz'
19
+ # Found a .atp or .atp.gz file so we should compile it
20
+ matches = Dir.glob("#{Origen.root}/**/#{patname}")
21
+ fail "Found multiple locations for #{patname}, exiting...\n\t#{matches}" if matches.size > 1
22
+ pattern = matches.first.to_s
23
+ current_compiler = select_compiler
24
+ run_compiler(current_compiler, pattern)
25
+ $compile = true
26
+ end
27
+ # Return false so the Origen generate command stops
28
+ return false
29
+ end
30
+ true
31
+ end
32
+ # Instantiate an instance of this class immediately when this file is required, this object will
33
+ # then listen for the remainder of the Origen thread
34
+ CallbackHandlers.new
35
+
36
+ private
37
+
38
+ def select_compiler
39
+ current_compiler = nil
40
+ if $compiler == :use_app_default
41
+ current_compiler = $dut.compiler
42
+ fail "DUT compiler '#{current_compiler}' is not instantiated" if $dut.pattern_compilers[current_compiler].nil?
43
+ elsif $compiler.is_a? Symbol
44
+ current_compiler = $compiler
45
+ fail "Command line compiler '#{current_compiler}' is not instantiated" if $dut.pattern_compilers[current_compiler].nil?
46
+ end
47
+ current_compiler
48
+ end
49
+
50
+ def run_compiler(current_compiler, pattern)
51
+ unless current_compiler.nil?
52
+ debug "Compiling pattern #{pattern} with compiler '#{current_compiler}'..."
53
+ $dut.pattern_compilers[current_compiler].find_jobs(pattern)
54
+ $dut.pattern_compilers[current_compiler].run
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,279 @@
1
+ require 'active_support/concern'
2
+ require 'erb'
3
+ require 'yaml'
4
+
5
+ module OrigenTesters
6
+ # This module should be included in all test program component generators and provides the required
7
+ # integration with the Flow.create and Resources.create methods
8
+ module Generator
9
+ autoload :Placeholder, 'origen_testers/generator/placeholder'
10
+ autoload :IdentityMap, 'origen_testers/generator/identity_map'
11
+ autoload :FlowControlAPI, 'origen_testers/generator/flow_control_api'
12
+
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ include Origen::Generator::Comparator
17
+ end
18
+
19
+ # The program source files are executed by eval to allow the tester to filter the
20
+ # source contents before executing. For examples the doc tester replaces all comments
21
+ # with a method call containing each comment so that they can be captured.
22
+ def self.execute_source(file)
23
+ if Origen.interface.respond_to?(:filter_source)
24
+ File.open(file) do |f|
25
+ src = f.read
26
+ src = Origen.interface.filter_source(src)
27
+ eval(src, global_binding)
28
+ end
29
+ else
30
+ load file
31
+ end
32
+ end
33
+
34
+ # When called on a generator no output files will be created from it
35
+ def inhibit_output
36
+ @inhibit_output = true
37
+ end
38
+
39
+ # Returns true if the output files from this generator will be inhibited
40
+ def output_inhibited?
41
+ @inhibit_output
42
+ end
43
+
44
+ # Expands and inserts all render statements that have been encountered
45
+ def close(options = {})
46
+ Origen.profile "closing #{filename}" do
47
+ base_collection = collection
48
+ base_collection.each_with_index do |item, i|
49
+ if item.is_a? Placeholder
50
+ if item.type == :render
51
+ txt = ''
52
+ Origen.file_handler.preserve_current_file do
53
+ Origen.file_handler.default_extension = file_extension
54
+ placeholder = compiler.render(item.file, item.options)
55
+ txt = compiler.insert(placeholder).chomp
56
+ end
57
+ base_collection[i] = txt
58
+ else
59
+ fail 'Unknown placeholder encountered!'
60
+ end
61
+ end
62
+ end
63
+ @collection = base_collection.flatten.compact
64
+ on_close(options)
65
+ end
66
+ end
67
+
68
+ def file_pipeline
69
+ @@file_pipeline ||= []
70
+ end
71
+
72
+ # Returns the directory of the current source file being generated
73
+ def current_dir
74
+ if file_pipeline.empty?
75
+ Origen.file_handler.base_directory
76
+ else
77
+ Pathname.new(file_pipeline.last).dirname
78
+ end
79
+ end
80
+
81
+ # Redefine this in the parent which includes this module if you want anything to
82
+ # occur after closing the generator (expanding all render/import statements) but
83
+ # before writing to a file.
84
+ def on_close(options = {})
85
+ end
86
+
87
+ # Redefine this in the parent which includes this module if you want anything to
88
+ # occur after all tests have been generated but before file writing starts.
89
+ def finalize(options = {})
90
+ end
91
+
92
+ def compiler
93
+ Origen.generator.compiler
94
+ end
95
+
96
+ def filename=(name)
97
+ @filename = name
98
+ end
99
+
100
+ def filename(options = {})
101
+ options = {
102
+ include_extension: true
103
+ }.merge(options)
104
+ name = (@filename || Origen.file_handler.current_file.basename('.rb')).to_s
105
+ if Origen.config.program_prefix
106
+ unless name =~ /^#{Origen.config.program_prefix}/i
107
+ name = "#{Origen.config.program_prefix}_#{name}"
108
+ end
109
+ end
110
+ f = Pathname.new(name).basename
111
+ ext = f.extname.empty? ? file_extension : f.extname
112
+ body = f.basename(".#{ext}").to_s
113
+ body.gsub!('_resources', '')
114
+ if defined? self.class::OUTPUT_POSTFIX
115
+ # Unless the postfix is already in the name
116
+ unless body =~ /#{self.class::OUTPUT_POSTFIX}$/i
117
+ body = "#{body}_#{self.class::OUTPUT_POSTFIX}"
118
+ end
119
+ end
120
+ ext = ".#{ext}" unless ext =~ /^\./
121
+ if options[:include_extension]
122
+ "#{body}#{ext}"
123
+ else
124
+ "#{body}"
125
+ end
126
+ end
127
+
128
+ def dont_diff=(val)
129
+ @dont_diff = val
130
+ end
131
+
132
+ # All generators must implement a collection method that returns an
133
+ # array containing the generated items
134
+ def collection
135
+ @collection ||= []
136
+ end
137
+
138
+ def collection=(array)
139
+ @collection = array
140
+ end
141
+
142
+ def file_extension
143
+ if defined? self.class::OUTPUT_EXTENSION
144
+ self.class::OUTPUT_EXTENSION
145
+ elsif defined? self.class::TEMPLATE
146
+ p = Pathname.new(self.class::TEMPLATE)
147
+ ext = p.basename('.erb').extname
148
+ ext.empty? ? 'txt' : ext
149
+ else
150
+ 'txt'
151
+ end
152
+ end
153
+
154
+ def write_to_file(options = {})
155
+ c = caller[0]
156
+ unless output_inhibited?
157
+ if defined? self.class::TEMPLATE || Origen.tester.is_a?(Origen::Tester::Doc)
158
+ write_from_template(options)
159
+ else
160
+ fail "Don't know hot to write without a template!"
161
+ end
162
+ stats.completed_files += 1
163
+ end
164
+ end
165
+
166
+ def write_from_template(options = {})
167
+ options = {
168
+ quiet: false,
169
+ skip_diff: false
170
+ }.merge(options)
171
+ unless output_inhibited?
172
+ # If this is not the first time we have written to the current output file
173
+ # then append to it, otherwise clear it and start from scratch.
174
+ # The use of a class variable to store the opened files means that it will be
175
+ # shared by all generators in this run.
176
+ @@opened_files ||= []
177
+ if @@opened_files.include?(output_file) && !Origen.tester.is_a?(Origen::Tester::Doc)
178
+ @append = true
179
+ Origen.file_handler.preserve_state do
180
+ File.open(output_file, 'a') do |out|
181
+ content = compiler.insert(ERB.new(File.read(self.class::TEMPLATE), 0, Origen.config.erb_trim_mode).result(binding))
182
+ out.puts content unless content.empty?
183
+ end
184
+ end
185
+ Origen.log.info "Appending... #{output_file.basename}" unless options[:quiet]
186
+ else
187
+ @append = false
188
+ Origen.file_handler.preserve_state do
189
+ if Origen.tester.is_a?(Origen::Tester::Doc)
190
+ if options[:return_model]
191
+ Origen::Tester::Doc.model.add_flow(filename(include_extension: false), to_yaml)
192
+ else
193
+ Origen.file_handler.open_for_write(output_file) do |f|
194
+ f.puts YAML.dump(to_yaml(include_descriptions: false))
195
+ end
196
+ end
197
+ else
198
+ File.open(output_file, 'w') do |out|
199
+ out.puts compiler.insert(ERB.new(File.read(self.class::TEMPLATE), 0, Origen.config.erb_trim_mode).result(binding))
200
+ end
201
+ end
202
+ end
203
+ @@opened_files << output_file
204
+ Origen.log.info "Writing... #{output_file.basename}" unless options[:quiet]
205
+ end
206
+ if !@dont_diff && !options[:skip_diff] && !options[:quiet]
207
+ check_for_changes(output_file, reference_file,
208
+ compile_job: true,
209
+ comment_char: Origen.app.tester.program_comment_char)
210
+ end
211
+ end
212
+ end
213
+
214
+ def output_file
215
+ if respond_to? :subdirectory
216
+ p = Pathname.new("#{Origen.file_handler.output_directory}/#{subdirectory}/#{filename}")
217
+ FileUtils.mkdir_p p.dirname.to_s unless p.dirname.exist?
218
+ p
219
+ else
220
+ Pathname.new("#{Origen.file_handler.output_directory}/#{filename}")
221
+ end
222
+ end
223
+
224
+ def reference_file
225
+ Pathname.new("#{Origen.file_handler.reference_directory}/#{filename}")
226
+ end
227
+
228
+ def import(file, options = {})
229
+ file = Pathname.new(file).absolute? ? file : "#{current_dir}/#{file}"
230
+ file = Origen.file_handler.clean_path_to_sub_program(file)
231
+ base_collection = collection
232
+ @collection = []
233
+ Origen.generator.option_pipeline << options
234
+ file_pipeline << file
235
+ ::OrigenTesters::Generator.execute_source(file)
236
+ file_pipeline.pop
237
+ base_collection << @collection
238
+ @collection = base_collection.flatten
239
+ end
240
+
241
+ def render(file, options = {})
242
+ if options.delete(:_inline)
243
+ super Origen.file_handler.clean_path_to_sub_template(file), options
244
+ else
245
+ collection << Placeholder.new(:render, file, options)
246
+ end
247
+ end
248
+
249
+ def stats
250
+ Origen.app.stats
251
+ end
252
+
253
+ def to_be_written?
254
+ true
255
+ end
256
+
257
+ def set_flow_description(desc)
258
+ Origen.interface.descriptions.add_for_flow(output_file, desc)
259
+ end
260
+
261
+ def identity_map # :nodoc:
262
+ Origen.interface.identity_map
263
+ end
264
+
265
+ def platform
266
+ Origen.interface.platform
267
+ end
268
+
269
+ module ClassMethods
270
+ def new(*args, &block) # :nodoc:
271
+ options = (args.last && args.last.is_a?(Hash)) ? args.last : {}
272
+ x = allocate
273
+ x.send(:initialize, *args, &block)
274
+ Origen.interface.sheet_generators << x unless options[:manually_register]
275
+ x
276
+ end
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,611 @@
1
+ module OrigenTesters
2
+ module Generator
3
+ module FlowControlAPI
4
+ # Flow control methods related to flow context
5
+ FLOW_METHODS = [
6
+ # Methods in arrays are aliases, the primary name is the first one
7
+ [:if_enable, :if_enabled, :enable, :enabled],
8
+ [:unless_enable, :unless_enabled],
9
+ [:if_job, :if_jobs],
10
+ [:unless_job, :unless_jobs]
11
+ ]
12
+
13
+ # Flow control methods related to a relationship with another test
14
+ RELATION_METHODS = [
15
+ # Methods in arrays are aliases, the primary name is the first one
16
+ :if_ran,
17
+ :unless_ran,
18
+ [:if_failed, :unless_passed],
19
+ [:if_passed, :unless_failed],
20
+ [:if_any_passed, :unless_all_failed],
21
+ [:if_all_passed, :unless_any_failed],
22
+ [:if_any_failed, :unless_all_passed],
23
+ [:if_all_failed, :unless_any_passed]
24
+ ]
25
+
26
+ # Returns true if the test context generated from the supplied options + existing context
27
+ # wrappers is different from that which was applied to the previous test.
28
+ def context_changed?(options = {})
29
+ current_context[:hash_code] != summarize_context(options)[:hash_code]
30
+ end
31
+
32
+ # @api private
33
+ def save_context(options = {})
34
+ # If the test has requested to use the current context...
35
+ if options[:context] == :current
36
+ replace_context_with_current(options)
37
+ else
38
+ @current_context = summarize_context(options)
39
+ options.merge(@current_context[:context])
40
+ end
41
+ end
42
+
43
+ # Returns a hash representing the current context, that is the context that was applied
44
+ # to the last test.
45
+ #
46
+ # The hash contains two items:
47
+ #
48
+ # * :context contains a hash that summarises the flow control options that have been
49
+ # used, for example it may contain something like: :if_enable => "data_collection"
50
+ # * :hash_code returns a hash-code for the values contained in the :context arrary. Any
51
+ # two equivalent contexts will have the same :hash_code, therefore this can be used
52
+ # to easily check the equivalence of any two contexts.
53
+ def current_context
54
+ @current_context ||= save_context
55
+ end
56
+
57
+ # @api private
58
+ #
59
+ # Removes any context options from the given options hash and merges in the current
60
+ # context
61
+ def replace_context_with_current(options)
62
+ options = options.merge({})
63
+ [FLOW_METHODS, RELATION_METHODS].flatten.each do |m|
64
+ options.delete(m)
65
+ end
66
+ options.merge(current_context[:context])
67
+ end
68
+
69
+ # Returns a hash like that returned by current_context based on the given set of options +
70
+ # existing context wrappers.
71
+ def summarize_context(options = {})
72
+ code = []
73
+ context = {}
74
+ (FLOW_METHODS + RELATION_METHODS).each do |m|
75
+ primary = m.is_a?(Array) ? m.first : m
76
+ val = false
77
+ [m].flatten.each do |m|
78
+ if options[m]
79
+ val = options[m]
80
+ elsif instance_variable_get("@#{m}_block")
81
+ val = instance_variable_get("@#{m}_block")
82
+ end
83
+ end
84
+ if val
85
+ code << primary
86
+ code << val
87
+ context[primary] = val
88
+ end
89
+ end
90
+ { hash_code: code.flatten.hash, context: context }
91
+ end
92
+
93
+ # All tests generated within the given block will be assigned the given enable word.
94
+ #
95
+ # If a test encountered within the block already has another enable word assigned to it then
96
+ # an error will be raised.
97
+ def if_enable(word, options = {})
98
+ @if_enable_block = word
99
+ yield word
100
+ @if_enable_block = nil
101
+ end
102
+ alias_method :if_enabled, :if_enable
103
+
104
+ # All tests generated will not run unless the given enable word is asserted.
105
+ def unless_enable(word, options = {})
106
+ @unless_enable_block = word unless options[:or]
107
+ yield word
108
+ @unless_enable_block = nil
109
+ end
110
+ alias_method :unless_enabled, :unless_enable
111
+
112
+ # All tests generated within the given block will be enabled only for the given jobs.
113
+ def if_job(*jobs)
114
+ jobs = jobs.flatten
115
+ @if_job_block = @if_job_block ? @if_job_block + jobs : jobs
116
+ yield
117
+ @if_job_block = nil
118
+ end
119
+ alias_method :if_jobs, :if_job
120
+
121
+ # All tests generated within the given block will be enabled only for the given jobs.
122
+ def unless_job(*jobs)
123
+ jobs = jobs.flatten
124
+ @unless_job_block = @unless_job_block ? @unless_job_block + jobs : jobs
125
+ yield
126
+ @unless_job_block = nil
127
+ end
128
+ alias_method :unless_jobs, :unless_job
129
+
130
+ # All tests generated within the given block will only run if the given test id has also
131
+ # run earlier in the flow
132
+ def if_ran(test_id, options = {})
133
+ test_id = Origen.interface.filter_id(test_id, options)
134
+ return if options.key?(:if) && !options[:if]
135
+ return if options.key?(:unless) && options[:unless]
136
+ if @if_ran_block
137
+ fail 'Sorry but nesting of if_ran is not currently supported!'
138
+ end
139
+ @if_ran_block = test_id
140
+ yield
141
+ @if_ran_block = nil
142
+ end
143
+
144
+ # All tests generated within the given block will only run if the given test id has not
145
+ # run earlier in the flow
146
+ def unless_ran(test_id, options = {})
147
+ test_id = Origen.interface.filter_id(test_id, options)
148
+ return if options.key?(:if) && !options[:if]
149
+ return if options.key?(:unless) && options[:unless]
150
+ if @unless_ran_block
151
+ fail 'Sorry but nesting of unless_ran is not currently supported!'
152
+ end
153
+ @unless_ran_block = test_id
154
+ yield
155
+ @unless_ran_block = nil
156
+ end
157
+
158
+ # All tests generated within the given block will only run if the given test id has
159
+ # failed earlier in the flow
160
+ def if_failed(test_id, options = {})
161
+ test_id = Origen.interface.filter_id(test_id, options)
162
+ return if options.key?(:if) && !options[:if]
163
+ return if options.key?(:unless) && options[:unless]
164
+ if @if_failed_block
165
+ fail 'Sorry but nesting of if_failed is not currently supported!'
166
+ end
167
+ @if_failed_block = test_id
168
+ yield
169
+ @if_failed_block = nil
170
+ end
171
+ alias_method :unless_passed, :if_failed
172
+
173
+ # All tests generated within the given block will only run if the given test id has
174
+ # passed earlier in the flow
175
+ def if_passed(test_id, options = {})
176
+ test_id = Origen.interface.filter_id(test_id, options)
177
+ return if options.key?(:if) && !options[:if]
178
+ return if options.key?(:unless) && options[:unless]
179
+ if @if_passed_block
180
+ fail 'Sorry but nesting of if_passed is not currently supported!'
181
+ end
182
+ @if_passed_block = test_id
183
+ yield
184
+ @if_passed_block = nil
185
+ end
186
+ alias_method :unless_failed, :if_passed
187
+
188
+ # All tests generated within the given block will only run if the given test id has
189
+ # passed ON ANY SITE earlier in the flow
190
+ def if_any_passed(test_id, options = {})
191
+ test_id = Origen.interface.filter_id(test_id, options)
192
+ return if conditionally_deactivated?(options)
193
+ if @if_any_passed_block
194
+ fail 'Sorry but nesting of if_any_passed is not currently supported!'
195
+ end
196
+ @if_any_passed_block = test_id
197
+ yield
198
+ @if_any_passed_block = nil
199
+ end
200
+ alias_method :unless_all_failed, :if_any_passed
201
+
202
+ # All tests generated within the given block will only run if the given test id has
203
+ # passed ON ALL SITES earlier in the flow
204
+ def if_all_passed(test_id, options = {})
205
+ test_id = Origen.interface.filter_id(test_id, options)
206
+ return if conditionally_deactivated?(options)
207
+ if @if_all_passed_block
208
+ fail 'Sorry but nesting of if_all_passed is not currently supported!'
209
+ end
210
+ @if_all_passed_block = test_id
211
+ yield
212
+ @if_all_passed_block = nil
213
+ end
214
+ alias_method :unless_any_failed, :if_all_passed
215
+
216
+ # All tests generated within the given block will only run if the given test id has
217
+ # failed ON ANY SITE earlier in the flow
218
+ def if_any_failed(test_id, options = {})
219
+ test_id = Origen.interface.filter_id(test_id, options)
220
+ return if conditionally_deactivated?(options)
221
+ if @if_any_failed_block
222
+ fail 'Sorry but nesting of if_any_failed is not currently supported!'
223
+ end
224
+ @if_any_failed_block = test_id
225
+ yield
226
+ @if_any_failed_block = nil
227
+ end
228
+ alias_method :unless_all_passed, :if_any_failed
229
+
230
+ # All tests generated within the given block will only run if the given test id has
231
+ # failed ON ALL SITES earlier in the flow
232
+ def if_all_failed(test_id, options = {})
233
+ test_id = Origen.interface.filter_id(test_id, options)
234
+ return if conditionally_deactivated?(options)
235
+ if @if_all_failed_block
236
+ fail 'Sorry but nesting of if_all_failed is not currently supported!'
237
+ end
238
+ @if_all_failed_block = test_id
239
+ yield
240
+ @if_all_failed_block = nil
241
+ end
242
+ alias_method :unless_any_passed, :if_all_failed
243
+
244
+ def conditionally_deactivated?(options)
245
+ (options.key?(:if) && !options[:if]) ||
246
+ (options.key?(:unless) && options[:unless])
247
+ end
248
+
249
+ def find_by_id(id, options = {}) # :nodoc:
250
+ options = {
251
+ search_other_flows: true
252
+ }.merge(options)
253
+ # Look within the current flow for a match first
254
+ t = identity_map[id.to_sym]
255
+ return t if t
256
+ # If no match then look across other flow modules for a match
257
+ # This currently returns the first match, should it raise an error on multiple?
258
+ if options[:search_other_flows]
259
+ Origen.interface.flow_generators.any? do |flow|
260
+ t = flow.find_by_id(id, search_other_flows: false)
261
+ end
262
+ end
263
+ t
264
+ end
265
+
266
+ def identity_map # :nodoc:
267
+ @identity_map ||= {}
268
+ end
269
+
270
+ # If a class that includes this module has a finalize method it must
271
+ # call apply_relationships
272
+ def finalize(options = {}) # :nodoc:
273
+ apply_relationships
274
+ reset_globals
275
+ end
276
+
277
+ def apply_relationships # :nodoc:
278
+ if @relationships
279
+ @relationships.each do |rel|
280
+ t = find_by_id(rel[:target_id])
281
+ fail "Test not found with ID: #{rel[:target_id]}, referenced in flow: #{filename}" unless t
282
+ t.id = rel[:target_id]
283
+ confirm_valid_context(t, rel[:dependent])
284
+ case rel[:type]
285
+ # The first cases here contain J750 logic, these should be replaced
286
+ # with the call method style used for the later cases when time permits.
287
+ when :failed
288
+ if rel[:dependent].respond_to?(:run_if_failed)
289
+ rel[:dependent].run_if_failed(rel[:target_id])
290
+ else
291
+ t.continue_on_fail
292
+ flag = t.set_flag_on_fail
293
+ rel[:dependent].flag_true = flag
294
+ end
295
+ when :passed
296
+ if rel[:dependent].respond_to?(:run_if_passed)
297
+ rel[:dependent].run_if_passed(rel[:target_id])
298
+ else
299
+ t.continue_on_fail
300
+ flag = t.set_flag_on_pass
301
+ rel[:dependent].flag_true = flag
302
+ end
303
+ when :if_ran, :unless_ran
304
+ if rel[:type] == :if_ran
305
+ if rel[:dependent].respond_to?(:run_if_ran)
306
+ rel[:dependent].run_if_ran(rel[:target_id])
307
+ else
308
+ # t.continue_on_fail
309
+ flag = t.set_flag_on_ran
310
+ rel[:dependent].flag_true = flag
311
+ end
312
+ else
313
+ if rel[:dependent].respond_to?(:run_unless_ran)
314
+ rel[:dependent].run_unless_ran(rel[:target_id])
315
+ else
316
+ # t.continue_on_fail
317
+ flag = t.set_flag_on_ran
318
+ rel[:dependent].flag_clear = flag
319
+ end
320
+ end
321
+ when :any_passed
322
+ rel[:dependent].run_if_any_passed(t)
323
+ when :all_passed
324
+ rel[:dependent].run_if_all_passed(t)
325
+ when :any_failed
326
+ rel[:dependent].run_if_any_failed(t)
327
+ when :all_failed
328
+ rel[:dependent].run_if_all_failed(t)
329
+ else
330
+ fail 'Unknown relationship type!'
331
+ end
332
+ end
333
+ @relationships = nil
334
+ end
335
+ end
336
+
337
+ def confirm_valid_context(test, dependent) # :nodoc:
338
+ # TODO: Add some validation checks here, for example make sure the dependent
339
+ # executes in the same job(s) as the test, otherwise the dependent will
340
+ # never be hit and will cause a validation error.
341
+ end
342
+
343
+ def record_id(test, options = {})
344
+ if options[:id]
345
+ @@existing_ids ||= []
346
+ if @@existing_ids.include?(options[:id].to_sym)
347
+ fail "The ID '#{test.id}' is not unique, it has already been assigned!"
348
+ else
349
+ @@existing_ids << options[:id].to_sym
350
+ end
351
+ identity_map[options[:id].to_sym] = test
352
+ end
353
+ end
354
+
355
+ # @api private
356
+ def at_run_start
357
+ @@existing_ids = nil
358
+ @@labels = nil
359
+ end
360
+ alias_method :reset_globals, :at_run_start
361
+
362
+ def replace_relationship_dependent(old_node, new_node)
363
+ @relationships.each do |rel|
364
+ rel[:dependent] = new_node if rel[:dependent] == old_node
365
+ end
366
+ end
367
+
368
+ # As generation of render and imports is not linear its possible that the test being
369
+ # referenced does not exist in the collection yet.
370
+ # Therefore the required relationship will be recorded for now and applied later upon
371
+ # closing the generator at which point the complete final collection will be available.
372
+ #
373
+ # Note - as of v2.0.1.dev64 the above is no longer true - imports are generated linearly.
374
+ # Therefore parent test should always already exist and it is possible that this relationship
375
+ # handling could be cleaned up considerably.
376
+ #
377
+ # However we should keep it around for now as it may come in useful when other tester
378
+ # platforms are supported in the future.
379
+ def track_relationships(test_options = {}) # :nodoc:
380
+ [:id, RELATION_METHODS].flatten.each do |id|
381
+ if test_options[id]
382
+ test_options[id] = Origen.interface.filter_id(test_options[id], test_options)
383
+ end
384
+ end
385
+ options = extract_relation_options!(test_options)
386
+ current_test = yield test_options
387
+ record_id(current_test, test_options)
388
+ @relationships ||= []
389
+ target_id = options[:if_failed] || options[:unless_passed] || @if_failed_block
390
+ if target_id
391
+ @relationships << {
392
+ type: :failed,
393
+ target_id: target_id,
394
+ dependent: current_test
395
+ }
396
+ end
397
+ target_id = options[:if_passed] || options[:unless_failed] || @if_passed_block
398
+ if target_id
399
+ @relationships << {
400
+ type: :passed,
401
+ target_id: target_id,
402
+ dependent: current_test
403
+ }
404
+ end
405
+ target_id = options.delete(:if_ran) || @if_ran_block
406
+ if target_id
407
+ @relationships << {
408
+ type: :if_ran,
409
+ target_id: target_id,
410
+ dependent: current_test
411
+ }
412
+ end
413
+ target_id = options.delete(:unless_ran) || @unless_ran_block
414
+ if target_id
415
+ @relationships << {
416
+ type: :unless_ran,
417
+ target_id: target_id,
418
+ dependent: current_test
419
+ }
420
+ end
421
+ target_id = options[:if_any_passed] || options[:unless_all_failed] || @if_any_passed_block
422
+ if target_id
423
+ @relationships << {
424
+ type: :any_passed,
425
+ target_id: target_id,
426
+ dependent: current_test
427
+ }
428
+ end
429
+ target_id = options[:if_all_passed] || options[:unless_any_failed] || @if_all_passed_block
430
+ if target_id
431
+ @relationships << {
432
+ type: :all_passed,
433
+ target_id: target_id,
434
+ dependent: current_test
435
+ }
436
+ end
437
+ target_id = options[:if_any_failed] || options[:unless_all_passed] || @if_any_failed_block
438
+ if target_id
439
+ @relationships << {
440
+ type: :any_failed,
441
+ target_id: target_id,
442
+ dependent: current_test
443
+ }
444
+ end
445
+ target_id = options[:if_all_failed] || options[:unless_any_passed] || @if_all_failed_block
446
+ if target_id
447
+ @relationships << {
448
+ type: :all_failed,
449
+ target_id: target_id,
450
+ dependent: current_test
451
+ }
452
+ end
453
+ if test_options[:context] == :current # Context has already been applied
454
+ current_test
455
+ else
456
+ apply_current_context!(current_test)
457
+ end
458
+ end
459
+
460
+ def apply_current_context!(line) # :nodoc:
461
+ if @if_enable_block
462
+ if line.enable && line.enable != @if_enable_block
463
+ fail "Cannot apply enable word '#{@if_enable_block}' to '#{line.parameter}', it already has '#{line.enable}'"
464
+ else
465
+ line.enable = @if_enable_block
466
+ end
467
+ end
468
+ if @unless_enable_block
469
+ line.unless_enable = @unless_enable_block
470
+ end
471
+ line.if_job = @if_job_block if @if_job_block
472
+ line.unless_job = @unless_job_block if @unless_job_block
473
+ line
474
+ end
475
+
476
+ # Removes any flow relationship options from given hash and returns them
477
+ # in a new hash
478
+ def extract_relation_options!(options) # :nodoc:
479
+ opts = {}
480
+ RELATION_METHODS.flatten.each do |o|
481
+ opts[o] = options.delete(o)
482
+ end
483
+ opts
484
+ end
485
+
486
+ def extract_flow_control_options!(options)
487
+ opts = {}
488
+ FLOW_METHODS.flatten.each do |o|
489
+ if options.key?(o)
490
+ opts[o] = options.delete(o)
491
+ end
492
+ end
493
+ opts
494
+ end
495
+
496
+ def generate_unique_label(id = nil)
497
+ id = 'label' if !id || id == ''
498
+ label = "#{Origen.interface.app_identifier}_#{id}"
499
+ label.gsub!(' ', '_')
500
+ label.upcase!
501
+ @@labels ||= {}
502
+ @@labels[Origen.tester.class] ||= {}
503
+ @@labels[Origen.tester.class][label] ||= 0
504
+ @@labels[Origen.tester.class][label] += 1
505
+ "#{label}_#{@@labels[Origen.tester.class][label]}"
506
+ end
507
+
508
+ module Interface
509
+ # Implement this method in your application interface if you want to
510
+ # sanitize all ID references used in the flow control API.
511
+ # For example you could use this to append a flow name prefix to every
512
+ # ID reference within a flow which can help with ID duplication problems
513
+ # when flow snippets are re-used.
514
+ def filter_id(id, options = {})
515
+ id
516
+ end
517
+
518
+ def extract_relation_options!(*args)
519
+ flow.extract_relation_options!(*args)
520
+ end
521
+
522
+ def extract_flow_control_options!(*args)
523
+ flow.extract_flow_control_options!(*args)
524
+ end
525
+
526
+ # Alias for flow#if_enable
527
+ def if_enable(*args, &block)
528
+ flow.if_enable(*args, &block)
529
+ end
530
+ alias_method :if_enabled, :if_enable
531
+
532
+ # Alias for flow#unless_enable
533
+ def unless_enable(*args, &block)
534
+ flow.unless_enable(*args, &block)
535
+ end
536
+ alias_method :unless_enabled, :unless_enable
537
+
538
+ # Alias for flow#if_job
539
+ def if_job(*args, &block)
540
+ flow.if_job(*args, &block)
541
+ end
542
+
543
+ # Alias for flow#unless_job
544
+ def unless_job(*args, &block)
545
+ flow.unless_job(*args, &block)
546
+ end
547
+
548
+ # Alias for flow#unless_ran
549
+ def unless_ran(*args, &block)
550
+ flow.unless_ran(*args, &block)
551
+ end
552
+
553
+ # Alias for flow#if_ran
554
+ def if_ran(*args, &block)
555
+ flow.if_ran(*args, &block)
556
+ end
557
+
558
+ # Alias for flow#if_failed
559
+ def if_failed(*args, &block)
560
+ flow.if_failed(*args, &block)
561
+ end
562
+ alias_method :unless_passed, :if_failed
563
+
564
+ # Alias for flow#if_passed
565
+ def if_passed(*args, &block)
566
+ flow.if_passed(*args, &block)
567
+ end
568
+ alias_method :unless_failed, :if_passed
569
+
570
+ # Alias for flow#if_any_passed
571
+ def if_any_passed(*args, &block)
572
+ flow.if_any_passed(*args, &block)
573
+ end
574
+ alias_method :unless_all_failed, :if_any_passed
575
+
576
+ # Alias for flow#if_all_passed
577
+ def if_all_passed(*args, &block)
578
+ flow.if_all_passed(*args, &block)
579
+ end
580
+ alias_method :unless_any_failed, :if_all_passed
581
+
582
+ # Alias for flow#if_any_failed
583
+ def if_any_failed(*args, &block)
584
+ flow.if_any_failed(*args, &block)
585
+ end
586
+ alias_method :unless_all_passed, :if_any_failed
587
+
588
+ # Alias for flow#if_all_failed
589
+ def if_all_failed(*args, &block)
590
+ flow.if_all_failed(*args, &block)
591
+ end
592
+ alias_method :unless_any_passed, :if_all_failed
593
+
594
+ # Alias for flow#skip
595
+ def skip(*args, &block)
596
+ flow.skip(*args, &block)
597
+ end
598
+
599
+ # Alias for flow#current_context
600
+ def current_context(*args, &block)
601
+ flow.current_context(*args, &block)
602
+ end
603
+
604
+ # Alias for flow#context_changed?
605
+ def context_changed?(*args, &block)
606
+ flow.context_changed?(*args, &block)
607
+ end
608
+ end
609
+ end
610
+ end
611
+ end