+
+ [['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], []],
+ ['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, 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, params: {
+ filters: [ ['properties.prop1', 'exists', true], ['properties.prop1', '!=', 'value1'] ]
+ }
+ assert_response :success
+ found = assigns(:objects).collect(&: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 array 'exists'" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ get :index, params: {
+ filters: [ ['storage_classes_confirmed.default', 'exists', true] ]
+ }
+ assert_response :success
+ found = assigns(:objects).collect(&: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 hash alternate form 'exists' and '!=' filter" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ get :index, params: {
+ filters: [ ['properties', 'exists', 'prop1'], ['properties.prop1', '!=', 'value1'] ]
+ }
+ assert_response :success
+ found = assigns(:objects).collect(&: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 array alternate form 'exists' filter" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ get :index, params: {
+ filters: [ ['storage_classes_confirmed', 'exists', 'default'] ]
+ }
+ assert_response :success
+ found = assigns(:objects).collect(&: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 'exists' must be boolean" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ get :index, params: {
+ filters: [ ['properties.prop1', 'exists', nil] ]
+ }
+ assert_response 422
+ assert_match(/Invalid operand '' for 'exists' must be true or false/,
+ json_response['errors'].join(' '))
+ end
+
+ test "jsonb checks column exists" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ get :index, params: {
+ filters: [ ['puppies.prop1', '=', 'value1'] ]
+ }
+ assert_response 422
+ assert_match(/Invalid attribute 'puppies' for subproperty filter/,
+ json_response['errors'].join(' '))
+ end
+
+ test "jsonb checks column is valid" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ get :index, params: {
+ filters: [ ['name.prop1', '=', 'value1'] ]
+ }
+ assert_response 422
+ assert_match(/Invalid attribute 'name' for subproperty filter/,
+ json_response['errors'].join(' '))
+ end
+
+ test "jsonb invalid operator" do
+ @controller = Arvados::V1::CollectionsController.new
+ authorize_with :admin
+ 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_includes(found, collections(:replication_desired_2_unconfirmed).uuid)
+ 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