4533: Move all controller tests into controllers/, merge overlapping class defs.
authorTom Clegg <tom@curoverse.com>
Thu, 27 Nov 2014 01:02:36 +0000 (20:02 -0500)
committerTom Clegg <tom@curoverse.com>
Thu, 27 Nov 2014 01:02:36 +0000 (20:02 -0500)
28 files changed:
apps/workbench/test/controllers/actions_controller_test.rb [moved from apps/workbench/test/functional/actions_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/api_client_authorizations_controller_test.rb [moved from apps/workbench/test/functional/api_client_authorizations_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/application_controller_test.rb [moved from apps/workbench/test/functional/application_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/authorized_keys_controller_test.rb [moved from apps/workbench/test/functional/authorized_keys_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/collections_controller_test.rb
apps/workbench/test/controllers/groups_controller_test.rb [moved from apps/workbench/test/functional/groups_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/humans_controller_test.rb [moved from apps/workbench/test/functional/humans_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/job_tasks_controller_test.rb [moved from apps/workbench/test/functional/job_tasks_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/jobs_controller_test.rb [moved from apps/workbench/test/functional/jobs_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/keep_disks_controller_test.rb [moved from apps/workbench/test/functional/keep_disks_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/links_controller_test.rb [moved from apps/workbench/test/functional/links_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/logs_controller_test.rb [moved from apps/workbench/test/functional/logs_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/nodes_controller_test.rb [moved from apps/workbench/test/functional/nodes_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/pipeline_instances_controller_test.rb
apps/workbench/test/controllers/pipeline_templates_controller_test.rb [moved from apps/workbench/test/functional/pipeline_templates_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/projects_controller_test.rb [moved from apps/workbench/test/functional/projects_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/repositories_controller_test.rb [moved from apps/workbench/test/functional/repositories_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/sessions_controller_test.rb [moved from apps/workbench/test/functional/sessions_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/specimens_controller_test.rb [moved from apps/workbench/test/functional/specimens_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/traits_controller_test.rb [moved from apps/workbench/test/functional/traits_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/user_agreements_controller_test.rb [moved from apps/workbench/test/functional/user_agreements_controller_test.rb with 100% similarity]
apps/workbench/test/controllers/users_controller_test.rb [moved from apps/workbench/test/functional/users_controller_test.rb with 96% similarity]
apps/workbench/test/controllers/virtual_machines_controller_test.rb [moved from apps/workbench/test/functional/virtual_machines_controller_test.rb with 100% similarity]
apps/workbench/test/functional/.gitkeep [deleted file]
apps/workbench/test/functional/collections_controller_test.rb [deleted file]
apps/workbench/test/functional/pipeline_instances_controller_test.rb [deleted file]
apps/workbench/test/helpers/pipeline_instances_helper_test.rb [new file with mode: 0644]
apps/workbench/test/test_helper.rb

index a5c6033616a4a59fbf66a586b556af4af15579c4..9f4c5da2298a9bca1b05879ce0be1d6d5ddfe34d 100644 (file)
@@ -1,8 +1,239 @@
 require 'test_helper'
 
 class CollectionsControllerTest < ActionController::TestCase
+  # These tests don't do state-changing API calls. Save some time by
+  # skipping the database reset.
+  reset_api_fixtures :after_each_test, false
+  reset_api_fixtures :after_suite, true
+
   include PipelineInstancesHelper
 
+  NONEXISTENT_COLLECTION = "ffffffffffffffffffffffffffffffff+0"
+
+  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}
+    params[:file] = file_name if file_name
+    params
+  end
+
+  def assert_hash_includes(actual_hash, expected_hash, msg=nil)
+    expected_hash.each do |key, value|
+      assert_equal(value, actual_hash[key], msg)
+    end
+  end
+
+  def assert_no_session
+    assert_hash_includes(session, {arvados_api_token: nil},
+                         "session includes unexpected API token")
+  end
+
+  def assert_session_for_auth(client_auth)
+    api_token =
+      api_fixture('api_client_authorizations')[client_auth.to_s]['api_token']
+    assert_hash_includes(session, {arvados_api_token: api_token},
+                         "session token does not belong to #{client_auth}")
+  end
+
+  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)
+    assert_response response
+  end
+
+  test "viewing a collection" do
+    show_collection(:foo_file, :active)
+    assert_equal([['.', 'foo', 3]], assigns(:object).files)
+  end
+
+  test "viewing a collection fetches related projects" do
+    show_collection({id: api_fixture('collections')["foo_file"]['portable_data_hash']}, :active)
+    assert_includes(assigns(:same_pdh).map(&:owner_uuid),
+                    api_fixture('groups')['aproject']['uuid'],
+                    "controller did not find linked project")
+  end
+
+  test "viewing a collection fetches related permissions" do
+    show_collection(:bar_file, :active)
+    assert_includes(assigns(:permissions).map(&:uuid),
+                    api_fixture('links')['bar_file_readable_by_active']['uuid'],
+                    "controller did not find permission link")
+  end
+
+  test "viewing a collection fetches jobs that output it" do
+    show_collection(:bar_file, :active)
+    assert_includes(assigns(:output_of).map(&:uuid),
+                    api_fixture('jobs')['foobar']['uuid'],
+                    "controller did not find output job")
+  end
+
+  test "viewing a collection fetches jobs that logged it" do
+    show_collection(:baz_file, :active)
+    assert_includes(assigns(:log_of).map(&:uuid),
+                    api_fixture('jobs')['foobar']['uuid'],
+                    "controller did not find logger job")
+  end
+
+  test "viewing a collection fetches logs about it" do
+    show_collection(:foo_file, :active)
+    assert_includes(assigns(:logs).map(&:uuid),
+                    api_fixture('logs')['log4']['uuid'],
+                    "controller did not find related log")
+  end
+
+  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)
+    assert_no_session
+  end
+
+  test "fetching collection file with reader token" do
+    expected = stub_file_content
+    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")
+    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)
+    assert(@controller.download_link.ends_with? '/',
+           "Collection share link does not end with slash for wget")
+  end
+
+  test "getting a file from Keep" do
+    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")
+  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)
+    assert_response 404
+  end
+
+  test "getting a file from Keep with a good reader token" do
+    params = collection_params(:foo_file, 'foo')
+    read_token = api_fixture('api_client_authorizations')['active']['api_token']
+    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")
+    assert_not_equal(read_token, session[:arvados_api_token],
+                     "using a reader token set the session's API token")
+  end
+
+  test "trying to get from Keep with an unscoped reader token prompts login" do
+    params = collection_params(:foo_file, 'foo')
+    params[:reader_token] =
+      api_fixture('api_client_authorizations')['active_noscope']['api_token']
+    get(:show_file, params)
+    assert_response :redirect
+  end
+
+  test "can get a file with an unpermissioned auth but in-scope reader token" do
+    params = collection_params(:foo_file, 'foo')
+    sess = session_for(:expired)
+    read_token = api_fixture('api_client_authorizations')['active']['api_token']
+    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")
+    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
+    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, {
+      uuid: ua_collection['uuid'],
+      file: ua_collection['manifest_text'].match(/ \d+:\d+:(\S+)/)[1]
+    }, session_for(:inactive)
+    assert_nil(assigns(:unsigned_user_agreements),
+               "Did not skip check_user_agreements filter " +
+               "when showing the user agreement.")
+    assert_response :success
+  end
+
+  test "requesting nonexistent Collection returns 404" do
+    show_collection({uuid: NONEXISTENT_COLLECTION, id: NONEXISTENT_COLLECTION},
+                    :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
+    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")
+  end
+
   test 'provenance graph' do
     use_token 'admin'
 
index b518b077bcf212582756ef0bce79394151fe061d..ac36f197f4306e5d0ac82f77a47cf8d7c0b1d977 100644 (file)
@@ -3,39 +3,158 @@ require 'test_helper'
 class PipelineInstancesControllerTest < ActionController::TestCase
   include PipelineInstancesHelper
 
-  test "one" do
-    r = [{started_at: 1, finished_at: 3}]
-    assert_equal 2, determine_wallclock_runtime(r)
-
-    r = [{started_at: 1, finished_at: 5}]
-    assert_equal 4, determine_wallclock_runtime(r)
-
-    r = [{started_at: 1, finished_at: 2}, {started_at: 3, finished_at: 5}]
-    assert_equal 3, determine_wallclock_runtime(r)
+  def create_instance_long_enough_to(instance_attrs={})
+    # create 'two_part' pipeline with the given instance attributes
+    pt_fixture = api_fixture('pipeline_templates')['two_part']
+    post :create, {
+      pipeline_instance: instance_attrs.merge({
+        pipeline_template_uuid: pt_fixture['uuid']
+      }),
+      format: :json
+    }, session_for(:active)
+    assert_response :success
+    pi_uuid = assigns(:object).uuid
+    assert_not_nil assigns(:object)
+
+    # yield
+    yield pi_uuid, pt_fixture
+
+    # delete the pipeline instance
+    use_token :active
+    PipelineInstance.where(uuid: pi_uuid).first.destroy
+  end
 
-    r = [{started_at: 3, finished_at: 5}, {started_at: 1, finished_at: 2}]
-    assert_equal 3, determine_wallclock_runtime(r)
+  test "pipeline instance components populated after create" do
+    create_instance_long_enough_to do |new_instance_uuid, template_fixture|
+      assert_equal(template_fixture['components'].to_json,
+                   assigns(:object).components.to_json)
+    end
+  end
 
-    r = [{started_at: 3, finished_at: 5}, {started_at: 1, finished_at: 2},
-         {started_at: 2, finished_at: 4}]
-    assert_equal 4, determine_wallclock_runtime(r)
+  test "can render pipeline instance with tagged collections" do
+    # Make sure to pass in a tagged collection to test that part of the rendering behavior.
+    get(:show,
+        {id: api_fixture("pipeline_instances")["pipeline_with_tagged_collection_input"]["uuid"]},
+        session_for(:active))
+    assert_response :success
+  end
 
-    r = [{started_at: 1, finished_at: 5}, {started_at: 2, finished_at: 3}]
-    assert_equal 4, determine_wallclock_runtime(r)
+  test "update script_parameters one at a time using merge param" do
+      template_fixture = api_fixture('pipeline_templates')['two_part']
+      post :update, {
+        id: api_fixture("pipeline_instances")["pipeline_to_merge_params"]["uuid"],
+        pipeline_instance: {
+          components: {
+            "part-two" => {
+              script_parameters: {
+                integer_with_value: {
+                  value: 9
+                },
+                plain_string: {
+                  value: 'quux'
+                },
+              }
+            }
+          }
+        },
+        merge: true,
+        format: :json
+      }, session_for(:active)
+      assert_response :success
+      assert_not_nil assigns(:object)
+      orig_params = template_fixture['components']['part-two']['script_parameters']
+      new_params = assigns(:object).components[:'part-two'][:script_parameters]
+      orig_params.keys.each do |k|
+        unless %w(integer_with_value plain_string).index(k)
+          assert_equal orig_params[k].to_json, new_params[k.to_sym].to_json
+        end
+      end
+  end
 
-    r = [{started_at: 3, finished_at: 5}, {started_at: 1, finished_at: 4}]
-    assert_equal 4, determine_wallclock_runtime(r)
+  test "component rendering copes with unexpected components format" do
+    get(:show,
+        {id: api_fixture("pipeline_instances")["components_is_jobspec"]["uuid"]},
+        session_for(:active))
+    assert_response :success
+  end
 
-    r = [{started_at: 1, finished_at: 4}, {started_at: 3, finished_at: 5}]
-    assert_equal 4, determine_wallclock_runtime(r)
+  test "dates in JSON components are parsed" do
+    get(:show,
+        {id: api_fixture('pipeline_instances')['has_component_with_completed_jobs']['uuid']},
+        session_for(:active))
+    assert_response :success
+    assert_not_nil assigns(:object)
+    assert_not_nil assigns(:object).components[:foo][:job]
+    assert assigns(:object).components[:foo][:job][:started_at].is_a? Time
+    assert assigns(:object).components[:foo][:job][:finished_at].is_a? Time
+  end
 
-    r = [{started_at: 1, finished_at: 4}, {started_at: 3, finished_at: 5},
-         {started_at: 5, finished_at: 8}]
-    assert_equal 7, determine_wallclock_runtime(r)
+  # The next two tests ensure that a pipeline instance can be copied
+  # when the template has components that do not exist in the
+  # instance (ticket #4000).
+
+  test "copy pipeline instance with components=use_latest" do
+    post(:copy,
+         {
+           id: api_fixture('pipeline_instances')['pipeline_with_newer_template']['uuid'],
+           components: 'use_latest',
+           script: 'use_latest',
+           pipeline_instance: {
+             state: 'RunningOnServer'
+           }
+         },
+         session_for(:active))
+    assert_response 302
+    assert_not_nil assigns(:object)
+
+    # Component 'foo' has script parameters only in the pipeline instance.
+    # Component 'bar' is present only in the pipeline_template.
+    # Test that the copied pipeline instance includes parameters for
+    # component 'foo' from the source instance, and parameters for
+    # component 'bar' from the source template.
+    #
+    assert_not_nil assigns(:object).components[:foo]
+    foo = assigns(:object).components[:foo]
+    assert_not_nil foo[:script_parameters]
+    assert_not_nil foo[:script_parameters][:input]
+    assert_equal 'foo instance input', foo[:script_parameters][:input][:title]
+
+    assert_not_nil assigns(:object).components[:bar]
+    bar = assigns(:object).components[:bar]
+    assert_not_nil bar[:script_parameters]
+    assert_not_nil bar[:script_parameters][:input]
+    assert_equal 'bar template input', bar[:script_parameters][:input][:title]
+  end
 
-    r = [{started_at: 1, finished_at: 4}, {started_at: 3, finished_at: 5},
-         {started_at: 6, finished_at: 8}]
-    assert_equal 6, determine_wallclock_runtime(r)
+  test "copy pipeline instance on newer template works with script=use_same" do
+    post(:copy,
+         {
+           id: api_fixture('pipeline_instances')['pipeline_with_newer_template']['uuid'],
+           components: 'use_latest',
+           script: 'use_same',
+           pipeline_instance: {
+             state: 'RunningOnServer'
+           }
+         },
+         session_for(:active))
+    assert_response 302
+    assert_not_nil assigns(:object)
+
+    # Test that relevant component parameters were copied from both
+    # the source instance and source template, respectively (see
+    # previous test)
+    #
+    assert_not_nil assigns(:object).components[:foo]
+    foo = assigns(:object).components[:foo]
+    assert_not_nil foo[:script_parameters]
+    assert_not_nil foo[:script_parameters][:input]
+    assert_equal 'foo instance input', foo[:script_parameters][:input][:title]
+
+    assert_not_nil assigns(:object).components[:bar]
+    bar = assigns(:object).components[:bar]
+    assert_not_nil bar[:script_parameters]
+    assert_not_nil bar[:script_parameters][:input]
+    assert_equal 'bar template input', bar[:script_parameters][:input][:title]
   end
 
   test "generate graph" do
similarity index 96%
rename from apps/workbench/test/functional/users_controller_test.rb
rename to apps/workbench/test/controllers/users_controller_test.rb
index a734391e98e6367edb3c0766e001e0a3ef0000a6..213a2a53c1630db44f3da2e1d1568670ec84a6d2 100644 (file)
@@ -1,7 +1,7 @@
 require 'test_helper'
 
 class UsersControllerTest < ActionController::TestCase
-  test "valid token works in functional test" do
+  test "valid token works in controller test" do
     get :index, {}, session_for(:active)
     assert_response :success
   end
diff --git a/apps/workbench/test/functional/.gitkeep b/apps/workbench/test/functional/.gitkeep
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/apps/workbench/test/functional/collections_controller_test.rb b/apps/workbench/test/functional/collections_controller_test.rb
deleted file mode 100644 (file)
index 7c406c2..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-require 'test_helper'
-
-class CollectionsControllerTest < ActionController::TestCase
-  # These tests don't do state-changing API calls. Save some time by
-  # skipping the database reset.
-  reset_api_fixtures :after_each_test, false
-  reset_api_fixtures :after_suite, true
-
-  NONEXISTENT_COLLECTION = "ffffffffffffffffffffffffffffffff+0"
-
-  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}
-    params[:file] = file_name if file_name
-    params
-  end
-
-  def assert_hash_includes(actual_hash, expected_hash, msg=nil)
-    expected_hash.each do |key, value|
-      assert_equal(value, actual_hash[key], msg)
-    end
-  end
-
-  def assert_no_session
-    assert_hash_includes(session, {arvados_api_token: nil},
-                         "session includes unexpected API token")
-  end
-
-  def assert_session_for_auth(client_auth)
-    api_token =
-      api_fixture('api_client_authorizations')[client_auth.to_s]['api_token']
-    assert_hash_includes(session, {arvados_api_token: api_token},
-                         "session token does not belong to #{client_auth}")
-  end
-
-  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)
-    assert_response response
-  end
-
-  test "viewing a collection" do
-    show_collection(:foo_file, :active)
-    assert_equal([['.', 'foo', 3]], assigns(:object).files)
-  end
-
-  test "viewing a collection fetches related projects" do
-    show_collection({id: api_fixture('collections')["foo_file"]['portable_data_hash']}, :active)
-    assert_includes(assigns(:same_pdh).map(&:owner_uuid),
-                    api_fixture('groups')['aproject']['uuid'],
-                    "controller did not find linked project")
-  end
-
-  test "viewing a collection fetches related permissions" do
-    show_collection(:bar_file, :active)
-    assert_includes(assigns(:permissions).map(&:uuid),
-                    api_fixture('links')['bar_file_readable_by_active']['uuid'],
-                    "controller did not find permission link")
-  end
-
-  test "viewing a collection fetches jobs that output it" do
-    show_collection(:bar_file, :active)
-    assert_includes(assigns(:output_of).map(&:uuid),
-                    api_fixture('jobs')['foobar']['uuid'],
-                    "controller did not find output job")
-  end
-
-  test "viewing a collection fetches jobs that logged it" do
-    show_collection(:baz_file, :active)
-    assert_includes(assigns(:log_of).map(&:uuid),
-                    api_fixture('jobs')['foobar']['uuid'],
-                    "controller did not find logger job")
-  end
-
-  test "viewing a collection fetches logs about it" do
-    show_collection(:foo_file, :active)
-    assert_includes(assigns(:logs).map(&:uuid),
-                    api_fixture('logs')['log4']['uuid'],
-                    "controller did not find related log")
-  end
-
-  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)
-    assert_no_session
-  end
-
-  test "fetching collection file with reader token" do
-    expected = stub_file_content
-    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")
-    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)
-    assert(@controller.download_link.ends_with? '/',
-           "Collection share link does not end with slash for wget")
-  end
-
-  test "getting a file from Keep" do
-    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")
-  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)
-    assert_response 404
-  end
-
-  test "getting a file from Keep with a good reader token" do
-    params = collection_params(:foo_file, 'foo')
-    read_token = api_fixture('api_client_authorizations')['active']['api_token']
-    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")
-    assert_not_equal(read_token, session[:arvados_api_token],
-                     "using a reader token set the session's API token")
-  end
-
-  test "trying to get from Keep with an unscoped reader token prompts login" do
-    params = collection_params(:foo_file, 'foo')
-    params[:reader_token] =
-      api_fixture('api_client_authorizations')['active_noscope']['api_token']
-    get(:show_file, params)
-    assert_response :redirect
-  end
-
-  test "can get a file with an unpermissioned auth but in-scope reader token" do
-    params = collection_params(:foo_file, 'foo')
-    sess = session_for(:expired)
-    read_token = api_fixture('api_client_authorizations')['active']['api_token']
-    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")
-    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
-    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, {
-      uuid: ua_collection['uuid'],
-      file: ua_collection['manifest_text'].match(/ \d+:\d+:(\S+)/)[1]
-    }, session_for(:inactive)
-    assert_nil(assigns(:unsigned_user_agreements),
-               "Did not skip check_user_agreements filter " +
-               "when showing the user agreement.")
-    assert_response :success
-  end
-
-  test "requesting nonexistent Collection returns 404" do
-    show_collection({uuid: NONEXISTENT_COLLECTION, id: NONEXISTENT_COLLECTION},
-                    :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
-    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")
-  end
-end
diff --git a/apps/workbench/test/functional/pipeline_instances_controller_test.rb b/apps/workbench/test/functional/pipeline_instances_controller_test.rb
deleted file mode 100644 (file)
index a14d419..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-require 'test_helper'
-
-class PipelineInstancesControllerTest < ActionController::TestCase
-  def create_instance_long_enough_to(instance_attrs={})
-    # create 'two_part' pipeline with the given instance attributes
-    pt_fixture = api_fixture('pipeline_templates')['two_part']
-    post :create, {
-      pipeline_instance: instance_attrs.merge({
-        pipeline_template_uuid: pt_fixture['uuid']
-      }),
-      format: :json
-    }, session_for(:active)
-    assert_response :success
-    pi_uuid = assigns(:object).uuid
-    assert_not_nil assigns(:object)
-
-    # yield
-    yield pi_uuid, pt_fixture
-
-    # delete the pipeline instance
-    use_token :active
-    PipelineInstance.where(uuid: pi_uuid).first.destroy
-  end
-
-  test "pipeline instance components populated after create" do
-    create_instance_long_enough_to do |new_instance_uuid, template_fixture|
-      assert_equal(template_fixture['components'].to_json,
-                   assigns(:object).components.to_json)
-    end
-  end
-
-  test "can render pipeline instance with tagged collections" do
-    # Make sure to pass in a tagged collection to test that part of the rendering behavior.
-    get(:show,
-        {id: api_fixture("pipeline_instances")["pipeline_with_tagged_collection_input"]["uuid"]},
-        session_for(:active))
-    assert_response :success
-  end
-
-  test "update script_parameters one at a time using merge param" do
-      template_fixture = api_fixture('pipeline_templates')['two_part']
-      post :update, {
-        id: api_fixture("pipeline_instances")["pipeline_to_merge_params"]["uuid"],
-        pipeline_instance: {
-          components: {
-            "part-two" => {
-              script_parameters: {
-                integer_with_value: {
-                  value: 9
-                },
-                plain_string: {
-                  value: 'quux'
-                },
-              }
-            }
-          }
-        },
-        merge: true,
-        format: :json
-      }, session_for(:active)
-      assert_response :success
-      assert_not_nil assigns(:object)
-      orig_params = template_fixture['components']['part-two']['script_parameters']
-      new_params = assigns(:object).components[:'part-two'][:script_parameters]
-      orig_params.keys.each do |k|
-        unless %w(integer_with_value plain_string).index(k)
-          assert_equal orig_params[k].to_json, new_params[k.to_sym].to_json
-        end
-      end
-  end
-
-  test "component rendering copes with unexpected components format" do
-    get(:show,
-        {id: api_fixture("pipeline_instances")["components_is_jobspec"]["uuid"]},
-        session_for(:active))
-    assert_response :success
-  end
-
-  test "dates in JSON components are parsed" do
-    get(:show,
-        {id: api_fixture('pipeline_instances')['has_component_with_completed_jobs']['uuid']},
-        session_for(:active))
-    assert_response :success
-    assert_not_nil assigns(:object)
-    assert_not_nil assigns(:object).components[:foo][:job]
-    assert assigns(:object).components[:foo][:job][:started_at].is_a? Time
-    assert assigns(:object).components[:foo][:job][:finished_at].is_a? Time
-  end
-
-  # The next two tests ensure that a pipeline instance can be copied
-  # when the template has components that do not exist in the
-  # instance (ticket #4000).
-
-  test "copy pipeline instance with components=use_latest" do
-    post(:copy,
-         {
-           id: api_fixture('pipeline_instances')['pipeline_with_newer_template']['uuid'],
-           components: 'use_latest',
-           script: 'use_latest',
-           pipeline_instance: {
-             state: 'RunningOnServer'
-           }
-         },
-         session_for(:active))
-    assert_response 302
-    assert_not_nil assigns(:object)
-
-    # Component 'foo' has script parameters only in the pipeline instance.
-    # Component 'bar' is present only in the pipeline_template.
-    # Test that the copied pipeline instance includes parameters for
-    # component 'foo' from the source instance, and parameters for
-    # component 'bar' from the source template.
-    #
-    assert_not_nil assigns(:object).components[:foo]
-    foo = assigns(:object).components[:foo]
-    assert_not_nil foo[:script_parameters]
-    assert_not_nil foo[:script_parameters][:input]
-    assert_equal 'foo instance input', foo[:script_parameters][:input][:title]
-
-    assert_not_nil assigns(:object).components[:bar]
-    bar = assigns(:object).components[:bar]
-    assert_not_nil bar[:script_parameters]
-    assert_not_nil bar[:script_parameters][:input]
-    assert_equal 'bar template input', bar[:script_parameters][:input][:title]
-  end
-
-  test "copy pipeline instance on newer template works with script=use_same" do
-    post(:copy,
-         {
-           id: api_fixture('pipeline_instances')['pipeline_with_newer_template']['uuid'],
-           components: 'use_latest',
-           script: 'use_same',
-           pipeline_instance: {
-             state: 'RunningOnServer'
-           }
-         },
-         session_for(:active))
-    assert_response 302
-    assert_not_nil assigns(:object)
-
-    # Test that relevant component parameters were copied from both
-    # the source instance and source template, respectively (see
-    # previous test)
-    #
-    assert_not_nil assigns(:object).components[:foo]
-    foo = assigns(:object).components[:foo]
-    assert_not_nil foo[:script_parameters]
-    assert_not_nil foo[:script_parameters][:input]
-    assert_equal 'foo instance input', foo[:script_parameters][:input][:title]
-
-    assert_not_nil assigns(:object).components[:bar]
-    bar = assigns(:object).components[:bar]
-    assert_not_nil bar[:script_parameters]
-    assert_not_nil bar[:script_parameters][:input]
-    assert_equal 'bar template input', bar[:script_parameters][:input][:title]
-  end
-end
diff --git a/apps/workbench/test/helpers/pipeline_instances_helper_test.rb b/apps/workbench/test/helpers/pipeline_instances_helper_test.rb
new file mode 100644 (file)
index 0000000..a785683
--- /dev/null
@@ -0,0 +1,38 @@
+require 'test_helper'
+
+class PipelineInstancesHelperTest < ActionView::TestCase
+  test "one" do
+    r = [{started_at: 1, finished_at: 3}]
+    assert_equal 2, determine_wallclock_runtime(r)
+
+    r = [{started_at: 1, finished_at: 5}]
+    assert_equal 4, determine_wallclock_runtime(r)
+
+    r = [{started_at: 1, finished_at: 2}, {started_at: 3, finished_at: 5}]
+    assert_equal 3, determine_wallclock_runtime(r)
+
+    r = [{started_at: 3, finished_at: 5}, {started_at: 1, finished_at: 2}]
+    assert_equal 3, determine_wallclock_runtime(r)
+
+    r = [{started_at: 3, finished_at: 5}, {started_at: 1, finished_at: 2},
+         {started_at: 2, finished_at: 4}]
+    assert_equal 4, determine_wallclock_runtime(r)
+
+    r = [{started_at: 1, finished_at: 5}, {started_at: 2, finished_at: 3}]
+    assert_equal 4, determine_wallclock_runtime(r)
+
+    r = [{started_at: 3, finished_at: 5}, {started_at: 1, finished_at: 4}]
+    assert_equal 4, determine_wallclock_runtime(r)
+
+    r = [{started_at: 1, finished_at: 4}, {started_at: 3, finished_at: 5}]
+    assert_equal 4, determine_wallclock_runtime(r)
+
+    r = [{started_at: 1, finished_at: 4}, {started_at: 3, finished_at: 5},
+         {started_at: 5, finished_at: 8}]
+    assert_equal 7, determine_wallclock_runtime(r)
+
+    r = [{started_at: 1, finished_at: 4}, {started_at: 3, finished_at: 5},
+         {started_at: 6, finished_at: 8}]
+    assert_equal 6, determine_wallclock_runtime(r)
+  end
+end
index 58e540cbeb47d95814970436911e1db7e0bc857c..dbeb9aa05de1e539023e9ff341e41aaf1f470d84 100644 (file)
@@ -192,7 +192,7 @@ class ActionController::TestCase
   def check_counter action
     @counter += 1
     if @counter == 2
-      assert_equal 1, 2, "Multiple actions in functional test"
+      assert_equal 1, 2, "Multiple actions in controller test"
     end
   end