X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/d53b4de9b3b23d8fec31be0254a9a0ec4355884a..678f1f53466c3f2133f63a6e6ad553f5e5d14804:/apps/workbench/test/controllers/collections_controller_test.rb diff --git a/apps/workbench/test/controllers/collections_controller_test.rb b/apps/workbench/test/controllers/collections_controller_test.rb index 7ff123cd45..88287cd3f3 100644 --- a/apps/workbench/test/controllers/collections_controller_test.rb +++ b/apps/workbench/test/controllers/collections_controller_test.rb @@ -1,3 +1,7 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + require 'test_helper' class CollectionsControllerTest < ActionController::TestCase @@ -13,21 +17,12 @@ class CollectionsControllerTest < ActionController::TestCase def config_anonymous enable Rails.configuration.anonymous_user_token = if enable - api_fixture('api_client_authorizations')['anonymous']['api_token'] + api_token('anonymous') else false end end - def stub_file_content - # For the duration of the current test case, stub file download - # content with a randomized (but recognizable) string. Return the - # string, the test case can use it in assertions. - txt = 'the quick brown fox ' + rand(2**32).to_s - @controller.stubs(:file_enumerator).returns([txt]) - txt - end - def collection_params(collection_name, file_name=nil) uuid = api_fixture('collections')[collection_name.to_s]['uuid'] params = {uuid: uuid, id: uuid} @@ -37,7 +32,11 @@ class CollectionsControllerTest < ActionController::TestCase def assert_hash_includes(actual_hash, expected_hash, msg=nil) expected_hash.each do |key, value| - assert_equal(value, actual_hash[key], msg) + if value.nil? + assert_nil(actual_hash[key], msg) + else + assert_equal(value, actual_hash[key], msg) + end end end @@ -48,7 +47,7 @@ class CollectionsControllerTest < ActionController::TestCase def assert_session_for_auth(client_auth) api_token = - api_fixture('api_client_authorizations')[client_auth.to_s]['api_token'] + self.api_token(client_auth.to_s) assert_hash_includes(session, {arvados_api_token: api_token}, "session token does not belong to #{client_auth}") end @@ -56,7 +55,7 @@ class CollectionsControllerTest < ActionController::TestCase def show_collection(params, session={}, response=:success) params = collection_params(params) if not params.is_a? Hash session = session_for(session) if not session.is_a? Hash - get(:show, params, session) + get(:show, params: params, session: session) assert_response response end @@ -71,17 +70,14 @@ class CollectionsControllerTest < ActionController::TestCase end test "download a file with spaces in filename" do + setup_for_keep_web collection = api_fixture('collections')['w_a_z_file'] - fakepipe = IO.popen(['echo', '-n', 'w a z'], 'rb') - IO.expects(:popen).with { |cmd, mode| - cmd.include? "#{collection['uuid']}/w a z" - }.returns(fakepipe) - get :show_file, { + get :show_file, params: { uuid: collection['uuid'], file: 'w a z' - }, session_for(:active) - assert_response :success - assert_equal 'w a z', response.body + }, session: session_for(:active) + assert_response :redirect + assert_match /w%20a%20z/, response.redirect_url end test "viewing a collection fetches related projects" do @@ -130,78 +126,65 @@ class CollectionsControllerTest < ActionController::TestCase test "viewing collection files with a reader token" do params = collection_params(:foo_file) - params[:reader_token] = api_fixture("api_client_authorizations", - "active_all_collections", "api_token") - get(:show_file_links, params) - assert_response :success - assert_equal([['.', 'foo', 3]], assigns(:object).files) + params[:reader_token] = api_token("active_all_collections") + get(:show_file_links, params: params) + assert_response :redirect assert_no_session end test "fetching collection file with reader token" do - expected = stub_file_content + setup_for_keep_web params = collection_params(:foo_file, "foo") - params[:reader_token] = api_fixture("api_client_authorizations", - "active_all_collections", "api_token") - get(:show_file, params) - assert_response :success - assert_equal(expected, @response.body, - "failed to fetch a Collection file with a reader token") + params[:reader_token] = api_token("active_all_collections") + get(:show_file, params: params) + assert_response :redirect + assert_match /foo/, response.redirect_url assert_no_session end test "reader token Collection links end with trailing slash" do # Testing the fix for #2937. session = session_for(:active_trustedclient) - post(:share, collection_params(:foo_file), session) + post(:share, params: collection_params(:foo_file), session: session) assert(@controller.download_link.ends_with? '/', "Collection share link does not end with slash for wget") end test "getting a file from Keep" do + setup_for_keep_web params = collection_params(:foo_file, 'foo') sess = session_for(:active) - expect_content = stub_file_content - get(:show_file, params, sess) - assert_response :success - assert_equal(expect_content, @response.body, - "failed to get a correct file from Keep") + get(:show_file, params: params, session: sess) + assert_response :redirect + assert_match /foo/, response.redirect_url end test 'anonymous download' do + setup_for_keep_web config_anonymous true - expect_content = stub_file_content - get :show_file, { + get :show_file, params: { uuid: api_fixture('collections')['user_agreement_in_anonymously_accessible_project']['uuid'], file: 'GNU_General_Public_License,_version_3.pdf', } - assert_response :success - assert_equal expect_content, response.body + assert_response :redirect + assert_match /GNU_General_Public_License/, response.redirect_url end test "can't get a file from Keep without permission" do params = collection_params(:foo_file, 'foo') sess = session_for(:spectator) - get(:show_file, params, sess) - assert_response 404 - end - - test "trying to get a nonexistent file from Keep returns a 404" do - params = collection_params(:foo_file, 'gone') - sess = session_for(:admin) - get(:show_file, params, sess) + get(:show_file, params: params, session: sess) assert_response 404 end test "getting a file from Keep with a good reader token" do + setup_for_keep_web params = collection_params(:foo_file, 'foo') - read_token = api_fixture('api_client_authorizations')['active']['api_token'] + read_token = api_token('active') params[:reader_token] = read_token - expect_content = stub_file_content - get(:show_file, params) - assert_response :success - assert_equal(expect_content, @response.body, - "failed to get a correct file from Keep using a reader token") + get(:show_file, params: params) + assert_response :redirect + assert_match /foo/, response.redirect_url assert_not_equal(read_token, session[:arvados_api_token], "using a reader token set the session's API token") end @@ -211,8 +194,8 @@ class CollectionsControllerTest < ActionController::TestCase config_anonymous anon params = collection_params(:foo_file, 'foo') params[:reader_token] = - api_fixture('api_client_authorizations')['active_noscope']['api_token'] - get(:show_file, params) + api_token('active_noscope') + get(:show_file, params: params) if anon # Some files can be shown without a valid token, but not this one. assert_response 404 @@ -225,33 +208,30 @@ class CollectionsControllerTest < ActionController::TestCase end test "can get a file with an unpermissioned auth but in-scope reader token" do + setup_for_keep_web params = collection_params(:foo_file, 'foo') sess = session_for(:expired) - read_token = api_fixture('api_client_authorizations')['active']['api_token'] + read_token = api_token('active') params[:reader_token] = read_token - expect_content = stub_file_content - get(:show_file, params, sess) - assert_response :success - assert_equal(expect_content, @response.body, - "failed to get a correct file from Keep using a reader token") + get(:show_file, params: params, session: sess) + assert_response :redirect assert_not_equal(read_token, session[:arvados_api_token], "using a reader token set the session's API token") end test "inactive user can retrieve user agreement" do + setup_for_keep_web ua_collection = api_fixture('collections')['user_agreement'] # Here we don't test whether the agreement can be retrieved from - # Keep. We only test that show_file decides to send file content, - # so we use the file content stub. - stub_file_content - get :show_file, { + # Keep. We only test that show_file decides to send file content. + get :show_file, params: { uuid: ua_collection['uuid'], file: ua_collection['manifest_text'].match(/ \d+:\d+:(\S+)/)[1] - }, session_for(:inactive) + }, session: session_for(:inactive) assert_nil(assigns(:unsigned_user_agreements), "Did not skip check_user_agreements filter " + "when showing the user agreement.") - assert_response :success + assert_response :redirect end test "requesting nonexistent Collection returns 404" do @@ -259,37 +239,12 @@ class CollectionsControllerTest < ActionController::TestCase :active, 404) end - test "use a reasonable read buffer even if client requests a huge range" do - fakefiledata = mock - IO.expects(:popen).returns(fakefiledata) - fakefiledata.expects(:read).twice.with() do |length| - # Fail the test if read() is called with length>1MiB: - length < 2**20 - ## Force the ActionController::Live thread to lose the race to - ## verify that @response.body.length actually waits for the - ## response (see below): - # sleep 3 - end.returns("foo\n", nil) - fakefiledata.expects(:close) - foo_file = api_fixture('collections')['foo_file'] - @request.headers['Range'] = 'bytes=0-4294967296/*' - get :show_file, { - uuid: foo_file['uuid'], - file: foo_file['manifest_text'].match(/ \d+:\d+:(\S+)/)[1] - }, session_for(:active) - # Wait for the whole response to arrive before deciding whether - # mocks' expectations were met. Otherwise, Mocha will fail the - # test depending on how slowly the ActionController::Live thread - # runs. - @response.body.length - end - test "show file in a subdirectory of a collection" do + setup_for_keep_web params = collection_params(:collection_with_files_in_subdir, 'subdir2/subdir3/subdir4/file1_in_subdir4.txt') - expect_content = stub_file_content - get(:show_file, params, session_for(:user1_with_load)) - assert_response :success - assert_equal(expect_content, @response.body, "failed to get a correct file from Keep") + get(:show_file, params: params, session: session_for(:user1_with_load)) + assert_response :redirect + assert_match /subdir2\/subdir3\/subdir4\/file1_in_subdir4\.txt/, response.redirect_url end test 'provenance graph' do @@ -369,11 +324,11 @@ class CollectionsControllerTest < ActionController::TestCase show_collection(fixture_name, :active) fixture = api_fixture('collections')[fixture_name.to_s] assert_equal(fixture['name'], assigns(:object).name) - assert_equal(fixture['properties'][0], assigns(:object).properties[0]) + assert_equal(fixture['properties'].values[0], assigns(:object).properties.values[0]) end test "create collection with properties" do - post :create, { + post :create, params: { collection: { name: 'collection created with properties', manifest_text: '', @@ -382,7 +337,7 @@ class CollectionsControllerTest < ActionController::TestCase }, }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response :success assert_not_nil assigns(:object).uuid assert_equal 'collection created with properties', assigns(:object).name @@ -391,13 +346,13 @@ class CollectionsControllerTest < ActionController::TestCase test "update description and check manifest_text is not lost" do collection = api_fixture("collections")["multilevel_collection_1"] - post :update, { + post :update, params: { id: collection["uuid"], collection: { description: 'test description update' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response :success assert_not_nil assigns(:object) # Ensure the Workbench response still has the original manifest_text @@ -456,7 +411,7 @@ class CollectionsControllerTest < ActionController::TestCase assert_equal true, files.length>0, "Expected one or more files in collection" disabled = css_select('[disabled="disabled"]').collect do |el| - el.attributes['title'].split[-1] + el.attributes['title'].value.split[-1] end assert_equal files.sort, disabled.sort, "Expected to see all collection files in disabled list of files" @@ -465,7 +420,7 @@ class CollectionsControllerTest < ActionController::TestCase test "anonymous user accesses collection in shared project" do config_anonymous true collection = api_fixture('collections')['public_text_file'] - get(:show, {id: collection['uuid']}) + get(:show, params: {id: collection['uuid']}) response_object = assigns(:object) assert_equal collection['name'], response_object['name'] @@ -476,19 +431,19 @@ class CollectionsControllerTest < ActionController::TestCase end test "can view empty collection" do - get :show, {id: 'd41d8cd98f00b204e9800998ecf8427e+0'}, session_for(:active) + get :show, params: {id: 'd41d8cd98f00b204e9800998ecf8427e+0'}, session: session_for(:active) assert_includes @response.body, 'The following collections have this content' end test "collection portable data hash redirect" do di = api_fixture('collections')['docker_image'] - get :show, {id: di['portable_data_hash']}, session_for(:active) + get :show, params: {id: di['portable_data_hash']}, session: session_for(:active) assert_match /\/collections\/#{di['uuid']}/, @response.redirect_url end test "collection portable data hash with multiple matches" do pdh = api_fixture('collections')['foo_file']['portable_data_hash'] - get :show, {id: pdh}, session_for(:admin) + get :show, params: {id: pdh}, session: session_for(:admin) matches = api_fixture('collections').select {|k,v| v["portable_data_hash"] == pdh} assert matches.size > 1 @@ -504,46 +459,51 @@ class CollectionsControllerTest < ActionController::TestCase test "collection page renders name" do collection = api_fixture('collections')['foo_file'] - get :show, {id: collection['uuid']}, session_for(:active) + get :show, params: {id: collection['uuid']}, session: session_for(:active) assert_includes @response.body, collection['name'] assert_match /not authorized to manage collection sharing links/, @response.body end test "No Upload tab on non-writable collection" do - get :show, {id: api_fixture('collections')['user_agreement']['uuid']}, session_for(:active) + get :show, + params: {id: api_fixture('collections')['user_agreement']['uuid']}, + session: session_for(:active) assert_not_includes @response.body, ' 'file1renamed' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response :success + use_token :active collection = Collection.select([:uuid, :manifest_text]).where(uuid: collection['uuid']).first assert_match /. d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:file1renamed 0:0:file2\n.\/dir1 d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:dir1file1 0:0:dir1file2 0:0:dir1imagefile.png\n$/, collection['manifest_text'] # now rename 'file2' such that it is moved into 'dir1' @test_counter = 0 - post :update, { + post :update, params: { id: collection['uuid'], collection: { 'rename-file-path:file2' => 'dir1/file2' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response :success + use_token :active collection = Collection.select([:uuid, :manifest_text]).where(uuid: collection['uuid']).first assert_match /. d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:file1renamed\n.\/dir1 d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:dir1file1 0:0:dir1file2 0:0:dir1imagefile.png 0:0:file2\n$/, collection['manifest_text'] # now rename 'dir1/dir1file1' such that it is moved into a new subdir @test_counter = 0 - post :update, { + post :update, params: { id: collection['uuid'], collection: { 'rename-file-path:dir1/dir1file1' => 'dir2/dir3/dir1file1moved' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response :success + use_token :active collection = Collection.select([:uuid, :manifest_text]).where(uuid: collection['uuid']).first assert_match /. d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:file1renamed\n.\/dir1 d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:dir1file2 0:0:dir1imagefile.png 0:0:file2\n.\/dir2\/dir3 d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:dir1file1moved\n$/, collection['manifest_text'] # now rename the image file 'dir1/dir1imagefile.png' @test_counter = 0 - post :update, { + post :update, params: { id: collection['uuid'], collection: { 'rename-file-path:dir1/dir1imagefile.png' => 'dir1/dir1imagefilerenamed.png' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response :success + use_token :active collection = Collection.select([:uuid, :manifest_text]).where(uuid: collection['uuid']).first assert_match /. d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:file1renamed\n.\/dir1 d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:dir1file2 0:0:dir1imagefilerenamed.png 0:0:file2\n.\/dir2\/dir3 d41d8cd98f00b204e9800998ecf8427e\+0\+A(.*) 0:0:dir1file1moved\n$/, collection['manifest_text'] end @@ -751,13 +717,13 @@ class CollectionsControllerTest < ActionController::TestCase use_token :active # rename 'file2' as 'file1' and expect error - post :update, { + post :update, params: { id: 'zzzzz-4zz18-pyw8yp9g3pr7irn', collection: { 'rename-file-path:file2' => 'file1' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response 422 assert_includes json_response['errors'], 'Duplicate file path' end @@ -766,13 +732,13 @@ class CollectionsControllerTest < ActionController::TestCase use_token :active # rename 'file1' as 'dir1/file1' and expect error - post :update, { + post :update, params: { id: 'zzzzz-4zz18-pyw8yp9g3pr7irn', collection: { 'rename-file-path:file1' => 'dir1/file1' }, format: :json - }, session_for(:active) + }, session: session_for(:active) assert_response 422 assert_includes json_response['errors'], 'Duplicate file path' end