3 class ContainerRequestTest < ActiveSupport::TestCase
4 def create_minimal_req! attrs={}
6 command: ["echo", "foo"],
7 container_image: links(:docker_image_collection_tag).name,
10 mounts: {"/out" => {"kind" => "tmp", "capacity" => 1000000}},
12 runtime_constraints: {},
16 cr = ContainerRequest.create!(defaults.merge(attrs))
21 def check_bogus_states cr
22 [nil, "Flubber"].each do |state|
23 assert_raises(ActiveRecord::RecordInvalid) do
31 test "Container request create" do
32 set_user_from_auth :active
33 cr = create_minimal_req!
35 assert_nil cr.container_uuid
36 assert_nil cr.priority
40 # Ensure we can modify all attributes
41 cr.command = ["echo", "foo3"]
42 cr.container_image = "img3"
44 cr.environment = {"BUP" => "BOP"}
45 cr.mounts = {"BAR" => "BAZ"}
46 cr.output_path = "/tmp4"
48 cr.runtime_constraints = {"vcpus" => 4}
50 cr.description = "bar3"
53 assert_nil cr.container_uuid
56 test "Container request priority must be non-nil" do
57 set_user_from_auth :active
58 cr = create_minimal_req!(priority: nil)
59 cr.state = "Committed"
60 assert_raises(ActiveRecord::RecordInvalid) do
65 test "Container request commit" do
66 set_user_from_auth :active
67 cr = create_minimal_req!(runtime_constraints: {"vcpus" => [2,3]})
69 assert_nil cr.container_uuid
72 cr.state = "Committed"
78 assert_not_nil cr.container_uuid
79 c = Container.find_by_uuid cr.container_uuid
81 assert_equal ["echo", "foo"], c.command
82 assert_equal collections(:docker_image).portable_data_hash, c.container_image
83 assert_equal "/tmp", c.cwd
84 assert_equal({}, c.environment)
85 assert_equal({"/out" => {"kind"=>"tmp", "capacity"=>1000000}}, c.mounts)
86 assert_equal "/out", c.output_path
87 assert_equal({"vcpus" => 2}, c.runtime_constraints)
88 assert_equal 1, c.priority
90 assert_raises(ActiveRecord::RecordInvalid) do
100 assert_equal 0, cr.priority
101 assert_equal 0, c.priority
105 test "Container request max priority" do
106 set_user_from_auth :active
107 cr = create_minimal_req!(priority: 5, state: "Committed")
109 c = Container.find_by_uuid cr.container_uuid
110 assert_equal 5, c.priority
112 cr2 = create_minimal_req!
114 cr2.state = "Committed"
115 cr2.container_uuid = cr.container_uuid
116 act_as_system_user do
120 # cr and cr2 have priority 5 and 10, and are being satisfied by
121 # the same container c, so c's priority should be
124 assert_equal 10, c.priority
126 cr2.update_attributes!(priority: 0)
129 assert_equal 5, c.priority
131 cr.update_attributes!(priority: 0)
134 assert_equal 0, c.priority
138 test "Independent container requests" do
139 set_user_from_auth :active
140 cr1 = create_minimal_req!(command: ["foo", "1"], priority: 5, state: "Committed")
141 cr2 = create_minimal_req!(command: ["foo", "2"], priority: 10, state: "Committed")
143 c1 = Container.find_by_uuid cr1.container_uuid
144 assert_equal 5, c1.priority
146 c2 = Container.find_by_uuid cr2.container_uuid
147 assert_equal 10, c2.priority
149 cr1.update_attributes!(priority: 0)
152 assert_equal 0, c1.priority
155 assert_equal 10, c2.priority
158 test "Request is finalized when its container is cancelled" do
159 set_user_from_auth :active
160 cr = create_minimal_req!(priority: 1, state: "Committed")
162 act_as_system_user do
163 Container.find_by_uuid(cr.container_uuid).
164 update_attributes!(state: Container::Cancelled)
168 assert_equal "Final", cr.state
171 test "Request is finalized when its container is completed" do
172 set_user_from_auth :active
173 cr = create_minimal_req!(priority: 1, state: "Committed")
175 c = act_as_system_user do
176 c = Container.find_by_uuid(cr.container_uuid)
177 c.update_attributes!(state: Container::Locked)
178 c.update_attributes!(state: Container::Running)
183 assert_equal "Committed", cr.state
185 act_as_system_user do
186 c.update_attributes!(state: Container::Complete)
190 assert_equal "Final", cr.state
193 test "Container makes container request, then is cancelled" do
194 set_user_from_auth :active
195 cr = create_minimal_req!(priority: 5, state: "Committed")
197 c = Container.find_by_uuid cr.container_uuid
198 assert_equal 5, c.priority
200 cr2 = create_minimal_req!(priority: 10, state: "Committed", requesting_container_uuid: c.uuid)
202 c2 = Container.find_by_uuid cr2.container_uuid
203 assert_equal 10, c2.priority
205 act_as_system_user do
206 c.state = "Cancelled"
211 assert_equal "Final", cr.state
214 assert_equal 0, cr2.priority
217 assert_equal 0, c2.priority
221 ['active', 'zzzzz-dz642-runningcontainr'],
222 ['active_no_prefs', nil],
223 ].each do |token, expected|
224 test "create as #{token} and expect requesting_container_uuid to be #{expected}" do
225 set_user_from_auth token
226 cr = ContainerRequest.create(container_image: "img", output_path: "/tmp", command: ["echo", "foo"])
227 assert_not_nil cr.uuid, 'uuid should be set for newly created container_request'
228 assert_equal expected, cr.requesting_container_uuid
232 [[{"vcpus" => [2, nil]},
233 lambda { |resolved| resolved["vcpus"] == 2 }],
234 [{"vcpus" => [3, 7]},
235 lambda { |resolved| resolved["vcpus"] == 3 }],
237 lambda { |resolved| resolved["vcpus"] == 4 }],
238 [{"ram" => [1000000000, 2000000000]},
239 lambda { |resolved| resolved["ram"] == 1000000000 }],
240 [{"ram" => [1234234234]},
241 lambda { |resolved| resolved["ram"] == 1234234234 }],
242 ].each do |rc, okfunc|
243 test "resolve runtime constraint range #{rc} to values" do
244 cr = ContainerRequest.new(runtime_constraints: rc)
245 resolved = cr.send :runtime_constraints_for_container
246 assert(okfunc.call(resolved),
247 "container runtime_constraints was #{resolved.inspect}")
252 "kind" => "collection",
253 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
256 resolved["/out"] == {
257 "portable_data_hash" => "1f4b0bc7583c2a7f9102c395f4ffc5e3+45",
258 "kind" => "collection",
263 "kind" => "collection",
264 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
265 "portable_data_hash" => "1f4b0bc7583c2a7f9102c395f4ffc5e3+45",
268 resolved["/out"] == {
269 "portable_data_hash" => "1f4b0bc7583c2a7f9102c395f4ffc5e3+45",
270 "kind" => "collection",
274 ].each do |mounts, okfunc|
275 test "resolve mounts #{mounts.inspect} to values" do
276 set_user_from_auth :active
277 cr = ContainerRequest.new(mounts: mounts)
278 resolved = cr.send :mounts_for_container
279 assert(okfunc.call(resolved),
280 "mounts_for_container returned #{resolved.inspect}")
284 test 'mount unreadable collection' do
285 set_user_from_auth :spectator
288 "kind" => "collection",
289 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
293 cr = ContainerRequest.new(mounts: m)
294 assert_raises(ActiveRecord::RecordNotFound) do
295 cr.send :mounts_for_container
299 test 'mount collection with mismatched UUID and PDH' do
300 set_user_from_auth :active
303 "kind" => "collection",
304 "uuid" => "zzzzz-4zz18-znfnqtbbv4spc3w",
305 "portable_data_hash" => "fa7aeb5140e2848d39b416daeef4ffc5+45",
309 cr = ContainerRequest.new(mounts: m)
310 assert_raises(ArgumentError) do
311 cr.send :mounts_for_container
315 ['arvados/apitestfixture:latest',
316 'arvados/apitestfixture',
317 'd8309758b8fe2c81034ffc8a10c36460b77db7bc5e7b448c4e5b684f9d95a678',
319 test "container_image_for_container(#{tag.inspect})" do
320 set_user_from_auth :active
321 cr = ContainerRequest.new(container_image: tag)
322 resolved = cr.send :container_image_for_container
323 assert_equal resolved, collections(:docker_image).portable_data_hash
327 test "container_image_for_container(pdh)" do
328 set_user_from_auth :active
329 pdh = collections(:docker_image).portable_data_hash
330 cr = ContainerRequest.new(container_image: pdh)
331 resolved = cr.send :container_image_for_container
332 assert_equal resolved, pdh
335 ['acbd18db4cc2f85cedef654fccc4a4d8+3',
337 'arvados/apitestfixture:ENOEXIST',
339 test "container_image_for_container(#{img.inspect}) => 404" do
340 set_user_from_auth :active
341 cr = ContainerRequest.new(container_image: img)
342 assert_raises(ActiveRecord::RecordNotFound) do
343 cr.send :container_image_for_container