Merge branch '14713-fix-master' refs #14713
[arvados.git] / services / api / test / functional / arvados / v1 / filters_test.rb
index 61b9e786b78ded4b719080e34a5ac5860a1eb9a2..d49fe7a3e647caec2215c6f911fe5e37b1d6a5ab 100644 (file)
@@ -8,7 +8,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test '"not in" filter passes null values' do
     @controller = Arvados::V1::GroupsController.new
     authorize_with :admin
-    get :index, {
+    get :index, params: {
       filters: [ ['group_class', 'not in', ['project']] ],
       controller: 'groups',
     }
@@ -21,7 +21,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   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
@@ -32,7 +32,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test 'error message for full text search on a specific column' do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :active
-    get :index, {
+    get :index, params: {
       filters: [['uuid', '@@', 'abcdef']],
     }
     assert_response 422
@@ -42,7 +42,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test 'difficult characters in full text search' do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :active
-    get :index, {
+    get :index, params: {
       filters: [['any', '@@', 'a|b"c']],
     }
     assert_response :success
@@ -52,7 +52,7 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
   test 'array operand in full text search' do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :active
-    get :index, {
+    get :index, params: {
       filters: [['any', '@@', ['abc', 'def']]],
     }
     assert_response 422
@@ -86,7 +86,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]],
       }
@@ -104,11 +104,11 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
     @controller = Arvados::V1::GroupsController.new
     authorize_with :admin
 
-    get :contents, {
+    get :contents, params: {
       format: :json,
       count: 'none',
       limit: 1000,
-      filters: [['any', '@@', Rails.configuration.uuid_prefix]],
+      filters: [['any', '@@', Rails.configuration.ClusterID]],
     }
 
     assert_response :success
@@ -131,13 +131,13 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
 
     @controller = Arvados::V1::GroupsController.new
 
-    get :contents, {
+    get :contents, params: {
       format: :json,
       count: 'none',
       limit: 1000,
       offset: '5',
       last_object_class: 'PipelineInstance',
-      filters: [['any', '@@', Rails.configuration.uuid_prefix]],
+      filters: [['any', '@@', Rails.configuration.ClusterID]],
     }
 
     assert_response :success
@@ -152,123 +152,164 @@ class Arvados::V1::FiltersTest < ActionController::TestCase
     assert_equal true, second_page['arvados#pipelineTemplate']>0
   end
 
-  test "jsonb '=' filter" do
+  [['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]],
+   ['prop1', 'exists', false, [:collection_with_prop2_1], [:collection_with_prop1_value1, :collection_with_prop1_value2, :collection_with_prop1_value3, :collection_with_prop1_other1]],
+   ['prop1', 'in', ['value1', 'value2'], [:collection_with_prop1_value1, :collection_with_prop1_value2], [:collection_with_prop1_value3, :collection_with_prop2_1]],
+   ['prop1', 'in', ['value1', 'valueX'], [:collection_with_prop1_value1], [:collection_with_prop1_value3, :collection_with_prop2_1]],
+   ['prop1', 'not in', ['value1', 'value2'], [:collection_with_prop1_value3, :collection_with_prop1_other1, :collection_with_prop2_1], [:collection_with_prop1_value1, :collection_with_prop1_value2]],
+   ['prop1', 'not in', ['value1', 'valueX'], [:collection_with_prop1_value2, :collection_with_prop1_value3, :collection_with_prop1_other1, :collection_with_prop2_1], [:collection_with_prop1_value1]],
+   ['prop1', '>', 'value2', [:collection_with_prop1_value3], [:collection_with_prop1_other1, :collection_with_prop1_value1]],
+   ['prop1', '<', 'value2', [:collection_with_prop1_other1, :collection_with_prop1_value1], [:collection_with_prop1_value2, :collection_with_prop1_value2]],
+   ['prop1', '<=', 'value2', [:collection_with_prop1_other1, :collection_with_prop1_value1, :collection_with_prop1_value2], [:collection_with_prop1_value3]],
+   ['prop1', '>=', 'value2', [:collection_with_prop1_value2, :collection_with_prop1_value3], [:collection_with_prop1_other1, :collection_with_prop1_value1]],
+   ['prop1', 'like', 'value%', [:collection_with_prop1_value1, :collection_with_prop1_value2, :collection_with_prop1_value3], [:collection_with_prop1_other1]],
+   ['prop1', 'like', '%1', [:collection_with_prop1_value1, :collection_with_prop1_other1], [:collection_with_prop1_value2, :collection_with_prop1_value3]],
+   ['prop1', 'ilike', 'VALUE%', [:collection_with_prop1_value1, :collection_with_prop1_value2, :collection_with_prop1_value3], [:collection_with_prop1_other1]],
+   ['prop2', '>',  1, [:collection_with_prop2_5], [:collection_with_prop2_1]],
+   ['prop2', '<',  5, [:collection_with_prop2_1], [:collection_with_prop2_5]],
+   ['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], []],
+  ].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, params: {
+            filters: SafeJSON.dump([ ["properties.#{prop}", op, opr] ]),
+            limit: 1000
+          }
+      assert_response :success
+      found = assigns(:objects).collect(&:uuid)
+
+      inc.each do |i|
+        assert_includes(found, collections(i).uuid)
+      end
+
+      ex.each do |e|
+        assert_not_includes(found, collections(e).uuid)
+      end
+    end
+  end
+
+  test "jsonb hash 'exists' and '!=' filter" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', '=', 'value1'] ]
+    get :index, params: {
+      filters: [ ['properties.prop1', 'exists', true], ['properties.prop1', '!=', 'value1'] ]
     }
     assert_response :success
     found = assigns(:objects).collect(&:uuid)
-    assert_equal(found, [collections(:collection_with_prop1_value1).uuid])
+    assert_equal found.length, 3
+    assert_not_includes(found, collections(:collection_with_prop1_value1).uuid)
+    assert_includes(found, collections(:collection_with_prop1_value2).uuid)
+    assert_includes(found, collections(:collection_with_prop1_value3).uuid)
+    assert_includes(found, collections(:collection_with_prop1_other1).uuid)
   end
 
-  test "jsonb '!=' filter" do
+  test "jsonb array 'exists'" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', '!=', 'value1'] ]
+    get :index, params: {
+      filters: [ ['storage_classes_confirmed.default', 'exists', true] ]
     }
     assert_response :success
     found = assigns(:objects).collect(&:uuid)
-    assert_operator found.length, :>, 1
-    assert_includes(found, collections(:collection_with_prop1_value2).uuid)
+    assert_equal 2, found.length
+    assert_not_includes(found,
+      collections(:storage_classes_desired_default_unconfirmed).uuid)
+    assert_includes(found,
+      collections(:storage_classes_desired_default_confirmed_default).uuid)
+    assert_includes(found,
+      collections(:storage_classes_desired_archive_confirmed_default).uuid)
   end
 
-  test "jsonb '?'" do
+  test "jsonb hash alternate form 'exists' and '!=' filter" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', '?', nil] ]
+    get :index, params: {
+      filters: [ ['properties', 'exists', 'prop1'], ['properties.prop1', '!=', 'value1'] ]
     }
     assert_response :success
     found = assigns(:objects).collect(&:uuid)
-    assert_equal found.length, 2
-    assert_includes(found, collections(:collection_with_prop1_value1).uuid)
+    assert_equal found.length, 3
+    assert_not_includes(found, collections(:collection_with_prop1_value1).uuid)
     assert_includes(found, collections(:collection_with_prop1_value2).uuid)
+    assert_includes(found, collections(:collection_with_prop1_value3).uuid)
+    assert_includes(found, collections(:collection_with_prop1_other1).uuid)
   end
 
-  test "jsonb '?' and '!=' filter" do
+  test "jsonb array alternate form 'exists' filter" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', '?', nil], ['properties.prop1', '!=', 'value1'] ]
+    get :index, params: {
+      filters: [ ['storage_classes_confirmed', 'exists', 'default'] ]
     }
     assert_response :success
     found = assigns(:objects).collect(&:uuid)
-    assert_equal(found, [collections(:collection_with_prop1_value2).uuid])
+    assert_equal 2, found.length
+    assert_not_includes(found,
+      collections(:storage_classes_desired_default_unconfirmed).uuid)
+    assert_includes(found,
+      collections(:storage_classes_desired_default_confirmed_default).uuid)
+    assert_includes(found,
+      collections(:storage_classes_desired_archive_confirmed_default).uuid)
   end
 
-  test "jsonb 'in' filter (match all)" do
+  test "jsonb 'exists' must be boolean" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', 'in', ['value1', 'value2']] ]
+    get :index, params: {
+      filters: [ ['properties.prop1', 'exists', nil] ]
     }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal found.length, 2
-    assert_includes(found, collections(:collection_with_prop1_value1).uuid)
-    assert_includes(found, collections(:collection_with_prop1_value2).uuid)
+    assert_response 422
+    assert_match(/Invalid operand '' for 'exists' must be true or false/,
+                 json_response['errors'].join(' '))
   end
 
-  test "jsonb 'in' filter (match some)" do
+  test "jsonb checks column exists" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', 'in', ['value1', 'value3']] ]
+    get :index, params: {
+      filters: [ ['puppies.prop1', '=', 'value1'] ]
     }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_equal(found, [collections(:collection_with_prop1_value1).uuid])
+    assert_response 422
+    assert_match(/Invalid attribute 'puppies' for subproperty filter/,
+                 json_response['errors'].join(' '))
   end
 
-  test "jsonb 'not in' filter (match all)" do
+  test "jsonb checks column is valid" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', 'not in', ['value1', 'value2']] ]
+    get :index, params: {
+      filters: [ ['name.prop1', '=', 'value1'] ]
     }
-    assert_response :success
-    found = assigns(:objects).collect(&:uuid)
-    assert_not_includes(found, collections(:collection_with_prop1_value1).uuid)
-    assert_not_includes(found, collections(:collection_with_prop1_value2).uuid)
+    assert_response 422
+    assert_match(/Invalid attribute 'name' for subproperty filter/,
+                 json_response['errors'].join(' '))
   end
 
-  test "jsonb 'not in' filter (match some)" do
+  test "jsonb invalid operator" do
     @controller = Arvados::V1::CollectionsController.new
     authorize_with :admin
-    get :index, {
-      filters: [ ['properties.prop1', 'not in', ['value1', 'value3']] ]
+    get :index, params: {
+      filters: [ ['properties.prop1', '###', 'value1'] ]
+    }
+    assert_response 422
+    assert_match(/Invalid operator for subproperty search '###'/,
+                 json_response['errors'].join(' '))
+  end
+
+  test "replication_desired = 2" do
+    @controller = Arvados::V1::CollectionsController.new
+    authorize_with :admin
+    get :index, params: {
+      filters: SafeJSON.dump([ ['replication_desired', '=', 2] ])
     }
     assert_response :success
     found = assigns(:objects).collect(&:uuid)
-    assert_not_includes(found, collections(:collection_with_prop1_value1).uuid)
-    assert_includes(found, collections(:collection_with_prop1_value2).uuid)
+    assert_includes(found, collections(:replication_desired_2_unconfirmed).uuid)
+    assert_includes(found, collections(:replication_desired_2_confirmed_2).uuid)
   end
-
-  # test "jsonb '>' filter (>3)" do
-  #   @controller = Arvados::V1::CollectionsController.new
-  #   authorize_with :admin
-  #   get :index, {
-  #     filters: [ ['properties.prop2', '>', 3] ]
-  #   }
-  #   assert_response :success
-  #   found = assigns(:objects).collect(&:uuid)
-  #   assert_not_includes(found, collections(:collection_with_prop2_1).uuid)
-  #   assert_includes(found, collections(:collection_with_prop2_5).uuid)
-  # end
-
-  # test "jsonb '>' filter (>'value1')" do
-  #   @controller = Arvados::V1::CollectionsController.new
-  #   authorize_with :admin
-  #   get :index, {
-  #     filters: [ ['properties.prop1', '>', "value1"] ]
-  #   }
-  #   assert_response :success
-  #   found = assigns(:objects).collect(&:uuid)
-  #   assert_not_includes(found, collections(:collection_with_prop1_value1).uuid)
-  #   assert_includes(found, collections(:collection_with_prop1_value2).uuid)
-  # end
-
 end