1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
7 class PipelineInstancesControllerTest < ActionController::TestCase
8 include PipelineInstancesHelper
10 def create_instance_long_enough_to(instance_attrs={})
11 # create 'two_part' pipeline with the given instance attributes
12 pt_fixture = api_fixture('pipeline_templates')['two_part']
13 post :create, params: {
14 pipeline_instance: instance_attrs.merge({
15 pipeline_template_uuid: pt_fixture['uuid']
18 }, session: session_for(:active)
19 assert_response :success
20 pi_uuid = assigns(:object).uuid
21 assert_not_nil assigns(:object)
24 yield pi_uuid, pt_fixture
26 # delete the pipeline instance
28 PipelineInstance.where(uuid: pi_uuid).first.destroy
31 test "can render pipeline instance with tagged collections" do
32 # Make sure to pass in a tagged collection to test that part of the rendering behavior.
34 params: {id: api_fixture("pipeline_instances")["pipeline_with_tagged_collection_input"]["uuid"]},
35 session: session_for(:active))
36 assert_response :success
39 test "update script_parameters one at a time using merge param" do
40 template_fixture = api_fixture('pipeline_templates')['two_part']
41 post :update, params: {
42 id: api_fixture("pipeline_instances")["pipeline_to_merge_params"]["uuid"],
59 }, session: session_for(:active)
60 assert_response :success
61 assert_not_nil assigns(:object)
62 orig_params = template_fixture['components']['part-two']['script_parameters']
63 new_params = assigns(:object).components[:'part-two'][:script_parameters]
64 orig_params.keys.each do |k|
65 unless %w(integer_with_value plain_string).index(k)
66 assert_equal orig_params[k].to_json, new_params[k.to_sym].to_json
71 test "component rendering copes with unexpected components format" do
73 params: {id: api_fixture("pipeline_instances")["components_is_jobspec"]["uuid"]},
74 session: session_for(:active))
75 assert_response :success
78 test "dates in JSON components are parsed" do
80 params: {id: api_fixture('pipeline_instances')['has_component_with_completed_jobs']['uuid']},
81 session: session_for(:active))
82 assert_response :success
83 assert_not_nil assigns(:object)
84 assert_not_nil assigns(:object).components[:foo][:job]
85 start_at = assigns(:object).components[:foo][:job][:started_at]
86 start_at = Time.parse(start_at) if (start_at.andand.class == String)
87 assert start_at.is_a? Time
88 finished_at = assigns(:object).components[:foo][:job][:started_at]
89 finished_at = Time.parse(finished_at) if (finished_at.andand.class == String)
90 assert finished_at.is_a? Time
93 # The next two tests ensure that a pipeline instance can be copied
94 # when the template has components that do not exist in the
95 # instance (ticket #4000).
97 test "generate graph" do
101 pipeline_for_graph = {
103 uuid: 'zzzzz-d1hrv-9fm8l10i9z2kqc9',
108 script_version: 'master',
109 job: {uuid: 'zzzzz-8i9sb-graphstage10000'},
110 output_uuid: 'zzzzz-4zz18-bv31uwvy3neko22'
115 script_version: 'master',
117 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45'
119 job: {uuid: 'zzzzz-8i9sb-graphstage20000'},
120 output_uuid: 'zzzzz-4zz18-uukreo9rbgwsujx'
125 @controller.params['tab_pane'] = "Graph"
126 provenance, pips = @controller.graph([pipeline_for_graph])
128 graph_test_collection1 = find_fixture Collection, "graph_test_collection1"
129 stage1 = find_fixture Job, "graph_stage1"
130 stage2 = find_fixture Job, "graph_stage2"
132 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage1',
133 'component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage2',
138 pipeline_for_graph[:components][:stage1][:output_uuid],
139 pipeline_for_graph[:components][:stage2][:output_uuid]
142 assert_not_nil provenance[k], "Expected key #{k} in provenance set"
143 assert_equal 1, pips[k], "Expected key #{k} in pips set" if !k.start_with? "component_"
146 prov_svg = ProvenanceHelper::create_provenance_graph provenance, "provenance_svg", {
147 :request => RequestDuck,
148 :all_script_parameters => true,
149 :combine_jobs => :script_and_version,
151 :only_components => true }
153 stage1_id = "#{stage1[:script]}_#{stage1[:script_version]}_#{Digest::MD5.hexdigest(stage1[:script_parameters].to_json)}"
154 stage2_id = "#{stage2[:script]}_#{stage2[:script_version]}_#{Digest::MD5.hexdigest(stage2[:script_parameters].to_json)}"
156 stage1_out = stage1[:output].gsub('+','\\\+')
158 assert_match /#{stage1_id}->#{stage1_out}/, prov_svg
160 assert_match /#{stage1_out}->#{stage2_id}/, prov_svg
164 test "generate graph compare" do
168 pipeline_for_graph1 = {
170 uuid: 'zzzzz-d1hrv-9fm8l10i9z2kqc9',
175 script_version: 'master',
176 job: {uuid: 'zzzzz-8i9sb-graphstage10000'},
177 output_uuid: 'zzzzz-4zz18-bv31uwvy3neko22'
182 script_version: 'master',
184 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45'
186 job: {uuid: 'zzzzz-8i9sb-graphstage20000'},
187 output_uuid: 'zzzzz-4zz18-uukreo9rbgwsujx'
192 pipeline_for_graph2 = {
194 uuid: 'zzzzz-d1hrv-9fm8l10i9z2kqc0',
199 script_version: 'master',
200 job: {uuid: 'zzzzz-8i9sb-graphstage10000'},
201 output_uuid: 'zzzzz-4zz18-bv31uwvy3neko22'
206 script_version: 'master',
209 job: {uuid: 'zzzzz-8i9sb-graphstage30000'},
210 output_uuid: 'zzzzz-4zz18-uukreo9rbgwsujj'
215 @controller.params['tab_pane'] = "Graph"
216 provenance, pips = @controller.graph([pipeline_for_graph1, pipeline_for_graph2])
218 collection1 = find_fixture Collection, "graph_test_collection1"
220 stage1 = find_fixture Job, "graph_stage1"
221 stage2 = find_fixture Job, "graph_stage2"
222 stage3 = find_fixture Job, "graph_stage3"
224 [['component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage1', nil],
225 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc9_stage2', nil],
226 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc0_stage1', nil],
227 ['component_zzzzz-d1hrv-9fm8l10i9z2kqc0_stage2', nil],
234 [pipeline_for_graph1[:components][:stage1][:output_uuid], 3],
235 [pipeline_for_graph1[:components][:stage2][:output_uuid], 1],
236 [pipeline_for_graph2[:components][:stage2][:output_uuid], 2]
238 assert_not_nil provenance[k[0]], "Expected key #{k[0]} in provenance set"
239 assert_equal k[1], pips[k[0]], "Expected key #{k} in pips" if !k[0].start_with? "component_"
242 prov_svg = ProvenanceHelper::create_provenance_graph provenance, "provenance_svg", {
243 :request => RequestDuck,
244 :all_script_parameters => true,
245 :combine_jobs => :script_and_version,
247 :only_components => true }
249 collection1_id = collection1.portable_data_hash.gsub('+','\\\+')
251 stage2_id = "#{stage2[:script]}_#{stage2[:script_version]}_#{Digest::MD5.hexdigest(stage2[:script_parameters].to_json)}"
252 stage3_id = "#{stage3[:script]}_#{stage3[:script_version]}_#{Digest::MD5.hexdigest(stage3[:script_parameters].to_json)}"
254 stage2_out = stage2[:output].gsub('+','\\\+')
255 stage3_out = stage3[:output].gsub('+','\\\+')
257 assert_match /#{collection1_id}->#{stage2_id}/, prov_svg
258 assert_match /#{collection1_id}->#{stage3_id}/, prov_svg
260 assert_match /#{stage2_id}->#{stage2_out}/, prov_svg
261 assert_match /#{stage3_id}->#{stage3_out}/, prov_svg