3 class PipelineInstancesControllerTest < ActionController::TestCase
4 include PipelineInstancesHelper
6 def create_instance_long_enough_to(instance_attrs={})
7 # create 'two_part' pipeline with the given instance attributes
8 pt_fixture = api_fixture('pipeline_templates')['two_part']
10 pipeline_instance: instance_attrs.merge({
11 pipeline_template_uuid: pt_fixture['uuid']
14 }, session_for(:active)
15 assert_response :success
16 pi_uuid = assigns(:object).uuid
17 assert_not_nil assigns(:object)
20 yield pi_uuid, pt_fixture
22 # delete the pipeline instance
24 PipelineInstance.where(uuid: pi_uuid).first.destroy
27 test "pipeline instance components populated after create" do
28 create_instance_long_enough_to do |new_instance_uuid, template_fixture|
29 assert_equal(template_fixture['components'].to_json,
30 assigns(:object).components.to_json)
34 test "can render pipeline instance with tagged collections" do
35 # Make sure to pass in a tagged collection to test that part of the rendering behavior.
37 {id: api_fixture("pipeline_instances")["pipeline_with_tagged_collection_input"]["uuid"]},
39 assert_response :success
42 test "update script_parameters one at a time using merge param" do
43 template_fixture = api_fixture('pipeline_templates')['two_part']
45 id: api_fixture("pipeline_instances")["pipeline_to_merge_params"]["uuid"],
62 }, session_for(:active)
63 assert_response :success
64 assert_not_nil assigns(:object)
65 orig_params = template_fixture['components']['part-two']['script_parameters']
66 new_params = assigns(:object).components[:'part-two'][:script_parameters]
67 orig_params.keys.each do |k|
68 unless %w(integer_with_value plain_string).index(k)
69 assert_equal orig_params[k].to_json, new_params[k.to_sym].to_json
74 test "component rendering copes with unexpected components format" do
76 {id: api_fixture("pipeline_instances")["components_is_jobspec"]["uuid"]},
78 assert_response :success
81 test "dates in JSON components are parsed" do
83 {id: api_fixture('pipeline_instances')['has_component_with_completed_jobs']['uuid']},
85 assert_response :success
86 assert_not_nil assigns(:object)
87 assert_not_nil assigns(:object).components[:foo][:job]
88 assert assigns(:object).components[:foo][:job][:started_at].is_a? Time
89 assert assigns(:object).components[:foo][:job][:finished_at].is_a? Time
92 # The next two tests ensure that a pipeline instance can be copied
93 # when the template has components that do not exist in the
94 # instance (ticket #4000).
96 test "copy pipeline instance with components=use_latest" do
99 id: api_fixture('pipeline_instances')['pipeline_with_newer_template']['uuid'],
100 components: 'use_latest',
101 script: 'use_latest',
103 state: 'RunningOnServer'
106 session_for(:active))
108 assert_not_nil assigns(:object)
110 # Component 'foo' has script parameters only in the pipeline instance.
111 # Component 'bar' is present only in the pipeline_template.
112 # Test that the copied pipeline instance includes parameters for
113 # component 'foo' from the source instance, and parameters for
114 # component 'bar' from the source template.
116 assert_not_nil assigns(:object).components[:foo]
117 foo = assigns(:object).components[:foo]
118 assert_not_nil foo[:script_parameters]
119 assert_not_nil foo[:script_parameters][:input]
120 assert_equal 'foo instance input', foo[:script_parameters][:input][:title]
122 assert_not_nil assigns(:object).components[:bar]
123 bar = assigns(:object).components[:bar]
124 assert_not_nil bar[:script_parameters]
125 assert_not_nil bar[:script_parameters][:input]
126 assert_equal 'bar template input', bar[:script_parameters][:input][:title]
129 test "copy pipeline instance on newer template works with script=use_same" do
132 id: api_fixture('pipeline_instances')['pipeline_with_newer_template']['uuid'],
133 components: 'use_latest',
136 state: 'RunningOnServer'
139 session_for(:active))
141 assert_not_nil assigns(:object)
143 # Test that relevant component parameters were copied from both
144 # the source instance and source template, respectively (see
147 assert_not_nil assigns(:object).components[:foo]
148 foo = assigns(:object).components[:foo]
149 assert_not_nil foo[:script_parameters]
150 assert_not_nil foo[:script_parameters][:input]
151 assert_equal 'foo instance input', foo[:script_parameters][:input][:title]
153 assert_not_nil assigns(:object).components[:bar]
154 bar = assigns(:object).components[:bar]
155 assert_not_nil bar[:script_parameters]
156 assert_not_nil bar[:script_parameters][:input]
157 assert_equal 'bar template input', bar[:script_parameters][:input][:title]
160 test "generate graph" do
164 pipeline_for_graph = {
166 uuid: 'zzzzz-d1hrv-9fm8l10i9z2kqc9',
171 script_version: 'master',
172 job: {uuid: 'zzzzz-8i9sb-graphstage10000'},
173 output_uuid: 'zzzzz-4zz18-bv31uwvy3neko22'
178 script_version: 'master',
180 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45'
182 job: {uuid: 'zzzzz-8i9sb-graphstage20000'},
183 output_uuid: 'zzzzz-4zz18-uukreo9rbgwsujx'
188 @controller.params['tab_pane'] = "Graph"
189 provenance, pips = @controller.graph([pipeline_for_graph])
191 graph_test_collection1 = find_fixture Collection, "graph_test_collection1"
192 stage1 = find_fixture Job, "graph_stage1"
193 stage2 = find_fixture Job, "graph_stage2"
195 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage1',
196 'component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage2',
201 pipeline_for_graph[:components][:stage1][:output_uuid],
202 pipeline_for_graph[:components][:stage2][:output_uuid]
205 assert_not_nil provenance[k], "Expected key #{k} in provenance set"
206 assert_equal 1, pips[k], "Expected key #{k} in pips set" if !k.start_with? "component_"
209 prov_svg = ProvenanceHelper::create_provenance_graph provenance, "provenance_svg", {
210 :request => RequestDuck,
211 :all_script_parameters => true,
212 :combine_jobs => :script_and_version,
214 :only_components => true }
216 stage1_id = "#{stage1[:script]}_#{stage1[:script_version]}_#{Digest::MD5.hexdigest(stage1[:script_parameters].to_json)}"
217 stage2_id = "#{stage2[:script]}_#{stage2[:script_version]}_#{Digest::MD5.hexdigest(stage2[:script_parameters].to_json)}"
219 stage1_out = stage1[:output].gsub('+','\\\+')
221 assert_match /#{stage1_id}->#{stage1_out}/, prov_svg
223 assert_match /#{stage1_out}->#{stage2_id}/, prov_svg
227 test "generate graph compare" do
231 pipeline_for_graph1 = {
233 uuid: 'zzzzz-d1hrv-9fm8l10i9z2kqc9',
238 script_version: 'master',
239 job: {uuid: 'zzzzz-8i9sb-graphstage10000'},
240 output_uuid: 'zzzzz-4zz18-bv31uwvy3neko22'
245 script_version: 'master',
247 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45'
249 job: {uuid: 'zzzzz-8i9sb-graphstage20000'},
250 output_uuid: 'zzzzz-4zz18-uukreo9rbgwsujx'
255 pipeline_for_graph2 = {
257 uuid: 'zzzzz-d1hrv-9fm8l10i9z2kqc0',
262 script_version: 'master',
263 job: {uuid: 'zzzzz-8i9sb-graphstage10000'},
264 output_uuid: 'zzzzz-4zz18-bv31uwvy3neko22'
269 script_version: 'master',
272 job: {uuid: 'zzzzz-8i9sb-graphstage30000'},
273 output_uuid: 'zzzzz-4zz18-uukreo9rbgwsujj'
278 @controller.params['tab_pane'] = "Graph"
279 provenance, pips = @controller.graph([pipeline_for_graph1, pipeline_for_graph2])
281 collection1 = find_fixture Collection, "graph_test_collection1"
283 stage1 = find_fixture Job, "graph_stage1"
284 stage2 = find_fixture Job, "graph_stage2"
285 stage3 = find_fixture Job, "graph_stage3"
287 [['component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage1', nil],
288 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage2', nil],
289 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc0_stage1', nil],
290 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc0_stage2', nil],
297 [pipeline_for_graph1[:components][:stage1][:output_uuid], 3],
298 [pipeline_for_graph1[:components][:stage2][:output_uuid], 1],
299 [pipeline_for_graph2[:components][:stage2][:output_uuid], 2]
301 assert_not_nil provenance[k[0]], "Expected key #{k[0]} in provenance set"
302 assert_equal k[1], pips[k[0]], "Expected key #{k} in pips" if !k[0].start_with? "component_"
305 prov_svg = ProvenanceHelper::create_provenance_graph provenance, "provenance_svg", {
306 :request => RequestDuck,
307 :all_script_parameters => true,
308 :combine_jobs => :script_and_version,
310 :only_components => true }
312 collection1_id = collection1.portable_data_hash.gsub('+','\\\+')
314 stage2_id = "#{stage2[:script]}_#{stage2[:script_version]}_#{Digest::MD5.hexdigest(stage2[:script_parameters].to_json)}"
315 stage3_id = "#{stage3[:script]}_#{stage3[:script_version]}_#{Digest::MD5.hexdigest(stage3[:script_parameters].to_json)}"
317 stage2_out = stage2[:output].gsub('+','\\\+')
318 stage3_out = stage3[:output].gsub('+','\\\+')
320 assert_match /#{collection1_id}->#{stage2_id}/, prov_svg
321 assert_match /#{collection1_id}->#{stage3_id}/, prov_svg
323 assert_match /#{stage2_id}->#{stage2_out}/, prov_svg
324 assert_match /#{stage3_id}->#{stage3_out}/, prov_svg