3410: Merge branch 'master' into 3410-replication-attrs
[arvados.git] / services / api / test / functional / arvados / v1 / job_reuse_controller_test.rb
1 require 'test_helper'
2 require 'helpers/git_test_helper'
3
4 class Arvados::V1::JobReuseControllerTest < ActionController::TestCase
5   fixtures :repositories, :users, :jobs, :links, :collections
6
7   # See git_setup.rb for the commit log for test.git.tar
8   include GitTestHelper
9
10   setup do
11     @controller = Arvados::V1::JobsController.new
12     authorize_with :active
13   end
14
15   test "reuse job with no_reuse=false" do
16     post :create, job: {
17       no_reuse: false,
18       script: "hash",
19       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
20       repository: "foo",
21       script_parameters: {
22         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
23         an_integer: '1'
24       }
25     }
26     assert_response :success
27     assert_not_nil assigns(:object)
28     new_job = JSON.parse(@response.body)
29     assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
30     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
31   end
32
33   test "reuse job with find_or_create=true" do
34     post :create, {
35       job: {
36         script: "hash",
37         script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
38         repository: "foo",
39         script_parameters: {
40           input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
41           an_integer: '1'
42         }
43       },
44       find_or_create: true
45     }
46     assert_response :success
47     assert_not_nil assigns(:object)
48     new_job = JSON.parse(@response.body)
49     assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
50     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
51   end
52
53   test "reuse job with symbolic script_version" do
54     post :create, {
55       job: {
56         script: "hash",
57         script_version: "tag1",
58         repository: "foo",
59         script_parameters: {
60           input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
61           an_integer: '1'
62         }
63       },
64       find_or_create: true
65     }
66     assert_response :success
67     assert_not_nil assigns(:object)
68     new_job = JSON.parse(@response.body)
69     assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
70     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
71   end
72
73   test "do not reuse job because no_reuse=true" do
74     post :create, {
75       job: {
76         no_reuse: true,
77         script: "hash",
78         script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
79         repository: "foo",
80         script_parameters: {
81           input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
82           an_integer: '1'
83         }
84       }
85     }
86     assert_response :success
87     assert_not_nil assigns(:object)
88     new_job = JSON.parse(@response.body)
89     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
90     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
91   end
92
93   [false, "false"].each do |whichfalse|
94     test "do not reuse job because find_or_create=#{whichfalse.inspect}" do
95       post :create, {
96         job: {
97           script: "hash",
98           script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
99           repository: "foo",
100           script_parameters: {
101             input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
102             an_integer: '1'
103           }
104         },
105         find_or_create: whichfalse
106       }
107       assert_response :success
108       assert_not_nil assigns(:object)
109       new_job = JSON.parse(@response.body)
110       assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
111       assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
112     end
113   end
114
115   test "do not reuse job because output is not readable by user" do
116     authorize_with :job_reader
117     post :create, {
118       job: {
119         script: "hash",
120         script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
121         repository: "foo",
122         script_parameters: {
123           input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
124           an_integer: '1'
125         }
126       },
127       find_or_create: true
128     }
129     assert_response :success
130     assert_not_nil assigns(:object)
131     new_job = JSON.parse(@response.body)
132     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
133     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
134   end
135
136   test "test_cannot_reuse_job_no_output" do
137     post :create, job: {
138       no_reuse: false,
139       script: "hash",
140       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
141       repository: "foo",
142       script_parameters: {
143         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
144         an_integer: '2'
145       }
146     }
147     assert_response :success
148     assert_not_nil assigns(:object)
149     new_job = JSON.parse(@response.body)
150     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykppp', new_job['uuid']
151   end
152
153   test "test_reuse_job_range" do
154     post :create, job: {
155       no_reuse: false,
156       script: "hash",
157       minimum_script_version: "tag1",
158       script_version: "master",
159       repository: "foo",
160       script_parameters: {
161         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
162         an_integer: '1'
163       }
164     }
165     assert_response :success
166     assert_not_nil assigns(:object)
167     new_job = JSON.parse(@response.body)
168     assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
169     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
170   end
171
172   test "cannot_reuse_job_no_minimum_given_so_must_use_specified_commit" do
173     post :create, job: {
174       no_reuse: false,
175       script: "hash",
176       script_version: "master",
177       repository: "foo",
178       script_parameters: {
179         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
180         an_integer: '1'
181       }
182     }
183     assert_response :success
184     assert_not_nil assigns(:object)
185     new_job = JSON.parse(@response.body)
186     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
187     assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
188   end
189
190   test "test_cannot_reuse_job_different_input" do
191     post :create, job: {
192       no_reuse: false,
193       script: "hash",
194       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
195       repository: "foo",
196       script_parameters: {
197         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
198         an_integer: '2'
199       }
200     }
201     assert_response :success
202     assert_not_nil assigns(:object)
203     new_job = JSON.parse(@response.body)
204     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
205     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
206   end
207
208   test "test_cannot_reuse_job_different_version" do
209     post :create, job: {
210       no_reuse: false,
211       script: "hash",
212       script_version: "master",
213       repository: "foo",
214       script_parameters: {
215         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
216         an_integer: '2'
217       }
218     }
219     assert_response :success
220     assert_not_nil assigns(:object)
221     new_job = JSON.parse(@response.body)
222     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
223     assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
224   end
225
226   test "test_can_reuse_job_submitted_nondeterministic" do
227     post :create, job: {
228       no_reuse: false,
229       script: "hash",
230       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
231       repository: "foo",
232       script_parameters: {
233         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
234         an_integer: '1'
235       },
236       nondeterministic: true
237     }
238     assert_response :success
239     assert_not_nil assigns(:object)
240     new_job = JSON.parse(@response.body)
241     assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
242     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
243   end
244
245   test "test_cannot_reuse_job_past_nondeterministic" do
246     post :create, job: {
247       no_reuse: false,
248       script: "hash2",
249       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
250       repository: "foo",
251       script_parameters: {
252         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
253         an_integer: '1'
254       }
255     }
256     assert_response :success
257     assert_not_nil assigns(:object)
258     new_job = JSON.parse(@response.body)
259     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykyyy', new_job['uuid']
260     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
261   end
262
263   test "test_cannot_reuse_job_no_permission" do
264     authorize_with :spectator
265     post :create, job: {
266       no_reuse: false,
267       script: "hash",
268       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
269       repository: "foo",
270       script_parameters: {
271         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
272         an_integer: '1'
273       }
274     }
275     assert_response :success
276     assert_not_nil assigns(:object)
277     new_job = JSON.parse(@response.body)
278     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
279     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
280   end
281
282   test "test_cannot_reuse_job_excluded" do
283     post :create, job: {
284       no_reuse: false,
285       script: "hash",
286       minimum_script_version: "31ce37fe365b3dc204300a3e4c396ad333ed0556",
287       script_version: "master",
288       repository: "foo",
289       exclude_script_versions: ["tag1"],
290       script_parameters: {
291         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
292         an_integer: '1'
293       }
294     }
295     assert_response :success
296     assert_not_nil assigns(:object)
297     new_job = JSON.parse(@response.body)
298     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
299     assert_not_equal('4fe459abe02d9b365932b8f5dc419439ab4e2577',
300                      new_job['script_version'])
301   end
302
303   test "cannot reuse job with find_or_create but excluded version" do
304     post :create, {
305       job: {
306         script: "hash",
307         script_version: "master",
308         repository: "foo",
309         script_parameters: {
310           input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
311           an_integer: '1'
312         }
313       },
314       find_or_create: true,
315       minimum_script_version: "31ce37fe365b3dc204300a3e4c396ad333ed0556",
316       exclude_script_versions: ["tag1"],
317     }
318     assert_response :success
319     assert_not_nil assigns(:object)
320     new_job = JSON.parse(@response.body)
321     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
322     assert_not_equal('4fe459abe02d9b365932b8f5dc419439ab4e2577',
323                      new_job['script_version'])
324   end
325
326   BASE_FILTERS = {
327     'repository' => ['=', 'foo'],
328     'script' => ['=', 'hash'],
329     'script_version' => ['in git', 'master'],
330     'docker_image_locator' => ['=', nil],
331     'arvados_sdk_version' => ['=', nil],
332   }
333
334   def filters_from_hash(hash)
335     hash.each_pair.map { |name, filter| [name] + filter }
336   end
337
338   test "can reuse a Job based on filters" do
339     filters_hash = BASE_FILTERS.
340       merge('script_version' => ['in git', 'tag1'])
341     post(:create, {
342            job: {
343              script: "hash",
344              script_version: "master",
345              repository: "foo",
346              script_parameters: {
347                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
348                an_integer: '1'
349              }
350            },
351            filters: filters_from_hash(filters_hash),
352            find_or_create: true,
353          })
354     assert_response :success
355     assert_not_nil assigns(:object)
356     new_job = JSON.parse(@response.body)
357     assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
358     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
359   end
360
361   test "can not reuse a Job based on filters" do
362     filters = filters_from_hash(BASE_FILTERS
363                                   .reject { |k| k == 'script_version' })
364     filters += [["script_version", "in git",
365                  "31ce37fe365b3dc204300a3e4c396ad333ed0556"],
366                 ["script_version", "not in git", ["tag1"]]]
367     post(:create, {
368            job: {
369              script: "hash",
370              script_version: "master",
371              repository: "foo",
372              script_parameters: {
373                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
374                an_integer: '1'
375              }
376            },
377            filters: filters,
378            find_or_create: true,
379          })
380     assert_response :success
381     assert_not_nil assigns(:object)
382     new_job = JSON.parse(@response.body)
383     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
384     assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
385   end
386
387   test "can not reuse a Job based on arbitrary filters" do
388     filters_hash = BASE_FILTERS.
389       merge("created_at" => ["<", "2010-01-01T00:00:00Z"])
390     post(:create, {
391            job: {
392              script: "hash",
393              script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
394              repository: "foo",
395              script_parameters: {
396                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
397                an_integer: '1'
398              }
399            },
400            filters: filters_from_hash(filters_hash),
401            find_or_create: true,
402          })
403     assert_response :success
404     assert_not_nil assigns(:object)
405     new_job = JSON.parse(@response.body)
406     assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
407     assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
408   end
409
410   test "can reuse a Job with a Docker image" do
411     post(:create, {
412            job: {
413              script: "hash",
414              script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
415              repository: "foo",
416              script_parameters: {
417                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
418                an_integer: '1'
419              },
420              runtime_constraints: {
421                docker_image: 'arvados/apitestfixture',
422              }
423            },
424            find_or_create: true,
425          })
426     assert_response :success
427     new_job = assigns(:object)
428     assert_not_nil new_job
429     target_job = jobs(:previous_docker_job_run)
430     [:uuid, :script_version, :docker_image_locator].each do |attr|
431       assert_equal(target_job.send(attr), new_job.send(attr))
432     end
433   end
434
435   test "can reuse a Job with a Docker image hash filter" do
436     filters_hash = BASE_FILTERS.
437       merge("script_version" =>
438               ["=", "4fe459abe02d9b365932b8f5dc419439ab4e2577"],
439             "docker_image_locator" =>
440               ["in docker", links(:docker_image_collection_hash).name])
441     post(:create, {
442            job: {
443              script: "hash",
444              script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
445              repository: "foo",
446              script_parameters: {
447                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
448                an_integer: '1'
449              },
450            },
451            filters: filters_from_hash(filters_hash),
452            find_or_create: true,
453          })
454     assert_response :success
455     new_job = assigns(:object)
456     assert_not_nil new_job
457     target_job = jobs(:previous_docker_job_run)
458     [:uuid, :script_version, :docker_image_locator].each do |attr|
459       assert_equal(target_job.send(attr), new_job.send(attr))
460     end
461   end
462
463   test "reuse Job with Docker image repo+tag" do
464     filters_hash = BASE_FILTERS.
465       merge("script_version" =>
466               ["=", "4fe459abe02d9b365932b8f5dc419439ab4e2577"],
467             "docker_image_locator" =>
468               ["in docker", links(:docker_image_collection_tag2).name])
469     post(:create, {
470            job: {
471              script: "hash",
472              script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
473              repository: "foo",
474              script_parameters: {
475                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
476                an_integer: '1'
477              },
478            },
479            filters: filters_from_hash(filters_hash),
480            find_or_create: true,
481          })
482     assert_response :success
483     new_job = assigns(:object)
484     assert_not_nil new_job
485     target_job = jobs(:previous_docker_job_run)
486     [:uuid, :script_version, :docker_image_locator].each do |attr|
487       assert_equal(target_job.send(attr), new_job.send(attr))
488     end
489   end
490
491   test "new job with unknown Docker image filter" do
492     filters_hash = BASE_FILTERS.
493       merge("docker_image_locator" => ["in docker", "_nonesuchname_"])
494     post(:create, {
495            job: {
496              script: "hash",
497              script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
498              repository: "foo",
499              script_parameters: {
500                input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
501                an_integer: '1'
502              },
503            },
504            filters: filters_from_hash(filters_hash),
505            find_or_create: true,
506          })
507     assert_response :success
508     new_job = assigns(:object)
509     assert_not_nil new_job
510     assert_not_equal(jobs(:previous_docker_job_run).uuid, new_job.uuid)
511   end
512
513   ["repository", "script"].each do |skip_key|
514     test "missing #{skip_key} filter raises an error" do
515       filters = filters_from_hash(BASE_FILTERS.reject { |k| k == skip_key })
516       post(:create, {
517              job: {
518                script: "hash",
519                script_version: "master",
520                repository: "foo",
521                script_parameters: {
522                  input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
523                  an_integer: '1'
524                }
525              },
526              filters: filters,
527              find_or_create: true,
528            })
529       assert_includes(405..599, @response.code.to_i,
530                       "bad status code with missing #{skip_key} filter")
531     end
532   end
533
534   test "find Job with script version range" do
535     get :index, filters: [["repository", "=", "foo"],
536                           ["script", "=", "hash"],
537                           ["script_version", "in git", "tag1"]]
538     assert_response :success
539     assert_not_nil assigns(:objects)
540     assert_includes(assigns(:objects).map { |job| job.uuid },
541                     jobs(:previous_job_run).uuid)
542   end
543
544   test "find Job with script version range exclusions" do
545     get :index, filters: [["repository", "=", "foo"],
546                           ["script", "=", "hash"],
547                           ["script_version", "not in git", "tag1"]]
548     assert_response :success
549     assert_not_nil assigns(:objects)
550     refute_includes(assigns(:objects).map { |job| job.uuid },
551                     jobs(:previous_job_run).uuid)
552   end
553
554   test "find Job with Docker image range" do
555     get :index, filters: [["docker_image_locator", "in docker",
556                            "arvados/apitestfixture"]]
557     assert_response :success
558     assert_not_nil assigns(:objects)
559     assert_includes(assigns(:objects).map { |job| job.uuid },
560                     jobs(:previous_docker_job_run).uuid)
561     refute_includes(assigns(:objects).map { |job| job.uuid },
562                     jobs(:previous_job_run).uuid)
563   end
564
565   test "find Job with Docker image using reader tokens" do
566     authorize_with :inactive
567     get(:index, {
568           filters: [["docker_image_locator", "in docker",
569                      "arvados/apitestfixture"]],
570           reader_tokens: [api_token(:active)],
571         })
572     assert_response :success
573     assert_not_nil assigns(:objects)
574     assert_includes(assigns(:objects).map { |job| job.uuid },
575                     jobs(:previous_docker_job_run).uuid)
576     refute_includes(assigns(:objects).map { |job| job.uuid },
577                     jobs(:previous_job_run).uuid)
578   end
579
580   test "'in docker' filter accepts arrays" do
581     get :index, filters: [["docker_image_locator", "in docker",
582                            ["_nonesuchname_", "arvados/apitestfixture"]]]
583     assert_response :success
584     assert_not_nil assigns(:objects)
585     assert_includes(assigns(:objects).map { |job| job.uuid },
586                     jobs(:previous_docker_job_run).uuid)
587     refute_includes(assigns(:objects).map { |job| job.uuid },
588                     jobs(:previous_job_run).uuid)
589   end
590
591   test "'not in docker' filter accepts arrays" do
592     get :index, filters: [["docker_image_locator", "not in docker",
593                            ["_nonesuchname_", "arvados/apitestfixture"]]]
594     assert_response :success
595     assert_not_nil assigns(:objects)
596     assert_includes(assigns(:objects).map { |job| job.uuid },
597                     jobs(:previous_job_run).uuid)
598     refute_includes(assigns(:objects).map { |job| job.uuid },
599                     jobs(:previous_docker_job_run).uuid)
600   end
601
602   def create_foo_hash_job_params(params)
603     if not params.has_key?(:find_or_create)
604       params[:find_or_create] = true
605     end
606     job_attrs = params.delete(:job) || {}
607     params[:job] = {
608       script: "hash",
609       script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
610       repository: "foo",
611       script_parameters: {
612         input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
613         an_integer: '1',
614       },
615     }.merge(job_attrs)
616     params
617   end
618
619   def check_new_job_created_from(params)
620     start_time = Time.now
621     post(:create, create_foo_hash_job_params(params))
622     assert_response :success
623     new_job = assigns(:object)
624     assert_not_nil new_job
625     assert_operator(start_time, :<=, new_job.created_at)
626     new_job
627   end
628
629   def check_errors_from(params)
630     post(:create, create_foo_hash_job_params(params))
631     assert_includes(405..499, @response.code.to_i)
632     errors = json_response.fetch("errors", [])
633     assert(errors.any?, "no errors assigned from #{params}")
634     refute(errors.any? { |msg| msg =~ /^#<[A-Za-z]+: / },
635            "errors include raw exception")
636     errors
637   end
638
639   # 1de84a8 is on the b1 branch, after master's tip.
640   test "new job created from unsatisfiable minimum version filter" do
641     filters_hash = BASE_FILTERS.merge("script_version" => ["in git", "1de84a8"])
642     check_new_job_created_from(filters: filters_from_hash(filters_hash))
643   end
644
645   test "new job created from unsatisfiable minimum version parameter" do
646     check_new_job_created_from(minimum_script_version: "1de84a8")
647   end
648
649   test "new job created from unsatisfiable minimum version attribute" do
650     check_new_job_created_from(job: {minimum_script_version: "1de84a8"})
651   end
652
653   test "graceful error from nonexistent minimum version filter" do
654     filters_hash = BASE_FILTERS.merge("script_version" =>
655                                       ["in git", "__nosuchbranch__"])
656     errors = check_errors_from(filters: filters_from_hash(filters_hash))
657     assert(errors.any? { |msg| msg.include? "__nosuchbranch__" },
658            "bad refspec not mentioned in error message")
659   end
660
661   test "graceful error from nonexistent minimum version parameter" do
662     errors = check_errors_from(minimum_script_version: "__nosuchbranch__")
663     assert(errors.any? { |msg| msg.include? "__nosuchbranch__" },
664            "bad refspec not mentioned in error message")
665   end
666
667   test "graceful error from nonexistent minimum version attribute" do
668     errors = check_errors_from(job: {minimum_script_version: "__nosuchbranch__"})
669     assert(errors.any? { |msg| msg.include? "__nosuchbranch__" },
670            "bad refspec not mentioned in error message")
671   end
672
673   test "can't reuse job with older Arvados SDK version" do
674     params = {
675       script_version: "31ce37fe365b3dc204300a3e4c396ad333ed0556",
676       runtime_constraints: {
677         "arvados_sdk_version" => "master",
678         "docker_image" => links(:docker_image_collection_tag).name,
679       },
680     }
681     check_new_job_created_from(job: params)
682   end
683
684   test "reuse job from arvados_sdk_version git filters" do
685     filters_hash = BASE_FILTERS.
686       merge("arvados_sdk_version" => ["in git", "commit2"])
687     filters_hash.delete("script_version")
688     params = create_foo_hash_job_params(filters:
689                                         filters_from_hash(filters_hash))
690     post(:create, params)
691     assert_response :success
692     assert_equal(jobs(:previous_job_run_with_arvados_sdk_version).uuid,
693                  assigns(:object).uuid)
694   end
695
696   test "create new job because of arvados_sdk_version 'not in git' filters" do
697     filters_hash = BASE_FILTERS.reject { |k| k == "script_version" }
698     filters = filters_from_hash(filters_hash)
699     # Allow anything from the root commit, but before commit 2.
700     filters += [["arvados_sdk_version", "in git", "436637c8"],
701                 ["arvados_sdk_version", "not in git", "00634b2b"]]
702     check_new_job_created_from(filters: filters)
703   end
704 end