diff options
Diffstat (limited to 'activerecord/test/cases/connection_adapters')
7 files changed, 934 insertions, 0 deletions
diff --git a/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb b/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb new file mode 100644 index 0000000000..72838ff56b --- /dev/null +++ b/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require "cases/helper" + +module ActiveRecord + module ConnectionAdapters + class AdapterLeasingTest < ActiveRecord::TestCase + class Pool < ConnectionPool + def insert_connection_for_test!(c) + synchronize do + adopt_connection(c) + @available.add c + end + end + end + + def setup + @adapter = AbstractAdapter.new nil, nil + end + + def test_in_use? + assert_not @adapter.in_use?, "adapter is not in use" + assert @adapter.lease, "lease adapter" + assert @adapter.in_use?, "adapter is in use" + end + + def test_lease_twice + assert @adapter.lease, "should lease adapter" + assert_raises(ActiveRecordError) do + @adapter.lease + end + end + + def test_expire_mutates_in_use + assert @adapter.lease, "lease adapter" + assert @adapter.in_use?, "adapter is in use" + @adapter.expire + assert_not @adapter.in_use?, "adapter is in use" + end + + def test_close + pool = Pool.new(ConnectionSpecification.new("primary", {}, nil)) + pool.insert_connection_for_test! @adapter + @adapter.pool = pool + + # Make sure the pool marks the connection in use + assert_equal @adapter, pool.connection + assert_predicate @adapter, :in_use? + + # Close should put the adapter back in the pool + @adapter.close + assert_not_predicate @adapter, :in_use? + + assert_equal @adapter, pool.connection + end + end + end +end diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb new file mode 100644 index 0000000000..f4cc251fb9 --- /dev/null +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -0,0 +1,306 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/person" + +module ActiveRecord + module ConnectionAdapters + class ConnectionHandlerTest < ActiveRecord::TestCase + self.use_transactional_tests = false + + fixtures :people + + def setup + @handler = ConnectionHandler.new + @spec_name = "primary" + @pool = @handler.establish_connection(ActiveRecord::Base.configurations["arunit"]) + end + + def test_default_env_fall_back_to_default_env_when_rails_env_or_rack_env_is_empty_string + original_rails_env = ENV["RAILS_ENV"] + original_rack_env = ENV["RACK_ENV"] + ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "" + + assert_equal "default_env", ActiveRecord::ConnectionHandling::DEFAULT_ENV.call + ensure + ENV["RAILS_ENV"] = original_rails_env + ENV["RACK_ENV"] = original_rack_env + end + + def test_establish_connection_uses_spec_name + config = { "readonly" => { "adapter" => "sqlite3" } } + resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(config) + spec = resolver.spec(:readonly) + @handler.establish_connection(spec.to_hash) + + assert_not_nil @handler.retrieve_connection_pool("readonly") + ensure + @handler.remove_connection("readonly") + end + + def test_establish_connection_using_3_levels_config + previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env" + + config = { + "default_env" => { + "readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } + }, + "another_env" => { + "readonly" => { "adapter" => "sqlite3", "database" => "db/bad-readonly.sqlite3" }, + "primary" => { "adapter" => "sqlite3", "database" => "db/bad-primary.sqlite3" } + }, + "common" => { "adapter" => "sqlite3", "database" => "db/common.sqlite3" } + } + @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config + + @handler.establish_connection(:common) + @handler.establish_connection(:primary) + @handler.establish_connection(:readonly) + + assert_not_nil pool = @handler.retrieve_connection_pool("readonly") + assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + + assert_not_nil pool = @handler.retrieve_connection_pool("primary") + assert_equal "db/primary.sqlite3", pool.spec.config[:database] + + assert_not_nil pool = @handler.retrieve_connection_pool("common") + assert_equal "db/common.sqlite3", pool.spec.config[:database] + ensure + ActiveRecord::Base.configurations = @prev_configs + ENV["RAILS_ENV"] = previous_env + end + + def test_establish_connection_using_two_level_configurations + config = { "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } } + @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config + + @handler.establish_connection(:development) + + assert_not_nil pool = @handler.retrieve_connection_pool("development") + assert_equal "db/primary.sqlite3", pool.spec.config[:database] + ensure + ActiveRecord::Base.configurations = @prev_configs + end + + def test_establish_connection_using_top_level_key_in_two_level_config + config = { + "development" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" }, + "development_readonly" => { "adapter" => "sqlite3", "database" => "db/readonly.sqlite3" } + } + @prev_configs, ActiveRecord::Base.configurations = ActiveRecord::Base.configurations, config + + @handler.establish_connection(:development_readonly) + + assert_not_nil pool = @handler.retrieve_connection_pool("development_readonly") + assert_equal "db/readonly.sqlite3", pool.spec.config[:database] + ensure + ActiveRecord::Base.configurations = @prev_configs + end + + def test_retrieve_connection + assert @handler.retrieve_connection(@spec_name) + end + + def test_active_connections? + assert_not_predicate @handler, :active_connections? + assert @handler.retrieve_connection(@spec_name) + assert_predicate @handler, :active_connections? + @handler.clear_active_connections! + assert_not_predicate @handler, :active_connections? + end + + def test_retrieve_connection_pool + assert_not_nil @handler.retrieve_connection_pool(@spec_name) + end + + def test_retrieve_connection_pool_with_invalid_id + assert_nil @handler.retrieve_connection_pool("foo") + end + + def test_connection_pools + assert_equal([@pool], @handler.connection_pools) + end + + if Process.respond_to?(:fork) + def test_connection_pool_per_pid + object_id = ActiveRecord::Base.connection.object_id + + rd, wr = IO.pipe + rd.binmode + wr.binmode + + pid = fork { + rd.close + wr.write Marshal.dump ActiveRecord::Base.connection.object_id + wr.close + exit! + } + + wr.close + + Process.waitpid pid + assert_not_equal object_id, Marshal.load(rd.read) + rd.close + end + + def test_forked_child_doesnt_mangle_parent_connection + object_id = ActiveRecord::Base.connection.object_id + assert_predicate ActiveRecord::Base.connection, :active? + + rd, wr = IO.pipe + rd.binmode + wr.binmode + + pid = fork { + rd.close + if ActiveRecord::Base.connection.active? + wr.write Marshal.dump ActiveRecord::Base.connection.object_id + end + wr.close + + exit # allow finalizers to run + } + + wr.close + + Process.waitpid pid + assert_not_equal object_id, Marshal.load(rd.read) + rd.close + + assert_equal 3, ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM people") + end + + unless in_memory_db? + def test_forked_child_recovers_from_disconnected_parent + object_id = ActiveRecord::Base.connection.object_id + assert_predicate ActiveRecord::Base.connection, :active? + + rd, wr = IO.pipe + rd.binmode + wr.binmode + + outer_pid = fork { + ActiveRecord::Base.connection.disconnect! + + pid = fork { + rd.close + if ActiveRecord::Base.connection.active? + pair = [ActiveRecord::Base.connection.object_id, + ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM people")] + wr.write Marshal.dump pair + end + wr.close + + exit # allow finalizers to run + } + + Process.waitpid pid + } + + wr.close + + Process.waitpid outer_pid + child_id, child_count = Marshal.load(rd.read) + + assert_not_equal object_id, child_id + rd.close + + assert_equal 3, child_count + + # Outer connection is unaffected + assert_equal 6, ActiveRecord::Base.connection.select_value("SELECT 2 * COUNT(*) FROM people") + end + end + + def test_retrieve_connection_pool_copies_schema_cache_from_ancestor_pool + @pool.schema_cache = @pool.connection.schema_cache + @pool.schema_cache.add("posts") + + rd, wr = IO.pipe + rd.binmode + wr.binmode + + pid = fork { + rd.close + pool = @handler.retrieve_connection_pool(@spec_name) + wr.write Marshal.dump pool.schema_cache.size + wr.close + exit! + } + + wr.close + + Process.waitpid pid + assert_equal @pool.schema_cache.size, Marshal.load(rd.read) + rd.close + end + + def test_pool_from_any_process_for_uses_most_recent_spec + skip unless current_adapter?(:SQLite3Adapter) + + file = Tempfile.new "lol.sqlite3" + + rd, wr = IO.pipe + rd.binmode + wr.binmode + + pid = fork do + ActiveRecord::Base.configurations["arunit"]["database"] = file.path + ActiveRecord::Base.establish_connection(:arunit) + + pid2 = fork do + wr.write ActiveRecord::Base.connection_config[:database] + wr.close + end + + Process.waitpid pid2 + end + + Process.waitpid pid + + wr.close + + assert_equal file.path, rd.read + + rd.close + ensure + if file + file.close + file.unlink + end + end + + def test_a_class_using_custom_pool_and_switching_back_to_primary + klass2 = Class.new(Base) { def self.name; "klass2"; end } + + assert_same klass2.connection, ActiveRecord::Base.connection + + pool = klass2.establish_connection(ActiveRecord::Base.connection_pool.spec.config) + assert_same klass2.connection, pool.connection + refute_same klass2.connection, ActiveRecord::Base.connection + + klass2.remove_connection + + assert_same klass2.connection, ActiveRecord::Base.connection + end + + def test_connection_specification_name_should_fallback_to_parent + klassA = Class.new(Base) + klassB = Class.new(klassA) + + assert_equal klassB.connection_specification_name, klassA.connection_specification_name + klassA.connection_specification_name = "readonly" + assert_equal "readonly", klassB.connection_specification_name + end + + def test_remove_connection_should_not_remove_parent + klass2 = Class.new(Base) { def self.name; "klass2"; end } + klass2.remove_connection + refute_nil ActiveRecord::Base.connection + assert_same klass2.connection, ActiveRecord::Base.connection + end + end + end + end +end diff --git a/activerecord/test/cases/connection_adapters/connection_specification_test.rb b/activerecord/test/cases/connection_adapters/connection_specification_test.rb new file mode 100644 index 0000000000..f81b73c344 --- /dev/null +++ b/activerecord/test/cases/connection_adapters/connection_specification_test.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require "cases/helper" + +module ActiveRecord + module ConnectionAdapters + class ConnectionSpecificationTest < ActiveRecord::TestCase + def test_dup_deep_copy_config + spec = ConnectionSpecification.new("primary", { a: :b }, "bar") + assert_not_equal(spec.config.object_id, spec.dup.config.object_id) + end + end + end +end diff --git a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb new file mode 100644 index 0000000000..1b64324cc4 --- /dev/null +++ b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb @@ -0,0 +1,257 @@ +# frozen_string_literal: true + +require "cases/helper" + +module ActiveRecord + module ConnectionAdapters + class MergeAndResolveDefaultUrlConfigTest < ActiveRecord::TestCase + def setup + @previous_database_url = ENV.delete("DATABASE_URL") + @previous_rack_env = ENV.delete("RACK_ENV") + @previous_rails_env = ENV.delete("RAILS_ENV") + end + + teardown do + ENV["DATABASE_URL"] = @previous_database_url + ENV["RACK_ENV"] = @previous_rack_env + ENV["RAILS_ENV"] = @previous_rails_env + end + + def resolve_config(config) + ActiveRecord::ConnectionHandling::MergeAndResolveDefaultUrlConfig.new(config).resolve + end + + def resolve_spec(spec, config) + ConnectionSpecification::Resolver.new(resolve_config(config)).resolve(spec) + end + + def test_resolver_with_database_uri_and_current_env_symbol_key + ENV["DATABASE_URL"] = "postgres://localhost/foo" + config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } + actual = resolve_spec(:default_env, config) + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "default_env" } + assert_equal expected, actual + end + + def test_resolver_with_database_uri_and_current_env_symbol_key_and_rails_env + ENV["DATABASE_URL"] = "postgres://localhost/foo" + ENV["RAILS_ENV"] = "foo" + + config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } + actual = resolve_spec(:foo, config) + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "foo" } + assert_equal expected, actual + end + + def test_resolver_with_database_uri_and_current_env_symbol_key_and_rack_env + ENV["DATABASE_URL"] = "postgres://localhost/foo" + ENV["RACK_ENV"] = "foo" + + config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } + actual = resolve_spec(:foo, config) + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "foo" } + assert_equal expected, actual + end + + def test_resolver_with_database_uri_and_known_key + ENV["DATABASE_URL"] = "postgres://localhost/foo" + config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } } + actual = resolve_spec(:production, config) + expected = { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost", "name" => "production" } + assert_equal expected, actual + end + + def test_resolver_with_database_uri_and_unknown_symbol_key + ENV["DATABASE_URL"] = "postgres://localhost/foo" + config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } + assert_raises AdapterNotSpecified do + resolve_spec(:production, config) + end + end + + def test_resolver_with_database_uri_and_supplied_url + ENV["DATABASE_URL"] = "not-postgres://not-localhost/not_foo" + config = { "production" => { "adapter" => "also_not_postgres", "database" => "also_not_foo" } } + actual = resolve_spec("postgres://localhost/foo", config) + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" } + assert_equal expected, actual + end + + def test_jdbc_url + config = { "production" => { "url" => "jdbc:postgres://localhost/foo" } } + actual = resolve_config(config) + assert_equal config, actual + end + + def test_environment_does_not_exist_in_config_url_does_exist + ENV["DATABASE_URL"] = "postgres://localhost/foo" + config = { "not_default_env" => { "adapter" => "not_postgres", "database" => "not_foo" } } + actual = resolve_config(config) + expect_prod = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" } + assert_equal expect_prod, actual["default_env"] + end + + def test_url_with_hyphenated_scheme + ENV["DATABASE_URL"] = "ibm-db://localhost/foo" + config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } } + actual = resolve_spec(:default_env, config) + expected = { "adapter" => "ibm_db", "database" => "foo", "host" => "localhost", "name" => "default_env" } + assert_equal expected, actual + end + + def test_string_connection + config = { "default_env" => "postgres://localhost/foo" } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_url_sub_key + config = { "default_env" => { "url" => "postgres://localhost/foo" } } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_hash + config = { "production" => { "adapter" => "postgres", "database" => "foo" } } + actual = resolve_config(config) + assert_equal config, actual + end + + def test_blank + config = {} + actual = resolve_config(config) + assert_equal config, actual + end + + def test_blank_with_database_url + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = {} + actual = resolve_config(config) + expected = { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" } + assert_equal expected, actual["default_env"] + assert_nil actual["production"] + assert_nil actual["development"] + assert_nil actual["test"] + assert_nil actual[:default_env] + assert_nil actual[:production] + assert_nil actual[:development] + assert_nil actual[:test] + end + + def test_blank_with_database_url_with_rails_env + ENV["RAILS_ENV"] = "not_production" + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = {} + actual = resolve_config(config) + expected = { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" } + + assert_equal expected, actual["not_production"] + assert_nil actual["production"] + assert_nil actual["default_env"] + assert_nil actual["development"] + assert_nil actual["test"] + assert_nil actual[:default_env] + assert_nil actual[:not_production] + assert_nil actual[:production] + assert_nil actual[:development] + assert_nil actual[:test] + end + + def test_blank_with_database_url_with_rack_env + ENV["RACK_ENV"] = "not_production" + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = {} + actual = resolve_config(config) + expected = { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" } + + assert_equal expected, actual["not_production"] + assert_nil actual["production"] + assert_nil actual["default_env"] + assert_nil actual["development"] + assert_nil actual["test"] + assert_nil actual[:default_env] + assert_nil actual[:not_production] + assert_nil actual[:production] + assert_nil actual[:development] + assert_nil actual[:test] + end + + def test_database_url_with_ipv6_host_and_port + ENV["DATABASE_URL"] = "postgres://[::1]:5454/foo" + + config = {} + actual = resolve_config(config) + expected = { "adapter" => "postgresql", + "database" => "foo", + "host" => "::1", + "port" => 5454 } + assert_equal expected, actual["default_env"] + end + + def test_url_sub_key_with_database_url + ENV["DATABASE_URL"] = "NOT-POSTGRES://localhost/NOT_FOO" + + config = { "default_env" => { "url" => "postgres://localhost/foo" } } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_merge_no_conflicts_with_database_url + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = { "default_env" => { "pool" => "5" } } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost", + "pool" => "5" + } + } + assert_equal expected, actual + end + + def test_merge_conflicts_with_database_url + ENV["DATABASE_URL"] = "postgres://localhost/foo" + + config = { "default_env" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } } + actual = resolve_config(config) + expected = { "default_env" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost", + "pool" => "5" + } + } + assert_equal expected, actual + end + end + end +end diff --git a/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb new file mode 100644 index 0000000000..02e76ce146 --- /dev/null +++ b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require "cases/helper" +require "support/connection_helper" + +if current_adapter?(:Mysql2Adapter) + module ActiveRecord + module ConnectionAdapters + class MysqlTypeLookupTest < ActiveRecord::TestCase + include ConnectionHelper + + setup do + @connection = ActiveRecord::Base.connection + end + + def teardown + reset_connection + end + + def test_boolean_types + emulate_booleans(true) do + assert_lookup_type :boolean, "tinyint(1)" + assert_lookup_type :boolean, "TINYINT(1)" + end + end + + def test_string_types + assert_lookup_type :string, "enum('one', 'two', 'three')" + assert_lookup_type :string, "ENUM('one', 'two', 'three')" + assert_lookup_type :string, "set('one', 'two', 'three')" + assert_lookup_type :string, "SET('one', 'two', 'three')" + end + + def test_set_type_with_value_matching_other_type + assert_lookup_type :string, "SET('unicode', '8bit', 'none', 'time')" + end + + def test_enum_type_with_value_matching_other_type + assert_lookup_type :string, "ENUM('unicode', '8bit', 'none')" + end + + def test_binary_types + assert_lookup_type :binary, "bit" + assert_lookup_type :binary, "BIT" + end + + def test_integer_types + emulate_booleans(false) do + assert_lookup_type :integer, "tinyint(1)" + assert_lookup_type :integer, "TINYINT(1)" + assert_lookup_type :integer, "year" + assert_lookup_type :integer, "YEAR" + end + end + + private + + def assert_lookup_type(type, lookup) + cast_type = @connection.send(:type_map).lookup(lookup) + assert_equal type, cast_type.type + end + + def emulate_booleans(value) + old_emulate_booleans = @connection.emulate_booleans + change_emulate_booleans(value) + yield + ensure + change_emulate_booleans(old_emulate_booleans) + end + + def change_emulate_booleans(value) + @connection.emulate_booleans = value + @connection.clear_cache! + end + end + end + end +end diff --git a/activerecord/test/cases/connection_adapters/schema_cache_test.rb b/activerecord/test/cases/connection_adapters/schema_cache_test.rb new file mode 100644 index 0000000000..67496381d1 --- /dev/null +++ b/activerecord/test/cases/connection_adapters/schema_cache_test.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require "cases/helper" + +module ActiveRecord + module ConnectionAdapters + class SchemaCacheTest < ActiveRecord::TestCase + def setup + connection = ActiveRecord::Base.connection + @cache = SchemaCache.new connection + end + + def test_primary_key + assert_equal "id", @cache.primary_keys("posts") + end + + def test_yaml_dump_and_load + @cache.columns("posts") + @cache.columns_hash("posts") + @cache.data_sources("posts") + @cache.primary_keys("posts") + + new_cache = YAML.load(YAML.dump(@cache)) + assert_no_queries do + assert_equal 12, new_cache.columns("posts").size + assert_equal 12, new_cache.columns_hash("posts").size + assert new_cache.data_sources("posts") + assert_equal "id", new_cache.primary_keys("posts") + end + end + + def test_yaml_loads_5_1_dump + body = File.open(schema_dump_path).read + cache = YAML.load(body) + + assert_no_queries do + assert_equal 11, cache.columns("posts").size + assert_equal 11, cache.columns_hash("posts").size + assert cache.data_sources("posts") + assert_equal "id", cache.primary_keys("posts") + end + end + + def test_primary_key_for_non_existent_table + assert_nil @cache.primary_keys("omgponies") + end + + def test_caches_columns + columns = @cache.columns("posts") + assert_equal columns, @cache.columns("posts") + end + + def test_caches_columns_hash + columns_hash = @cache.columns_hash("posts") + assert_equal columns_hash, @cache.columns_hash("posts") + end + + def test_clearing + @cache.columns("posts") + @cache.columns_hash("posts") + @cache.data_sources("posts") + @cache.primary_keys("posts") + + @cache.clear! + + assert_equal 0, @cache.size + end + + def test_dump_and_load + @cache.columns("posts") + @cache.columns_hash("posts") + @cache.data_sources("posts") + @cache.primary_keys("posts") + + @cache = Marshal.load(Marshal.dump(@cache)) + + assert_no_queries do + assert_equal 12, @cache.columns("posts").size + assert_equal 12, @cache.columns_hash("posts").size + assert @cache.data_sources("posts") + assert_equal "id", @cache.primary_keys("posts") + end + end + + def test_data_source_exist + assert @cache.data_source_exists?("posts") + assert_not @cache.data_source_exists?("foo") + end + + def test_clear_data_source_cache + @cache.clear_data_source_cache!("posts") + end + + private + + def schema_dump_path + "test/assets/schema_dump_5_1.yml" + end + end + end +end diff --git a/activerecord/test/cases/connection_adapters/type_lookup_test.rb b/activerecord/test/cases/connection_adapters/type_lookup_test.rb new file mode 100644 index 0000000000..1c79d776f0 --- /dev/null +++ b/activerecord/test/cases/connection_adapters/type_lookup_test.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true + +require "cases/helper" + +unless current_adapter?(:PostgreSQLAdapter) # PostgreSQL does not use type strings for lookup + module ActiveRecord + module ConnectionAdapters + class TypeLookupTest < ActiveRecord::TestCase + setup do + @connection = ActiveRecord::Base.connection + end + + def test_boolean_types + assert_lookup_type :boolean, "boolean" + assert_lookup_type :boolean, "BOOLEAN" + end + + def test_string_types + assert_lookup_type :string, "char" + assert_lookup_type :string, "varchar" + assert_lookup_type :string, "VARCHAR" + assert_lookup_type :string, "varchar(255)" + assert_lookup_type :string, "character varying" + end + + def test_binary_types + assert_lookup_type :binary, "binary" + assert_lookup_type :binary, "BINARY" + assert_lookup_type :binary, "blob" + assert_lookup_type :binary, "BLOB" + end + + def test_text_types + assert_lookup_type :text, "text" + assert_lookup_type :text, "TEXT" + assert_lookup_type :text, "clob" + assert_lookup_type :text, "CLOB" + end + + def test_date_types + assert_lookup_type :date, "date" + assert_lookup_type :date, "DATE" + end + + def test_time_types + assert_lookup_type :time, "time" + assert_lookup_type :time, "TIME" + end + + def test_datetime_types + assert_lookup_type :datetime, "datetime" + assert_lookup_type :datetime, "DATETIME" + assert_lookup_type :datetime, "timestamp" + assert_lookup_type :datetime, "TIMESTAMP" + end + + def test_decimal_types + assert_lookup_type :decimal, "decimal" + assert_lookup_type :decimal, "decimal(2,8)" + assert_lookup_type :decimal, "DECIMAL" + assert_lookup_type :decimal, "numeric" + assert_lookup_type :decimal, "numeric(2,8)" + assert_lookup_type :decimal, "NUMERIC" + assert_lookup_type :decimal, "number" + assert_lookup_type :decimal, "number(2,8)" + assert_lookup_type :decimal, "NUMBER" + end + + def test_float_types + assert_lookup_type :float, "float" + assert_lookup_type :float, "FLOAT" + assert_lookup_type :float, "double" + assert_lookup_type :float, "DOUBLE" + end + + def test_integer_types + assert_lookup_type :integer, "integer" + assert_lookup_type :integer, "INTEGER" + assert_lookup_type :integer, "tinyint" + assert_lookup_type :integer, "smallint" + assert_lookup_type :integer, "bigint" + end + + def test_bigint_limit + limit = @connection.send(:type_map).lookup("bigint").send(:_limit) + if current_adapter?(:OracleAdapter) + assert_equal 19, limit + else + assert_equal 8, limit + end + end + + def test_decimal_without_scale + if current_adapter?(:OracleAdapter) + { + decimal: %w{decimal(2) decimal(2,0) numeric(2) numeric(2,0)}, + integer: %w{number(2) number(2,0)} + } + else + { decimal: %w{decimal(2) decimal(2,0) numeric(2) numeric(2,0) number(2) number(2,0)} } + end.each do |expected_type, types| + types.each do |type| + cast_type = @connection.send(:type_map).lookup(type) + + assert_equal expected_type, cast_type.type + assert_equal 2, cast_type.cast(2.1) + end + end + end + + private + + def assert_lookup_type(type, lookup) + cast_type = @connection.send(:type_map).lookup(lookup) + assert_equal type, cast_type.type + end + end + end + end +end |