Merge branch 'master' into 4523-search-index
[arvados.git] / services / api / test / functional / arvados / v1 / collections_controller_test.rb
index f2c15c656b3f2570adf211cd6fdb01222cf3bfb7..ed56b62cd9d2efa3c4e05aecb045204ef12bbac8 100644 (file)
@@ -2,21 +2,19 @@ require 'test_helper'
 
 class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
 
-  setup do
-    # Unless otherwise specified in the test, we want normal/secure behavior.
-    permit_unsigned_manifests false
-  end
-
-  teardown do
-    # Reset to secure behavior after each test.
-    permit_unsigned_manifests false
-  end
-
   def permit_unsigned_manifests isok=true
     # Set security model for the life of a test.
     Rails.configuration.permit_create_collection_with_unsigned_manifest = isok
   end
 
+  def assert_signed_manifest manifest_text, label=''
+    assert_not_nil manifest_text, "#{label} manifest_text was nil"
+    manifest_text.scan(/ [[:xdigit:]]{32}\S*/) do |tok|
+      assert_match(/\+A[[:xdigit:]]+@[[:xdigit:]]{8}\b/, tok,
+                   "Locator in #{label} manifest_text was not signed")
+    end
+  end
+
   test "should get index" do
     authorize_with :active
     get :index
@@ -26,6 +24,14 @@ class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
            "basic Collections index included manifest_text")
   end
 
+  test "collections.get returns signed locators" do
+    permit_unsigned_manifests
+    authorize_with :active
+    get :show, {id: collections(:foo_file).uuid}
+    assert_response :success
+    assert_signed_manifest json_response['manifest_text'], 'foo_file'
+  end
+
   test "index with manifest_text selected returns signed locators" do
     columns = %w(uuid owner_uuid manifest_text)
     authorize_with :active
@@ -36,13 +42,7 @@ class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
     json_response["items"].each do |coll|
       assert_equal(columns, columns & coll.keys,
                    "Collections index did not respect selected columns")
-      loc_regexp = / [[:xdigit:]]{32}\+\d+\S+/
-      pos = 0
-      while match = loc_regexp.match(coll["manifest_text"], pos)
-        assert_match(/\+A[[:xdigit:]]+@[[:xdigit:]]{8}\b/, match.to_s,
-                     "Locator in manifest_text was not signed")
-        pos = match.end(0)
-      end
+      assert_signed_manifest coll['manifest_text'], coll['uuid']
     end
   end
 
@@ -68,6 +68,18 @@ class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
     assert_equal unique_uuids.count, resp['items'].count
   end
 
+  test "items.count == items_available with filters" do
+    authorize_with :active
+    get :index, {
+      limit: 100,
+      filters: [['uuid','=',collections(:foo_file).uuid]]
+    }
+    assert_response :success
+    assert_equal 1, assigns(:objects).length
+    assert_equal 1, json_response['items_available']
+    assert_equal 1, json_response['items'].count
+  end
+
   test "get index with limit=2 offset=99999" do
     # Assume there are not that many test fixtures.
     authorize_with :active
@@ -104,18 +116,43 @@ EOS
     assert_response :success
     assert_nil assigns(:objects)
 
-    get :show, {
-      id: test_collection[:portable_data_hash]
-    }
-    assert_response :success
-    assert_not_nil assigns(:object)
-    resp = JSON.parse(@response.body)
-    assert_equal test_collection[:portable_data_hash], resp['portable_data_hash']
+    response_collection = assigns(:object)
+
+    stored_collection = Collection.select([:uuid, :portable_data_hash, :manifest_text]).
+      where(portable_data_hash: response_collection['portable_data_hash']).first
+
+    assert_equal test_collection[:portable_data_hash], stored_collection['portable_data_hash']
 
     # The manifest in the response will have had permission hints added.
     # Remove any permission hints in the response before comparing it to the source.
-    stripped_manifest = resp['manifest_text'].gsub(/\+A[A-Za-z0-9@_-]+/, '')
+    stripped_manifest = stored_collection['manifest_text'].gsub(/\+A[A-Za-z0-9@_-]+/, '')
     assert_equal test_collection[:manifest_text], stripped_manifest
