19297: Fixes error check for edge case of limit=0, count=none. Adds test.
[arvados.git] / services / api / test / functional / arvados / v1 / filters_test.rb
index c76b94e4823bc7542a100cdfe6895757744c7347..3916d63c5ed1cce10cca11182b23682db512d8d1 100644 (file)
@@ -6,22 +6,22 @@ require 'test_helper'
 
 class Arvados::V1::FiltersTest < ActionController::TestCase
   test '"not in" filter passes null values' do
-    @controller = Arvados::V1::GroupsController.new
+    @controller = Arvados::V1::ContainerRequestsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['group_class', 'not in', ['project']] ],
-      controller: 'groups',
+    get :index, params: {
+      filters: [ ['container_uuid', 'not in', ['zzzzz-dz642-queuedcontainer', 'zzzzz-dz642-runningcontainr']] ],
+      controller: 'container_requests',
     }
     assert_response :success
     found = assigns(:objects)
-    assert_includes(found.collect(&:group_class), nil,
-                    "'group_class not in ['project']' filter should pass null")
+    assert_includes(found.collect(&:container_uuid), nil,
+                    "'container_uuid not in [zzzzz-dz642-queuedcontainer, zzzzz-dz642-runningcontainr]' filter should pass null")
   end
 
   test 'error message for non-array element in filters array' do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :active
-    get :index, {
+    get :index, params: {
       filters: [{bogus: 'filter'}],
     }
     assert_response 422
@@ -29,34 +29,14 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
                  json_response['errors'].join(' '))
   end
 
