1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
6 require 'helpers/git_test_helper'
8 class Arvados::V1::JobReuseControllerTest < ActionController::TestCase
9 fixtures :repositories, :users, :jobs, :links, :collections
11 # See git_setup.rb for the commit log for test.git.tar
15 @controller = Arvados::V1::JobsController.new
16 authorize_with :active
19 test "reuse job with no_reuse=false" do
20 post :create, params: {
24 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
25 repository: "active/foo",
28 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45'
32 assert_response :success
33 assert_not_nil assigns(:object)
34 new_job = JSON.parse(@response.body)
35 assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
36 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
39 test "reuse job with find_or_create=true" do
40 post :create, params: {
43 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
44 repository: "active/foo",
46 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
52 assert_response :success
53 assert_not_nil assigns(:object)
54 new_job = JSON.parse(@response.body)
55 assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
56 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
59 test "no reuse job with null log" do
60 post :create, params: {
63 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
64 repository: "active/foo",
66 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
72 assert_response :success
73 assert_not_nil assigns(:object)
74 new_job = JSON.parse(@response.body)
75 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqq3', new_job['uuid']
76 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
79 test "reuse job with symbolic script_version" do
80 post :create, params: {
83 script_version: "tag1",
84 repository: "active/foo",
86 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
92 assert_response :success
93 assert_not_nil assigns(:object)
94 new_job = JSON.parse(@response.body)
95 assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
96 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
99 test "do not reuse job because no_reuse=true" do
100 post :create, params: {
104 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
105 repository: "active/foo",
107 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
112 assert_response :success
113 assert_not_nil assigns(:object)
114 new_job = JSON.parse(@response.body)
115 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
116 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
119 [false, "false"].each do |whichfalse|
120 test "do not reuse job because find_or_create=#{whichfalse.inspect}" do
121 post :create, params: {
124 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
125 repository: "active/foo",
127 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
131 find_or_create: whichfalse
133 assert_response :success
134 assert_not_nil assigns(:object)
135 new_job = JSON.parse(@response.body)
136 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
137 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
141 test "do not reuse job because output is not readable by user" do
142 authorize_with :job_reader
143 post :create, params: {
146 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
147 repository: "active/foo",
149 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
155 assert_response :success
156 assert_not_nil assigns(:object)
157 new_job = JSON.parse(@response.body)
158 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
159 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
162 test "test_cannot_reuse_job_no_output" do
163 post :create, params: {
167 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
168 repository: "active/foo",
170 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
175 assert_response :success
176 assert_not_nil assigns(:object)
177 new_job = JSON.parse(@response.body)
178 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykppp', new_job['uuid']
181 test "test_reuse_job_range" do
182 post :create, params: {
186 minimum_script_version: "tag1",
187 script_version: "master",
188 repository: "active/foo",
190 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
195 assert_response :success
196 assert_not_nil assigns(:object)
197 new_job = JSON.parse(@response.body)
198 assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
199 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
202 test "cannot_reuse_job_no_minimum_given_so_must_use_specified_commit" do
203 post :create, params: {
207 script_version: "master",
208 repository: "active/foo",
210 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
215 assert_response :success
216 assert_not_nil assigns(:object)
217 new_job = JSON.parse(@response.body)
218 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
219 assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
222 test "test_cannot_reuse_job_different_input" do
223 post :create, params: {
227 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
228 repository: "active/foo",
230 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
235 assert_response :success
236 assert_not_nil assigns(:object)
237 new_job = JSON.parse(@response.body)
238 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
239 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
242 test "test_cannot_reuse_job_different_version" do
243 post :create, params: {
247 script_version: "master",
248 repository: "active/foo",
250 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
255 assert_response :success
256 assert_not_nil assigns(:object)
257 new_job = JSON.parse(@response.body)
258 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
259 assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
262 test "test_can_reuse_job_submitted_nondeterministic" do
263 post :create, params: {
267 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
268 repository: "active/foo",
270 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
273 nondeterministic: true
276 assert_response :success
277 assert_not_nil assigns(:object)
278 new_job = JSON.parse(@response.body)
279 assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
280 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
283 test "test_cannot_reuse_job_past_nondeterministic" do
284 post :create, params: {
288 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
289 repository: "active/foo",
291 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
296 assert_response :success
297 assert_not_nil assigns(:object)
298 new_job = JSON.parse(@response.body)
299 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykyyy', new_job['uuid']
300 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
303 test "test_cannot_reuse_job_no_permission" do
304 authorize_with :spectator
305 post :create, params: {
309 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
310 repository: "active/foo",
312 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
317 assert_response :success
318 assert_not_nil assigns(:object)
319 new_job = JSON.parse(@response.body)
320 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
321 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
324 test "test_cannot_reuse_job_excluded" do
325 post :create, params: {
329 minimum_script_version: "31ce37fe365b3dc204300a3e4c396ad333ed0556",
330 script_version: "master",
331 repository: "active/foo",
332 exclude_script_versions: ["tag1"],
334 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
339 assert_response :success
340 assert_not_nil assigns(:object)
341 new_job = JSON.parse(@response.body)
342 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
343 assert_not_equal('4fe459abe02d9b365932b8f5dc419439ab4e2577',
344 new_job['script_version'])
347 test "cannot reuse job with find_or_create but excluded version" do
348 post :create, params: {
351 script_version: "master",
352 repository: "active/foo",
354 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
358 find_or_create: true,
359 minimum_script_version: "31ce37fe365b3dc204300a3e4c396ad333ed0556",
360 exclude_script_versions: ["tag1"],
362 assert_response :success
363 assert_not_nil assigns(:object)
364 new_job = JSON.parse(@response.body)
365 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
366 assert_not_equal('4fe459abe02d9b365932b8f5dc419439ab4e2577',
367 new_job['script_version'])
370 test "cannot reuse job when hash-like branch includes newer commit" do
371 check_new_job_created_from({job: {script_version: "738783"}},
372 :previous_job_run_superseded_by_hash_branch)
376 'repository' => ['=', 'active/foo'],
377 'script' => ['=', 'hash'],
378 'script_version' => ['in git', 'master'],
379 'docker_image_locator' => ['=', nil],
380 'arvados_sdk_version' => ['=', nil],
383 def filters_from_hash(hash)
384 hash.each_pair.map { |name, filter| [name] + filter }
387 test "can reuse a Job based on filters" do
388 filters_hash = BASE_FILTERS.
389 merge('script_version' => ['in git', 'tag1'])
390 post(:create, params: {
393 script_version: "master",
394 repository: "active/foo",
396 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
400 filters: filters_from_hash(filters_hash),
401 find_or_create: true,
403 assert_response :success
404 assert_not_nil assigns(:object)
405 new_job = JSON.parse(@response.body)
406 assert_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
407 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
410 test "can not reuse a Job based on filters" do
411 filters = filters_from_hash(BASE_FILTERS
412 .reject { |k| k == 'script_version' })
413 filters += [["script_version", "in git",
414 "31ce37fe365b3dc204300a3e4c396ad333ed0556"],
415 ["script_version", "not in git", ["tag1"]]]
416 post(:create, params: {
419 script_version: "master",
420 repository: "active/foo",
422 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
427 find_or_create: true,
429 assert_response :success
430 assert_not_nil assigns(:object)
431 new_job = JSON.parse(@response.body)
432 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
433 assert_equal '077ba2ad3ea24a929091a9e6ce545c93199b8e57', new_job['script_version']
436 test "can not reuse a Job based on arbitrary filters" do
437 filters_hash = BASE_FILTERS.
438 merge("created_at" => ["<", "2010-01-01T00:00:00Z"])
439 post(:create, params: {
442 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
443 repository: "active/foo",
445 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
449 filters: filters_from_hash(filters_hash),
450 find_or_create: true,
452 assert_response :success
453 assert_not_nil assigns(:object)
454 new_job = JSON.parse(@response.body)
455 assert_not_equal 'zzzzz-8i9sb-cjs4pklxxjykqqq', new_job['uuid']
456 assert_equal '4fe459abe02d9b365932b8f5dc419439ab4e2577', new_job['script_version']
459 test "can reuse a Job with a Docker image" do
460 post(:create, params: {
463 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
464 repository: "active/foo",
466 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
469 runtime_constraints: {
470 docker_image: 'arvados/apitestfixture',
473 find_or_create: true,
475 assert_response :success
476 new_job = assigns(:object)
477 assert_not_nil new_job
478 target_job = jobs(:previous_docker_job_run)
479 [:uuid, :script_version, :docker_image_locator].each do |attr|
480 assert_equal(target_job.send(attr), new_job.send(attr))
484 test "can reuse a Job with a Docker image hash filter" do
485 filters_hash = BASE_FILTERS.
486 merge("script_version" =>
487 ["=", "4fe459abe02d9b365932b8f5dc419439ab4e2577"],
488 "docker_image_locator" =>
489 ["in docker", links(:docker_image_collection_hash).name])
490 post(:create, params: {
493 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
494 repository: "active/foo",
496 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
500 filters: filters_from_hash(filters_hash),
501 find_or_create: true,
503 assert_response :success
504 new_job = assigns(:object)
505 assert_not_nil new_job
506 target_job = jobs(:previous_docker_job_run)
507 [:uuid, :script_version, :docker_image_locator].each do |attr|
508 assert_equal(target_job.send(attr), new_job.send(attr))
512 test "reuse Job with Docker image repo+tag" do
513 filters_hash = BASE_FILTERS.
514 merge("script_version" =>
515 ["=", "4fe459abe02d9b365932b8f5dc419439ab4e2577"],
516 "docker_image_locator" =>
517 ["in docker", links(:docker_image_collection_tag2).name])
518 post(:create, params: {
521 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
522 repository: "active/foo",
524 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
528 filters: filters_from_hash(filters_hash),
529 find_or_create: true,
531 assert_response :success
532 new_job = assigns(:object)
533 assert_not_nil new_job
534 target_job = jobs(:previous_docker_job_run)
535 [:uuid, :script_version, :docker_image_locator].each do |attr|
536 assert_equal(target_job.send(attr), new_job.send(attr))
540 test "new job with unknown Docker image filter" do
541 filters_hash = BASE_FILTERS.
542 merge("docker_image_locator" => ["in docker", "_nonesuchname_"])
543 post(:create, params: {
546 script_version: "4fe459abe02d9b365932b8f5dc419439ab4e2577",
547 repository: "active/foo",
549 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
553 filters: filters_from_hash(filters_hash),
554 find_or_create: true,
556 assert_response :success
557 new_job = assigns(:object)
558 assert_not_nil new_job
559 assert_not_equal(jobs(:previous_docker_job_run).uuid, new_job.uuid)
562 test "don't reuse job using older Docker image of same name" do
563 jobspec = {runtime_constraints: {
564 docker_image: "arvados/apitestfixture",
566 check_new_job_created_from({job: jobspec},
567 :previous_ancient_docker_image_job_run)
570 test "reuse job with Docker image that has hash name" do
571 jobspec = {runtime_constraints: {
572 docker_image: "a" * 64,
574 check_job_reused_from(jobspec, :previous_docker_job_run)
577 ["repository", "script"].each do |skip_key|
578 test "missing #{skip_key} filter raises an error" do
579 filters = filters_from_hash(BASE_FILTERS.reject { |k| k == skip_key })
580 post(:create, params: {
583 script_version: "master",
584 repository: "active/foo",
586 input: 'fa7aeb5140e2848d39b416daeef4ffc5+45',
591 find_or_create: true,
593 assert_includes(405..599, @response.code.to_i,
594 "bad status code with missing #{skip_key} filter")
598 test "find Job with script version range" do
599 get :index, params: {
600 filters: [["repository", "=", "active/foo"],
601 ["script", "=", "hash"],
602 ["script_version", "in git", "tag1"]]
604 assert_response :success
605 assert_not_nil assigns(:objects)
606 assert_includes(assigns(:objects).map { |job| job.uuid },
607 jobs(:previous_job_run).uuid)
610 test "find Job with script version range exclusions" do
611 get :index, params: {
612 filters: [["repository", "=", "active/foo"],
613 ["script", "=", "hash"],
614 ["script_version", "not in git", "tag1"]]
616 assert_response :success
617 assert_not_nil assigns(:objects)
618 refute_includes(assigns(:objects).map { |job| job.uuid },
619 jobs(:previous_job_run).uuid)
622 test "find Job with Docker image range" do
623 get :index, params: {
624 filters: [["docker_image_locator", "in docker",
625 "arvados/apitestfixture"]]
627 assert_response :success
628 assert_not_nil assigns(:objects)
629 assert_includes(assigns(:objects).map { |job| job.uuid },
630 jobs(:previous_docker_job_run).uuid)
631 refute_includes(assigns(:objects).map { |job| job.uuid },
632 jobs(:previous_job_run).uuid)
635 test "find Job with Docker image using reader tokens" do
636 authorize_with :inactive
637 get(:index, params: {
638 filters: [["docker_image_locator", "in docker",
639 "arvados/apitestfixture"]],
640 reader_tokens: [api_token(:active)],
642 assert_response :success
643 assert_not_nil assigns(:objects)
644 assert_includes(assigns(:objects).map { |job| job.uuid },
645 jobs(:previous_docker_job_run).uuid)
646 refute_includes(assigns(:objects).map { |job| job.uuid },
647 jobs(:previous_job_run).uuid)
650 test "'in docker' filter accepts arrays" do
651 get :index, params: {
652 filters: [["docker_image_locator", "in docker",
653 ["_nonesuchname_", "arvados/apitestfixture"]]]
655 assert_response :success
656 assert_not_nil assigns(:objects)
657 assert_includes(assigns(:objects).map { |job| job.uuid },
658 jobs(:previous_docker_job_run).uuid)
659 refute_includes(assigns(:objects).map { |job| job.uuid },
660 jobs(:previous_job_run).uuid)
663 test "'not in docker' filter accepts arrays" do
664 get :index, params: {
665 filters: [["docker_image_locator", "not in docker",
666 ["_nonesuchname_", "arvados/apitestfixture"]]]
668 assert_response :success
669 assert_not_nil assigns(:objects)
670 assert_includes(assigns(:objects).map { |job| job.uuid },
671 jobs(:previous_job_run).uuid)
672 refute_includes(assigns(:objects).map { |job| job.uuid },
673 jobs(:previous_docker_job_run).uuid)
676 JOB_SUBMIT_KEYS = [:script, :script_parameters, :script_version, :repository]
677 DEFAULT_START_JOB = :previous_job_run
679 def create_job_params(params, start_from=DEFAULT_START_JOB)
680 if not params.has_key?(:find_or_create)
681 params[:find_or_create] = true
683 job_attrs = params.delete(:job) || {}
684 start_job = jobs(start_from)
685 params[:job] = Hash[JOB_SUBMIT_KEYS.map do |key|
686 [key, start_job.send(key)]
688 params[:job][:runtime_constraints] =
689 job_attrs.delete(:runtime_constraints) || {}
690 { arvados_sdk_version: :arvados_sdk_version,
691 docker_image_locator: :docker_image }.each do |method, constraint_key|
692 if constraint_value = start_job.send(method)
693 params[:job][:runtime_constraints][constraint_key] ||= constraint_value
696 params[:job].merge!(job_attrs)
700 def create_job_from(params, start_from)
701 post(:create, params: create_job_params(params, start_from))
702 assert_response :success
703 new_job = assigns(:object)
704 assert_not_nil new_job
708 def check_new_job_created_from(params, start_from=DEFAULT_START_JOB)
709 start_time = Time.now
710 new_job = create_job_from(params, start_from)
711 assert_operator(start_time, :<=, new_job.created_at)
715 def check_job_reused_from(params, start_from)
716 new_job = create_job_from(params, start_from)
717 assert_equal(jobs(start_from).uuid, new_job.uuid)
720 def check_errors_from(params, start_from=DEFAULT_START_JOB)
721 post(:create, params: create_job_params(params, start_from))
722 assert_includes(405..499, @response.code.to_i)
723 errors = json_response.fetch("errors", [])
724 assert(errors.any?, "no errors assigned from #{params}")
725 refute(errors.any? { |msg| msg =~ /^#<[A-Za-z]+: / },
726 "errors include raw exception: #{errors.inspect}")
730 # 1de84a8 is on the b1 branch, after master's tip.
731 test "new job created from unsatisfiable minimum version filter" do
732 filters_hash = BASE_FILTERS.merge("script_version" => ["in git", "1de84a8"])
733 check_new_job_created_from(filters: filters_from_hash(filters_hash))
736 test "new job created from unsatisfiable minimum version parameter" do
737 check_new_job_created_from(minimum_script_version: "1de84a8")
740 test "new job created from unsatisfiable minimum version attribute" do
741 check_new_job_created_from(job: {minimum_script_version: "1de84a8"})
744 test "graceful error from nonexistent minimum version filter" do
745 filters_hash = BASE_FILTERS.merge("script_version" =>
746 ["in git", "__nosuchbranch__"])
747 errors = check_errors_from(filters: filters_from_hash(filters_hash))
748 assert(errors.any? { |msg| msg.include? "__nosuchbranch__" },
749 "bad refspec not mentioned in error message")
752 test "graceful error from nonexistent minimum version parameter" do
753 errors = check_errors_from(minimum_script_version: "__nosuchbranch__")
754 assert(errors.any? { |msg| msg.include? "__nosuchbranch__" },
755 "bad refspec not mentioned in error message")
758 test "graceful error from nonexistent minimum version attribute" do
759 errors = check_errors_from(job: {minimum_script_version: "__nosuchbranch__"})
760 assert(errors.any? { |msg| msg.include? "__nosuchbranch__" },
761 "bad refspec not mentioned in error message")
764 test "don't reuse job with older Arvados SDK version specified by branch" do
765 jobspec = {runtime_constraints: {
766 arvados_sdk_version: "master",
768 check_new_job_created_from({job: jobspec},
769 :previous_job_run_with_arvados_sdk_version)
772 test "don't reuse job with older Arvados SDK version specified by commit" do
773 jobspec = {runtime_constraints: {
774 arvados_sdk_version: "ca68b24e51992e790f29df5cc4bc54ce1da4a1c2",
776 check_new_job_created_from({job: jobspec},
777 :previous_job_run_with_arvados_sdk_version)
780 test "don't reuse job with newer Arvados SDK version specified by commit" do
781 jobspec = {runtime_constraints: {
782 arvados_sdk_version: "436637c87a1d2bdbf4b624008304064b6cf0e30c",
784 check_new_job_created_from({job: jobspec},
785 :previous_job_run_with_arvados_sdk_version)
788 test "reuse job from arvados_sdk_version git filters" do
789 prev_job = jobs(:previous_job_run_with_arvados_sdk_version)
790 filters_hash = BASE_FILTERS.
791 merge("arvados_sdk_version" => ["in git", "commit2"],
792 "docker_image_locator" => ["=", prev_job.docker_image_locator])
793 filters_hash.delete("script_version")
794 params = create_job_params(filters: filters_from_hash(filters_hash))
795 post(:create, params: params)
796 assert_response :success
797 assert_equal(prev_job.uuid, assigns(:object).uuid)
800 test "create new job because of arvados_sdk_version 'not in git' filters" do
801 filters_hash = BASE_FILTERS.reject { |k| k == "script_version" }
802 filters = filters_from_hash(filters_hash)
803 # Allow anything from the root commit, but before commit 2.
804 filters += [["arvados_sdk_version", "in git", "436637c8"],
805 ["arvados_sdk_version", "not in git", "00634b2b"]]
806 check_new_job_created_from(filters: filters)