+
+    # TBD: create action should add permission signatures to manifest_text in the response,
+    # and we need to check those permission signatures here.
+  end
+
+  [:admin, :active].each do |user|
+    test "#{user} can get collection using portable data hash" do
+      authorize_with user
+
+      foo_collection = collections(:foo_file)
+
+      # Get foo_file using its portable data hash
+      get :show, {
+        id: foo_collection[:portable_data_hash]
+      }
+      assert_response :success
+      assert_not_nil assigns(:object)
+      resp = assigns(:object)
+      assert_equal foo_collection[:portable_data_hash], resp['portable_data_hash']
+      assert_signed_manifest resp['manifest_text']
+
+      # The manifest in the response will have had permission hints added.
+      # Remove any permission hints in the response before comparing it to the source.
+      stripped_manifest = resp['manifest_text'].gsub(/\+A[A-Za-z0-9@_-]+/, '')
+      assert_equal foo_collection[:manifest_text], stripped_manifest
+    end
   end
 
   test "create with owner_uuid set to owned group" do
@@ -147,24 +184,31 @@ EOS
       }
     }
     assert_response 422
+    response_errors = json_response['errors']
+    assert_not_nil response_errors, 'Expected error in response'
+    assert(response_errors.first.include?('duplicate key'),
+           "Expected 'duplicate key' error in #{response_errors.first}")
   end
 
-  test "create succeeds with with duplicate name with ensure_unique_name" do
-    permit_unsigned_manifests
-    authorize_with :admin
-    manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
-    post :create, {
-      collection: {
-        owner_uuid: 'zzzzz-tpzed-000000000000000',
-        manifest_text: manifest_text,
-        portable_data_hash: "d30fe8ae534397864cb96c544f4cf102+47",
-        name: "foo_file"
-      },
-      ensure_unique_name: true
-    }
-    assert_response :success
-    resp = JSON.parse(@response.body)
-    assert_equal 'foo_file (2)', resp['name']
+  [false, true].each do |unsigned|
+    test "create with duplicate name, ensure_unique_name, unsigned=#{unsigned}" do
+      permit_unsigned_manifests unsigned
+      authorize_with :active
+      manifest_text = ". acbd18db4cc2f85cedef654fccc4a4d8+3 0:0:foo.txt\n"
+      if !unsigned
+        manifest_text = Collection.sign_manifest manifest_text, api_token(:active)
+      end
+      post :create, {
+        collection: {
+          owner_uuid: users(:active).uuid,
+          manifest_text: manifest_text,
+          name: "owned_by_active"
+        },
+        ensure_unique_name: true
+      }
+      assert_response :success
+      assert_equal 'owned_by_active (2)', json_response['name']
+    end
   end
 
   test "create with owner_uuid set to group i can_manage" do
@@ -303,12 +347,12 @@ EOS
   test "search collections with 'any' operator" do
     authorize_with :active
     get :index, {
-      where: { any: ['contains', '7f9102c395f4ffc5e3'] }
+      where: { any: ['contains', 'd0bc8c7f34be170a7b7b'] }
     }
     assert_response :success
     found = assigns(:objects).collect(&:portable_data_hash)
-    assert_equal 2, found.count
-    assert_equal true, !!found.index('1f4b0bc7583c2a7f9102c395f4ffc5e3+45')
+    assert_equal 1, found.count
+    assert_equal true, !!found.index('5bd9c1ad0bc8c7f34be170a7b7b39089+45')
   end
 
   [false, true].each do |permit_unsigned|
@@ -544,6 +588,7 @@ EOS
   end
 
   test 'Reject manifest with unsigned blob' do
+    permit_unsigned_manifests false
     authorize_with :active
     unsigned_manifest = ". 0cc175b9c0f1b6a831c399e269772661+1 0:1:a.txt\n"
     manifest_uuid = Digest::MD5.hexdigest(unsigned_manifest)
@@ -616,4 +661,35 @@ EOS
     }
     assert_response :success
   end
+
+  test "get collection and verify that file_names is not included" do
+    authorize_with :active
+    get :show, {id: collections(:foo_file).uuid}
+    assert_response :success
+    assert_equal collections(:foo_file).uuid, json_response['uuid']
+    assert_nil json_response['file_names']
+    assert json_response['manifest_text']
+  end
+
+  [
+    [2**8, :success],
+    [2**18, 422],
+  ].each do |description_size, expected_response|
+    test "create collection with description size #{description_size}
+          and expect response #{expected_response}" do
+      authorize_with :active
+
+      description = 'here is a collection with a very large description'
+      while description.length < description_size
+        description = description + description
+      end
+
+      post :create, collection: {
+        manifest_text: ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:foo.txt\n",
+        description: description,
+      }
+
+      assert_response expected_response
+    end
+  end
 end