-  test 'error message for full text search on a specific column' do
+  test 'error message for unsupported full text search' do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :active
-    get :index, {
+    get :index, params: {
       filters: [['uuid', '@@', 'abcdef']],
     }
     assert_response 422
-    assert_match(/not supported/, json_response['errors'].join(' '))
-  end
-
-  test 'difficult characters in full text search' do
-    @controller = Arvados::V1::CollectionsController.new
-    authorize_with :active
-    get :index, {
-      filters: [['any', '@@', 'a|b"c']],
-    }
-    assert_response :success
-    # (Doesn't matter so much which results are returned.)
-  end
-
-  test 'array operand in full text search' do
-    @controller = Arvados::V1::CollectionsController.new
-    authorize_with :active
-    get :index, {
-      filters: [['any', '@@', ['abc', 'def']]],
-    }
-    assert_response 422
-    assert_match(/not supported/, json_response['errors'].join(' '))
+    assert_match(/no longer supported/, json_response['errors'].join(' '))
   end
 
   test 'api responses provide timestamps with nanoseconds' do
@@ -86,7 +66,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
       timestamp = mine.modified_at.strftime('%Y-%m-%dT%H:%M:%S.%NZ')
       @controller = Arvados::V1::CollectionsController.new
       authorize_with :active
-      get :index, {
+      get :index, params: {
         filters: [['modified_at', operator, timestamp],
                   ['uuid', '=', mine.uuid]],
       }
@@ -100,58 +80,6 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
     end
   end
 
-  test "full text search with count='none'" do
-    @controller = Arvados::V1::GroupsController.new
-    authorize_with :admin
-
-    get :contents, {
-      format: :json,
-      count: 'none',
-      limit: 1000,
-      filters: [['any', '@@', Rails.configuration.uuid_prefix]],
-    }
-
-    assert_response :success
-
-    all_objects = Hash.new(0)
-    json_response['items'].map{|o| o['kind']}.each{|t| all_objects[t] += 1}
-
-    assert_equal true, all_objects['arvados#group']>0
-    assert_equal true, all_objects['arvados#job']>0
-    assert_equal true, all_objects['arvados#pipelineInstance']>0
-    assert_equal true, all_objects['arvados#pipelineTemplate']>0
-
-    # Perform test again mimicking a second page request with:
-    # last_object_class = PipelineInstance
-    #   and hence groups and jobs should not be included in the response
-    # offset = 5, which means first 5 pipeline instances were already received in page 1
-    #   and hence the remaining pipeline instances and all other object types should be included in the response
-
-    @test_counter = 0  # Reset executed action counter
-
-    @controller = Arvados::V1::GroupsController.new
-
-    get :contents, {
-      format: :json,
-      count: 'none',
-      limit: 1000,
-      offset: '5',
-      last_object_class: 'PipelineInstance',
-      filters: [['any', '@@', Rails.configuration.uuid_prefix]],
-    }
-
-    assert_response :success
-
-    second_page = Hash.new(0)
-    json_response['items'].map{|o| o['kind']}.each{|t| second_page[t] += 1}
-
-    assert_equal false, second_page.include?('arvados#group')
-    assert_equal false, second_page.include?('arvados#job')
-    assert_equal true, second_page['arvados#pipelineInstance']>0
-    assert_equal all_objects['arvados#pipelineInstance'], second_page['arvados#pipelineInstance']+5
-    assert_equal true, second_page['arvados#pipelineTemplate']>0
-  end
-
   [['prop1', '=', 'value1', [:collection_with_prop1_value1], [:collection_with_prop1_value2, :collection_with_prop2_1]],
    ['prop1', '!=', 'value1', [:collection_with_prop1_value2, :collection_with_prop2_1], [:collection_with_prop1_value1]],
    ['prop1', 'exists', true, [:collection_with_prop1_value1, :collection_with_prop1_value2, :collection_with_prop1_value3, :collection_with_prop1_other1], [:collection_with_prop2_1]],
@@ -172,11 +100,18 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
    ['prop2', '<=', 5, [:collection_with_prop2_1, :collection_with_prop2_5], []],
    ['prop2', '>=', 1, [:collection_with_prop2_1, :collection_with_prop2_5], []],
    ['<http://schema.org/example>', '=', "value1", [:collection_with_uri_prop], []],
+   ['listprop', 'contains', 'elem1', [:collection_with_list_prop_odd, :collection_with_listprop_elem1], [:collection_with_list_prop_even]],
+   ['listprop', '=', 'elem1', [:collection_with_listprop_elem1], [:collection_with_list_prop_odd]],
+   ['listprop', 'contains', 5, [:collection_with_list_prop_odd], [:collection_with_list_prop_even, :collection_with_listprop_elem1]],
+   ['listprop', 'contains', 'elem2', [:collection_with_list_prop_even], [:collection_with_list_prop_odd, :collection_with_listprop_elem1]],
+   ['listprop', 'contains', 'ELEM2', [], [:collection_with_list_prop_even]],
+   ['listprop', 'contains', 'elem8', [], [:collection_with_list_prop_even]],
+   ['listprop', 'contains', 4, [:collection_with_list_prop_even], [:collection_with_list_prop_odd, :collection_with_listprop_elem1]],
   ].each do |prop, op, opr, inc, ex|
     test "jsonb filter properties.#{prop} #{op} #{opr})" do
       @controller = Arvados::V1::CollectionsController.new
       authorize_with :admin
-      get :index, {
+      get :index, params: {
             filters: SafeJSON.dump([ ["properties.#{prop}", op, opr] ]),
             limit: 1000
           }
@@ -196,7 +131,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb hash 'exists' and '!=' filter" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['properties.prop1', 'exists', true], ['properties.prop1', '!=', 'value1'] ]
     }
     assert_response :success
@@ -211,7 +146,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb array 'exists'" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['storage_classes_confirmed.default', 'exists', true] ]
     }
     assert_response :success
@@ -228,7 +163,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb hash alternate form 'exists' and '!=' filter" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['properties', 'exists', 'prop1'], ['properties.prop1', '!=', 'value1'] ]
     }
     assert_response :success
@@ -243,7 +178,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb array alternate form 'exists' filter" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['storage_classes_confirmed', 'exists', 'default'] ]
     }
     assert_response :success
@@ -260,7 +195,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb 'exists' must be boolean" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['properties.prop1', 'exists', nil] ]
     }
     assert_response 422
