X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/495a7df016f63ae348000b1c046f8e1c5f1c5903..664cbad59d3fff30efb7e19c73fa57120a7672b0:/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 676581470c..d07027721f 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 @@ -124,6 +139,7 @@ class ArvadosModelTest < ActiveSupport::TestCase test "search index exists on models that go into projects" do all_tables = ActiveRecord::Base.connection.tables all_tables.delete 'schema_migrations' + all_tables.delete 'permission_refresh_lock' all_tables.each do |table| table_class = table.classify.constantize @@ -147,23 +163,46 @@ class ArvadosModelTest < ActiveSupport::TestCase 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') - fts_index_columns = table_class.full_text_searchable_columns - index_columns = nil - indexes = ActiveRecord::Base.connection.indexes(table) - fts_index_by_columns = indexes.select do |index| - if index.columns.first.match(/to_tsvector/) - index_columns = index.columns.first.scan(/\((?[A-Za-z_]+)\,/).flatten! - index_columns.sort == fts_index_columns.sort - else - false + 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 !fts_index_by_columns.empty?, "#{table} has no FTS index with columns #{fts_index_columns}. Instead found FTS index with columns #{index_columns}" + assert ok, "#{table} has no full-text index\nexpect: #{expect.inspect}\nfound: #{indexes[table].inspect}" end end end @@ -219,4 +258,24 @@ class ArvadosModelTest < ActiveSupport::TestCase assert_equal true, (updated_at_2 > updated_at_1), "Expected updated time 2 to be newer than 1" end + + test 'jsonb column' do + set_user_from_auth :active + + c = Collection.create!(properties: {}) + assert_equal({}, c.properties) + + c.update_attributes(properties: {'foo' => 'foo'}) + c.reload + assert_equal({'foo' => 'foo'}, c.properties) + + c.update_attributes(properties: nil) + c.reload + assert_equal({}, c.properties) + + c.update_attributes(properties: {foo: 'bar'}) + assert_equal({'foo' => 'bar'}, c.properties) + c.reload + assert_equal({'foo' => 'bar'}, c.properties) + end end