Add 'apps/arv-web/' from commit 'f9732ad8460d013c2f28363655d0d1b91894dca5'
[arvados.git] / apps / workbench / test / controllers / application_controller_test.rb
1 require 'test_helper'
2
3 class ApplicationControllerTest < ActionController::TestCase
4   # These tests don't do state-changing API calls. Save some time by
5   # skipping the database reset.
6   reset_api_fixtures :after_each_test, false
7   reset_api_fixtures :after_suite, true
8
9   setup do
10     @user_dataclass = ArvadosBase.resource_class_for_uuid(api_fixture('users')['active']['uuid'])
11   end
12
13   test "links for object" do
14     use_token :active
15
16     ac = ApplicationController.new
17
18     link_head_uuid = api_fixture('links')['foo_file_readable_by_active']['head_uuid']
19
20     links = ac.send :links_for_object, link_head_uuid
21
22     assert links, 'Expected links'
23     assert links.is_a?(Array), 'Expected an array'
24     assert links.size > 0, 'Expected at least one link'
25     assert links[0][:uuid], 'Expected uuid for the head_link'
26   end
27
28   test "preload links for objects and uuids" do
29     use_token :active
30
31     ac = ApplicationController.new
32
33     link1_head_uuid = api_fixture('links')['foo_file_readable_by_active']['head_uuid']
34     link2_uuid = api_fixture('links')['bar_file_readable_by_active']['uuid']
35     link3_head_uuid = api_fixture('links')['bar_file_readable_by_active']['head_uuid']
36
37     link2_object = User.find(api_fixture('users')['active']['uuid'])
38     link2_object_uuid = link2_object['uuid']
39
40     uuids = [link1_head_uuid, link2_object, link3_head_uuid]
41     links = ac.send :preload_links_for_objects, uuids
42
43     assert links, 'Expected links'
44     assert links.is_a?(Hash), 'Expected a hash'
45     assert links.size == 3, 'Expected two objects in the preloaded links hash'
46     assert links[link1_head_uuid], 'Expected links for the passed in link head_uuid'
47     assert links[link2_object_uuid], 'Expected links for the passed in object uuid'
48     assert links[link3_head_uuid], 'Expected links for the passed in link head_uuid'
49
50     # invoke again for this same input. this time, the preloaded data will be returned
51     links = ac.send :preload_links_for_objects, uuids
52     assert links, 'Expected links'
53     assert links.is_a?(Hash), 'Expected a hash'
54     assert links.size == 3, 'Expected two objects in the preloaded links hash'
55     assert links[link1_head_uuid], 'Expected links for the passed in link head_uuid'
56   end
57
58   [ [:preload_links_for_objects, [] ],
59     [:preload_collections_for_objects, [] ],
60     [:preload_log_collections_for_objects, [] ],
61     [:preload_objects_for_dataclass, [] ],
62   ].each do |input|
63     test "preload data for empty array input #{input}" do
64       use_token :active
65
66       ac = ApplicationController.new
67
68       if input[0] == :preload_objects_for_dataclass
69         objects = ac.send input[0], @user_dataclass, input[1]
70       else
71         objects = ac.send input[0], input[1]
72       end
73
74       assert objects, 'Expected objects'
75       assert objects.is_a?(Hash), 'Expected a hash'
76       assert objects.size == 0, 'Expected no objects in the preloaded hash'
77     end
78   end
79
80   [ [:preload_links_for_objects, 'input not an array'],
81     [:preload_links_for_objects, nil],
82     [:links_for_object, nil],
83     [:preload_collections_for_objects, 'input not an array'],
84     [:preload_collections_for_objects, nil],
85     [:collections_for_object, nil],
86     [:preload_log_collections_for_objects, 'input not an array'],
87     [:preload_log_collections_for_objects, nil],
88     [:log_collections_for_object, nil],
89     [:preload_objects_for_dataclass, 'input not an array'],
90     [:preload_objects_for_dataclass, nil],
91     [:object_for_dataclass, 'some_dataclass', nil],
92     [:object_for_dataclass, nil, 'some_uuid'],
93   ].each do |input|
94     test "preload data for wrong type input #{input}" do
95       use_token :active
96
97       ac = ApplicationController.new
98
99       if input[0] == :object_for_dataclass
100         assert_raise ArgumentError do
101           ac.send input[0], input[1], input[2]
102         end
103       else
104         assert_raise ArgumentError do
105           ac.send input[0], input[1]
106         end
107       end
108     end
109   end
110
111   [ [:links_for_object, 'no-such-uuid' ],
112     [:collections_for_object, 'no-such-uuid' ],
113     [:log_collections_for_object, 'no-such-uuid' ],
114     [:object_for_dataclass, 'no-such-uuid' ],
115   ].each do |input|
116     test "get data for no such uuid #{input}" do
117       use_token :active
118
119       ac = ApplicationController.new
120
121       if input[0] == :object_for_dataclass
122         object = ac.send input[0], @user_dataclass, input[1]
123         assert_not object, 'Expected no object'
124       else
125         objects = ac.send input[0], input[1]
126         assert objects, 'Expected objects'
127         assert objects.is_a?(Array), 'Expected a array'
128       end
129     end
130   end
131
132   test "get 10 objects of data class user" do
133     use_token :active
134
135     ac = ApplicationController.new
136
137     objects = ac.send :get_n_objects_of_class, @user_dataclass, 10
138
139     assert objects, 'Expected objects'
140     assert objects.is_a?(ArvadosResourceList), 'Expected an ArvadosResourceList'
141
142     first_object = objects.first
143     assert first_object, 'Expected at least one object'
144     assert_equal 'User', first_object.class.name, 'Expected user object'
145
146     # invoke it again. this time, the preloaded info will be returned
147     objects = ac.send :get_n_objects_of_class, @user_dataclass, 10
148     assert objects, 'Expected objects'
149     assert_equal 'User', objects.first.class.name, 'Expected user object'
150   end
151
152   [ ['User', 10],
153     [nil, 10],
154     [@user_dataclass, 0],
155     [@user_dataclass, -1],
156     [@user_dataclass, nil] ].each do |input|
157     test "get_n_objects for incorrect input #{input}" do
158       use_token :active
159
160       ac = ApplicationController.new
161
162       assert_raise ArgumentError do
163         ac.send :get_n_objects_of_class, input[0], input[1]
164       end
165     end
166   end
167
168   test "collections for object" do
169     use_token :active
170
171     ac = ApplicationController.new
172
173     uuid = api_fixture('collections')['foo_file']['uuid']
174
175     collections = ac.send :collections_for_object, uuid
176
177     assert collections, 'Expected collections'
178     assert collections.is_a?(Array), 'Expected an array'
179     assert collections.size == 1, 'Expected one collection object'
180     assert_equal collections[0][:uuid], uuid, 'Expected uuid not found in collections'
181   end
182
183   test "preload collections for given uuids" do
184     use_token :active
185
186     ac = ApplicationController.new
187
188     uuid1 = api_fixture('collections')['foo_file']['uuid']
189     uuid2 = api_fixture('collections')['bar_file']['uuid']
190
191     uuids = [uuid1, uuid2]
192     collections = ac.send :preload_collections_for_objects, uuids
193
194     assert collections, 'Expected collection'
195     assert collections.is_a?(Hash), 'Expected a hash'
196     assert collections.size == 2, 'Expected two objects in the preloaded collection hash'
197     assert collections[uuid1], 'Expected collections for the passed in uuid'
198     assert_equal collections[uuid1].size, 1, 'Expected one collection for the passed in uuid'
199     assert collections[uuid2], 'Expected collections for the passed in uuid'
200     assert_equal collections[uuid2].size, 1, 'Expected one collection for the passed in uuid'
201
202     # invoke again for this same input. this time, the preloaded data will be returned
203     collections = ac.send :preload_collections_for_objects, uuids
204     assert collections, 'Expected collection'
205     assert collections.is_a?(Hash), 'Expected a hash'
206     assert collections.size == 2, 'Expected two objects in the preloaded collection hash'
207     assert collections[uuid1], 'Expected collections for the passed in uuid'
208   end
209
210   test "log collections for object" do
211     use_token :active
212
213     ac = ApplicationController.new
214
215     uuid = api_fixture('logs')['log4']['object_uuid']
216
217     collections = ac.send :log_collections_for_object, uuid
218
219     assert collections, 'Expected collections'
220     assert collections.is_a?(Array), 'Expected an array'
221     assert collections.size == 1, 'Expected one collection object'
222     assert_equal collections[0][:uuid], uuid, 'Expected uuid not found in collections'
223   end
224
225   test "preload log collections for given uuids" do
226     use_token :active
227
228     ac = ApplicationController.new
229
230     uuid1 = api_fixture('logs')['log4']['object_uuid']
231     uuid2 = api_fixture('collections')['bar_file']['uuid']
232
233     uuids = [uuid1, uuid2]
234     collections = ac.send :preload_log_collections_for_objects, uuids
235
236     assert collections, 'Expected collection'
237     assert collections.is_a?(Hash), 'Expected a hash'
238     assert collections.size == 2, 'Expected two objects in the preloaded collection hash'
239     assert collections[uuid1], 'Expected collections for the passed in uuid'
240     assert_equal collections[uuid1].size, 1, 'Expected one collection for the passed in uuid'
241     assert collections[uuid2], 'Expected collections for the passed in uuid'
242     assert_equal collections[uuid2].size, 1, 'Expected one collection for the passed in uuid'
243
244     # invoke again for this same input. this time, the preloaded data will be returned
245     collections = ac.send :preload_log_collections_for_objects, uuids
246     assert collections, 'Expected collection'
247     assert collections.is_a?(Hash), 'Expected a hash'
248     assert collections.size == 2, 'Expected two objects in the preloaded collection hash'
249     assert collections[uuid1], 'Expected collections for the passed in uuid'
250   end
251
252   test "object for dataclass" do
253     use_token :active
254
255     ac = ApplicationController.new
256
257     dataclass = ArvadosBase.resource_class_for_uuid(api_fixture('jobs')['running']['uuid'])
258     uuid = api_fixture('jobs')['running']['uuid']
259
260     obj = ac.send :object_for_dataclass, dataclass, uuid
261
262     assert obj, 'Expected object'
263     assert 'Job', obj.class
264     assert_equal uuid, obj['uuid'], 'Expected uuid not found'
265     assert_equal api_fixture('jobs')['running']['script_version'], obj['script_version'],
266       'Expected script_version not found'
267   end
268
269   test "preload objects for dataclass" do
270     use_token :active
271
272     ac = ApplicationController.new
273
274     dataclass = ArvadosBase.resource_class_for_uuid(api_fixture('jobs')['running']['uuid'])
275
276     uuid1 = api_fixture('jobs')['running']['uuid']
277     uuid2 = api_fixture('jobs')['running_cancelled']['uuid']
278
279     uuids = [uuid1, uuid2]
280     users = ac.send :preload_objects_for_dataclass, dataclass, uuids
281
282     assert users, 'Expected objects'
283     assert users.is_a?(Hash), 'Expected a hash'
284
285     assert users.size == 2, 'Expected two objects in the preloaded hash'
286     assert users[uuid1], 'Expected user object for the passed in uuid'
287     assert users[uuid2], 'Expected user object for the passed in uuid'
288
289     # invoke again for this same input. this time, the preloaded data will be returned
290     users = ac.send :preload_objects_for_dataclass, dataclass, uuids
291     assert users, 'Expected objects'
292     assert users.is_a?(Hash), 'Expected a hash'
293     assert users.size == 2, 'Expected two objects in the preloaded hash'
294
295     # invoke again for this with one more uuid
296     uuids << api_fixture('jobs')['foobar']['uuid']
297     users = ac.send :preload_objects_for_dataclass, dataclass, uuids
298     assert users, 'Expected objects'
299     assert users.is_a?(Hash), 'Expected a hash'
300     assert users.size == 3, 'Expected two objects in the preloaded hash'
301   end
302
303   test "requesting a nonexistent object returns 404" do
304     # We're really testing ApplicationController's find_object_by_uuid.
305     # It's easiest to do that by instantiating a concrete controller.
306     @controller = NodesController.new
307     get(:show, {id: "zzzzz-zzzzz-zzzzzzzzzzzzzzz"}, session_for(:admin))
308     assert_response 404
309   end
310
311   test "Workbench returns 4xx when API server is unreachable" do
312     # We're really testing ApplicationController's render_exception.
313     # Our primary concern is that it doesn't raise an error and
314     # return 500.
315     orig_api_server = Rails.configuration.arvados_v1_base
316     begin
317       # The URL should look valid in all respects, and avoid talking over a
318       # network.  100::/64 is the IPv6 discard prefix, so it's perfect.
319       Rails.configuration.arvados_v1_base = "https://[100::f]:1/"
320       @controller = NodesController.new
321       get(:index, {}, session_for(:active))
322       assert_includes(405..422, @response.code.to_i,
323                       "bad response code when API server is unreachable")
324     ensure
325       Rails.configuration.arvados_v1_base = orig_api_server
326     end
327   end
328 end