@@ -271,7 +206,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb checks column exists" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['puppies.prop1', '=', 'value1'] ]
     }
     assert_response 422
@@ -282,7 +217,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb checks column is valid" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['name.prop1', '=', 'value1'] ]
     }
     assert_response 422
@@ -293,7 +228,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test "jsonb invalid operator" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['properties.prop1', '###', 'value1'] ]
     }
     assert_response 422
@@ -301,10 +236,62 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
                  json_response['errors'].join(' '))
   end
 
+  test "groups contents with properties filter succeeds on objects with properties field" do
+    @controller = Arvados::V1::GroupsController.new
+    authorize_with :admin
+    get :contents, params: {
+      filters: [
+        ['properties', 'exists', 'foo'],
+        ['uuid', 'is_a', ["arvados#group","arvados#collection","arvados#containerRequest"]],
+      ]
+    }
+    assert_response 200
+    assert json_response['items'].length == 0
+  end
+
+  # Tests bug #19297
+  test "groups contents with properties filter succeeds on some objects with properties field" do
+    @controller = Arvados::V1::GroupsController.new
+    authorize_with :admin
+    get :contents, params: {
+      filters: [
+        ['properties', 'exists', 'foo'],
+        ['uuid', 'is_a', ["arvados#group","arvados#workflow"]],
+      ]
+    }
+    assert_response 200
+    assert json_response['items'].length == 0
+  end
+
+  # Tests bug #19297
+  test "groups contents with properties filter fails on objects without properties field" do
+    @controller = Arvados::V1::GroupsController.new
+    authorize_with :admin
+    get :contents, params: {
+      filters: [
+        ['properties', 'exists', 'foo'],
+        ['uuid', 'is_a', ["arvados#workflow"]],
+      ]
+    }
+    assert_response 422
+    assert_match(/Invalid attribute 'properties' for operator 'exists'.*on object type Workflow/, json_response['errors'].join(' '))
+  end
+
+  test "groups contents without filters and limit=0, count=none" do
+    @controller = Arvados::V1::GroupsController.new
+    authorize_with :admin
+    get :contents, params: {
+      limit: 0,
+      count: 'none',
+    }
+    assert_response 200
+    assert json_response['items'].length == 0
+  end
+
   test "replication_desired = 2" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: SafeJSON.dump([ ['replication_desired', '=', 2] ])
     }
     assert_response :success
@@ -313,4 +300,50 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
     assert_includes(found, collections(:replication_desired_2_confirmed_2).uuid)
   end
 
+  [
+    [1, "foo"],
+    [1, ["foo"]],
+    [1, ["bar"]],
+    [1, ["bar", "foo"]],
+    [0, ["foo", "qux"]],
+    [0, ["qux"]],
+    [nil, []],
+    [nil, [[]]],
+    [nil, [["bogus"]]],
+    [nil, [{"foo" => "bar"}]],
+    [nil, {"foo" => "bar"}],
+  ].each do |results, operand|
+    test "storage_classes_desired contains #{operand.inspect}" do
+      @controller = Arvados::V1::CollectionsController.new
+      authorize_with(:active)
+      c = Collection.create!(
+        manifest_text: "",
+        storage_classes_desired: ["foo", "bar", "baz"])
+      get :index, params: {
+            filters: [["storage_classes_desired", "contains", operand]],
+          }
+      if results.nil?
+        assert_response 422
+        next
+      end
+      assert_response :success
+      assert_equal results, json_response["items"].length
+      if results > 0
+        assert_equal c.uuid, json_response["items"][0]["uuid"]
+      end
+    end
+  end
+
+  test "collections properties contains top level key" do
+    @controller = Arvados::V1::CollectionsController.new
+    authorize_with(:active)
+    get :index, params: {
+          filters: [["properties", "contains", "prop1"]],
+        }
+    assert_response :success
+    assert_not_empty json_response["items"]
+    json_response["items"].each do |c|
+      assert c["properties"].has_key?("prop1")
+    end
+  end
 end