X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/5923d0fa912c73e3725e52c869d72793304ae44a..0eb72b526bf8bbb011551ecf019f604e17a534f1:/services/api/test/unit/arvados_model_test.rb diff --git a/services/api/test/unit/arvados_model_test.rb b/services/api/test/unit/arvados_model_test.rb index 750b9334df..1e26798a26 100644 --- a/services/api/test/unit/arvados_model_test.rb +++ b/services/api/test/unit/arvados_model_test.rb @@ -1,3 +1,7 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + require 'test_helper' class ArvadosModelTest < ActiveSupport::TestCase @@ -53,15 +57,25 @@ class ArvadosModelTest < ActiveSupport::TestCase {'a' => {'foo' => {:bar => 'baz'}}}, {'a' => {'foo' => {'bar' => :baz}}}, {'a' => {'foo' => ['bar', :baz]}}, + ].each do |x| + test "prevent symbol keys in serialized db columns: #{x.inspect}" do + set_user_from_auth :active + link = Link.create!(link_class: 'test', + properties: x) + raw = ActiveRecord::Base.connection. + select_value("select properties from links where uuid='#{link.uuid}'") + refute_match(/:[fb]/, raw) + end + end + + [ {['foo'] => 'bar'}, + {'a' => {['foo', :foo] => 'bar'}}, + {'a' => {{'foo' => 'bar'} => 'bar'}}, {'a' => {['foo', :foo] => ['bar', 'baz']}}, ].each do |x| - test "refuse symbol keys in serialized attribute: #{x.inspect}" do - set_user_from_auth :admin_trustedclient - assert_nothing_raised do - Link.create!(link_class: 'test', - properties: {}) - end - assert_raises ActiveRecord::RecordInvalid do + test "refuse non-string keys in serialized db columns: #{x.inspect}" do + set_user_from_auth :active + assert_raises(ArgumentError) do Link.create!(link_class: 'test', properties: x) end @@ -81,10 +95,11 @@ class ArvadosModelTest < ActiveSupport::TestCase test "No HashWithIndifferentAccess in database" do set_user_from_auth :admin_trustedclient - assert_raises ActiveRecord::RecordInvalid do - Link.create!(link_class: 'test', - properties: {'foo' => 'bar'}.with_indifferent_access) - end + link = Link.create!(link_class: 'test', + properties: {'foo' => 'bar'}.with_indifferent_access) + raw = ActiveRecord::Base.connection. + select_value("select properties from links where uuid='#{link.uuid}'") + assert_equal '{"foo":"bar"}', raw end test "store long string" do @@ -131,12 +146,12 @@ class ArvadosModelTest < ActiveSupport::TestCase search_index_columns = table_class.searchable_columns('ilike') # Disappointing, but text columns aren't indexed yet. search_index_columns -= table_class.columns.select { |c| - c.type == :text or c.name == 'description' + c.type == :text or c.name == 'description' or c.name == 'file_names' }.collect(&:name) indexes = ActiveRecord::Base.connection.indexes(table) search_index_by_columns = indexes.select do |index| - index.columns == search_index_columns + index.columns.sort == search_index_columns.sort end search_index_by_name = indexes.select do |index| index.name == "#{table}_search_index" @@ -146,6 +161,51 @@ class ArvadosModelTest < ActiveSupport::TestCase end end + test "full text search index exists on models" do + indexes = {} + conn = ActiveRecord::Base.connection + conn.exec_query("SELECT i.relname as indname, + i.relowner as indowner, + idx.indrelid::regclass::text as table, + am.amname as indam, + idx.indkey, + ARRAY( + SELECT pg_get_indexdef(idx.indexrelid, k + 1, true) + FROM generate_subscripts(idx.indkey, 1) as k + ORDER BY k + ) as keys, + idx.indexprs IS NOT NULL as indexprs, + idx.indpred IS NOT NULL as indpred + FROM pg_index as idx + JOIN pg_class as i + ON i.oid = idx.indexrelid + JOIN pg_am as am + ON i.relam = am.oid + JOIN pg_namespace as ns + ON ns.oid = i.relnamespace + AND ns.nspname = ANY(current_schemas(false))").each do |idx| + if idx['keys'].match(/to_tsvector/) + indexes[idx['table']] ||= [] + indexes[idx['table']] << idx + end + end + fts_tables = ["collections", "container_requests", "groups", "jobs", + "pipeline_instances", "pipeline_templates", "workflows"] + fts_tables.each do |table| + table_class = table.classify.constantize + if table_class.respond_to?('full_text_searchable_columns') + expect = table_class.full_text_searchable_columns + ok = false + indexes[table].andand.each do |idx| + if expect == idx['keys'].scan(/COALESCE\(([A-Za-z_]+)/).flatten + ok = true + end + end + assert ok, "#{table} has no full-text index\nexpect: #{expect.inspect}\nfound: #{indexes[table].inspect}" + end + end + end + test "selectable_attributes includes database attributes" do assert_includes(Job.selectable_attributes, "success") end @@ -167,4 +227,34 @@ class ArvadosModelTest < ActiveSupport::TestCase assert_includes(attr_a, "uuid") refute_includes(attr_a, "success") end + + test 'create and retrieve using created_at time' do + set_user_from_auth :active + group = Group.create! name: 'test create and retrieve group' + assert group.valid?, "group is not valid" + + results = Group.where(created_at: group.created_at) + assert_includes results.map(&:uuid), group.uuid, + "Expected new group uuid in results when searched with its created_at timestamp" + end + + test 'create and update twice and expect different update times' do + set_user_from_auth :active + group = Group.create! name: 'test create and retrieve group' + assert group.valid?, "group is not valid" + + # update 1 + group.update_attributes!(name: "test create and update name 1") + results = Group.where(uuid: group.uuid) + assert_equal "test create and update name 1", results.first.name, "Expected name to be updated to 1" + updated_at_1 = results.first.updated_at.to_f + + # update 2 + group.update_attributes!(name: "test create and update name 2") + results = Group.where(uuid: group.uuid) + assert_equal "test create and update name 2", results.first.name, "Expected name to be updated to 2" + updated_at_2 = results.first.updated_at.to_f + + assert_equal true, (updated_at_2 > updated_at_1), "Expected updated time 2 to be newer than 1" + end end