diff options
Diffstat (limited to 'activerecord/test/cases')
12 files changed, 297 insertions, 21 deletions
diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb index b4a776d04d..a75fdef698 100644 --- a/activerecord/test/cases/adapters/postgresql/range_test.rb +++ b/activerecord/test/cases/adapters/postgresql/range_test.rb @@ -232,6 +232,57 @@ _SQL end end + def test_create_tstzrange_preserve_usec + tstzrange = Time.parse("2010-01-01 14:30:00.670277 +0100")...Time.parse("2011-02-02 14:30:00.745125 CDT") + round_trip(@new_range, :tstz_range, tstzrange) + assert_equal @new_range.tstz_range, tstzrange + assert_equal @new_range.tstz_range, Time.parse("2010-01-01 13:30:00.670277 UTC")...Time.parse("2011-02-02 19:30:00.745125 UTC") + end + + def test_update_tstzrange_preserve_usec + assert_equal_round_trip(@first_range, :tstz_range, + Time.parse("2010-01-01 14:30:00.245124 CDT")...Time.parse("2011-02-02 14:30:00.451274 CET")) + assert_nil_round_trip(@first_range, :tstz_range, + Time.parse("2010-01-01 14:30:00.245124 +0100")...Time.parse("2010-01-01 13:30:00.245124 +0000")) + end + + def test_create_tsrange_preseve_usec + tz = ::ActiveRecord::Base.default_timezone + assert_equal_round_trip(@new_range, :ts_range, + Time.send(tz, 2010, 1, 1, 14, 30, 0, 125435)...Time.send(tz, 2011, 2, 2, 14, 30, 0, 225435)) + end + + def test_update_tsrange_preserve_usec + tz = ::ActiveRecord::Base.default_timezone + assert_equal_round_trip(@first_range, :ts_range, + Time.send(tz, 2010, 1, 1, 14, 30, 0, 142432)...Time.send(tz, 2011, 2, 2, 14, 30, 0, 224242)) + assert_nil_round_trip(@first_range, :ts_range, + Time.send(tz, 2010, 1, 1, 14, 30, 0, 142432)...Time.send(tz, 2010, 1, 1, 14, 30, 0, 142432)) + end + + def test_timezone_awareness_tsrange_preserve_usec + tz = "Pacific Time (US & Canada)" + + in_time_zone tz do + PostgresqlRange.reset_column_information + time_string = "2017-09-26 07:30:59.132451 -0700" + time = Time.zone.parse(time_string) + assert time.usec > 0 + + record = PostgresqlRange.new(ts_range: time_string..time_string) + assert_equal time..time, record.ts_range + assert_equal ActiveSupport::TimeZone[tz], record.ts_range.begin.time_zone + assert_equal time.usec, record.ts_range.begin.usec + + record.save! + record.reload + + assert_equal time..time, record.ts_range + assert_equal ActiveSupport::TimeZone[tz], record.ts_range.begin.time_zone + assert_equal time.usec, record.ts_range.begin.usec + end + end + def test_create_numrange assert_equal_round_trip(@new_range, :num_range, BigDecimal.new("0.5")...BigDecimal.new("1")) diff --git a/activerecord/test/cases/adapters/postgresql/serial_test.rb b/activerecord/test/cases/adapters/postgresql/serial_test.rb index 3c020a88d0..df7875dbf2 100644 --- a/activerecord/test/cases/adapters/postgresql/serial_test.rb +++ b/activerecord/test/cases/adapters/postgresql/serial_test.rb @@ -86,3 +86,39 @@ class PostgresqlBigSerialTest < ActiveRecord::PostgreSQLTestCase assert_match %r{t\.bigint\s+"serials_id",\s+default: -> \{ "nextval\('postgresql_big_serials_id_seq'::regclass\)" \}$}, output end end + +module SequenceNameDetectionTestCases + class CollidedSequenceNameTest < ActiveRecord::PostgreSQLTestCase + include SchemaDumpingHelper + + def setup + @connection = ActiveRecord::Base.connection + @connection.create_table :foo_bar, force: true do |t| + t.serial :baz_id + end + @connection.create_table :foo, force: true do |t| + t.serial :bar_id + t.bigserial :bar_baz_id + end + end + + def teardown + @connection.drop_table :foo_bar, if_exists: true + @connection.drop_table :foo, if_exists: true + end + + def test_serial_columns + columns = @connection.columns(:foo) + columns.each do |column| + assert_equal :integer, column.type + assert column.serial? + end + end + + def test_schema_dump_with_collided_sequence_name + output = dump_table_schema "foo" + assert_match %r{t\.serial\s+"bar_id",\s+null: false$}, output + assert_match %r{t\.bigserial\s+"bar_baz_id",\s+null: false$}, output + end + end +end diff --git a/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb b/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb index 449023b6eb..8212ed4263 100644 --- a/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb +++ b/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb @@ -30,6 +30,6 @@ class PostgresqlTypeLookupTest < ActiveRecord::PostgreSQLTestCase big_range = 0..123456789123456789 assert_raises(ActiveModel::RangeError) { int_range.serialize(big_range) } - assert_equal "[0,123456789123456789]", bigint_range.serialize(big_range) + assert_equal "[0,123456789123456789]", @connection.type_cast(bigint_range.serialize(big_range)) end end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 0ea8ef5cea..2d67c57cfb 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -1019,14 +1019,6 @@ class AttributeMethodsTest < ActiveRecord::TestCase ActiveRecord::Base.time_zone_aware_types = old_types end - def cached_columns - Topic.columns.map(&:name) - end - - def time_related_columns_on_topic - Topic.columns.select { |c| [:time, :date, :datetime, :timestamp].include?(c.type) } - end - def privatize(method_signature) @target.class_eval(<<-private_method, __FILE__, __LINE__ + 1) private diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index 29a25b4461..2caf2a63d4 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -108,12 +108,14 @@ module ActiveRecord assert_equal 6, klass.attribute_types.length assert_equal 6, klass.column_defaults.length + assert_equal 6, klass.attribute_names.length assert_not klass.attribute_types.include?("wibble") klass.attribute :wibble, Type::Value.new assert_equal 7, klass.attribute_types.length assert_equal 7, klass.column_defaults.length + assert_equal 7, klass.attribute_names.length assert_includes klass.attribute_types, "wibble" end diff --git a/activerecord/test/cases/comment_test.rb b/activerecord/test/cases/comment_test.rb index 1bcafd4b55..584e03d196 100644 --- a/activerecord/test/cases/comment_test.rb +++ b/activerecord/test/cases/comment_test.rb @@ -142,5 +142,27 @@ if ActiveRecord::Base.connection.supports_comments? assert_match %r[t\.string\s+"absent_comment"\n], output assert_no_match %r[t\.string\s+"absent_comment", comment:\n], output end + + def test_change_table_comment + @connection.change_table_comment :commenteds, "Edited table comment" + assert_equal "Edited table comment", @connection.table_comment("commenteds") + end + + def test_change_table_comment_to_nil + @connection.change_table_comment :commenteds, nil + assert_nil @connection.table_comment("commenteds") + end + + def test_change_column_comment + @connection.change_column_comment :commenteds, :name, "Edited column comment" + column = Commented.columns_hash["name"] + assert_equal "Edited column comment", column.comment + end + + def test_change_column_comment_to_nil + @connection.change_column_comment :commenteds, :name, nil + column = Commented.columns_hash["name"] + assert_nil column.comment + end end end diff --git a/activerecord/test/cases/instrumentation_test.rb b/activerecord/test/cases/instrumentation_test.rb new file mode 100644 index 0000000000..e6e8468757 --- /dev/null +++ b/activerecord/test/cases/instrumentation_test.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/book" + +module ActiveRecord + class InstrumentationTest < ActiveRecord::TestCase + def test_payload_name_on_load + Book.create(name: "test book") + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + if event.payload[:sql].match "SELECT" + assert_equal "Book Load", event.payload[:name] + end + end + Book.first + ensure + ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber + end + + def test_payload_name_on_create + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + if event.payload[:sql].match "INSERT" + assert_equal "Book Create", event.payload[:name] + end + end + Book.create(name: "test book") + ensure + ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber + end + + def test_payload_name_on_update + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + if event.payload[:sql].match "UPDATE" + assert_equal "Book Update", event.payload[:name] + end + end + book = Book.create(name: "test book") + book.update_attribute(:name, "new name") + ensure + ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber + end + + def test_payload_name_on_update_all + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + if event.payload[:sql].match "UPDATE" + assert_equal "Book Update All", event.payload[:name] + end + end + Book.create(name: "test book") + Book.update_all(name: "new name") + ensure + ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber + end + + def test_payload_name_on_destroy + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args| + event = ActiveSupport::Notifications::Event.new(*args) + if event.payload[:sql].match "DELETE" + assert_equal "Book Destroy", event.payload[:name] + end + end + book = Book.create(name: "test book") + book.destroy + ensure + ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber + end + end +end diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb index 0b5e983f14..58bc558619 100644 --- a/activerecord/test/cases/migration/command_recorder_test.rb +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -213,6 +213,11 @@ module ActiveRecord assert_equal [:remove_index, [:table, { name: "new_index" }]], remove end + def test_invert_add_index_with_algorithm_option + remove = @recorder.inverse_of :add_index, [:table, :one, algorithm: :concurrently] + assert_equal [:remove_index, [:table, { column: :one, algorithm: :concurrently }]], remove + end + def test_invert_remove_index add = @recorder.inverse_of :remove_index, [:table, :one] assert_equal [:add_index, [:table, :one]], add diff --git a/activerecord/test/cases/migration/compatibility_test.rb b/activerecord/test/cases/migration/compatibility_test.rb index cb3b02c02a..1ae15eb439 100644 --- a/activerecord/test/cases/migration/compatibility_test.rb +++ b/activerecord/test/cases/migration/compatibility_test.rb @@ -199,6 +199,87 @@ class LegacyPrimaryKeyTest < ActiveRecord::TestCase assert_match %r{create_table "legacy_primary_keys", id: :integer, default: nil}, schema end + if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter) + def test_legacy_primary_key_in_create_table_should_be_integer + @migration = Class.new(ActiveRecord::Migration[5.0]) { + def change + create_table :legacy_primary_keys, id: false do |t| + t.primary_key :id + end + end + }.new + + @migration.migrate(:up) + + schema = dump_table_schema "legacy_primary_keys" + assert_match %r{create_table "legacy_primary_keys", id: :(?:integer|serial), (?!default: nil)}, schema + end + + def test_legacy_primary_key_in_change_table_should_be_integer + @migration = Class.new(ActiveRecord::Migration[5.0]) { + def change + create_table :legacy_primary_keys, id: false do |t| + t.integer :dummy + end + change_table :legacy_primary_keys do |t| + t.primary_key :id + end + end + }.new + + @migration.migrate(:up) + + schema = dump_table_schema "legacy_primary_keys" + assert_match %r{create_table "legacy_primary_keys", id: :(?:integer|serial), (?!default: nil)}, schema + end + + def test_add_column_with_legacy_primary_key_should_be_integer + @migration = Class.new(ActiveRecord::Migration[5.0]) { + def change + create_table :legacy_primary_keys, id: false do |t| + t.integer :dummy + end + add_column :legacy_primary_keys, :id, :primary_key + end + }.new + + @migration.migrate(:up) + + schema = dump_table_schema "legacy_primary_keys" + assert_match %r{create_table "legacy_primary_keys", id: :(?:integer|serial), (?!default: nil)}, schema + end + end + + def test_legacy_join_table_foreign_keys_should_be_integer + @migration = Class.new(ActiveRecord::Migration[5.0]) { + def change + create_join_table :apples, :bananas do |t| + end + end + }.new + + @migration.migrate(:up) + + schema = dump_table_schema "apples_bananas" + assert_match %r{integer "apple_id", null: false}, schema + assert_match %r{integer "banana_id", null: false}, schema + end + + def test_legacy_join_table_column_options_should_be_overwritten + @migration = Class.new(ActiveRecord::Migration[5.0]) { + def change + create_join_table :apples, :bananas, column_options: { type: :bigint } do |t| + end + end + }.new + + @migration.migrate(:up) + + schema = dump_table_schema "apples_bananas" + assert_match %r{bigint "apple_id", null: false}, schema + assert_match %r{bigint "banana_id", null: false}, schema + end + if current_adapter?(:Mysql2Adapter) def test_legacy_bigint_primary_key_should_be_auto_incremented @migration = Class.new(ActiveRecord::Migration[5.0]) { diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 170fd02b6f..6cbe18cc8c 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -70,10 +70,10 @@ class PersistenceTest < ActiveRecord::TestCase end def test_update_many - topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } } + topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" }, nil => {} } updated = Topic.update(topic_data.keys, topic_data.values) - assert_equal 2, updated.size + assert_equal [1, 2], updated.map(&:id) assert_equal "1 updated", Topic.find(1).content assert_equal "2 updated", Topic.find(2).content end @@ -81,9 +81,8 @@ class PersistenceTest < ActiveRecord::TestCase def test_class_level_update_is_affected_by_scoping topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } } - assert_raise(ActiveRecord::RecordNotFound) do - Topic.where("1=0").scoping { Topic.update(topic_data.keys, topic_data.values) } - end + assert_equal [], Topic.where("1=0").scoping { Topic.update(topic_data.keys, topic_data.values) } + assert_not_equal "1 updated", Topic.find(1).content assert_not_equal "2 updated", Topic.find(2).content end @@ -175,7 +174,7 @@ class PersistenceTest < ActiveRecord::TestCase clients = Client.all.merge!(order: "id").find([2, 3]) assert_difference("Client.count", -2) do - destroyed = Client.destroy([2, 3]).sort_by(&:id) + destroyed = Client.destroy([2, 3, nil]).sort_by(&:id) assert_equal clients, destroyed assert destroyed.all?(&:frozen?), "destroyed clients should be frozen" end @@ -917,7 +916,9 @@ class PersistenceTest < ActiveRecord::TestCase should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world") Topic.find(1).replies << should_be_destroyed_reply - Topic.destroy(1) + topic = Topic.destroy(1) + assert topic.destroyed? + assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) } assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) } end @@ -926,9 +927,8 @@ class PersistenceTest < ActiveRecord::TestCase should_not_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world") Topic.find(1).replies << should_not_be_destroyed_reply - assert_raise(ActiveRecord::RecordNotFound) do - Topic.where("1=0").scoping { Topic.destroy(1) } - end + assert_nil Topic.where("1=0").scoping { Topic.destroy(1) } + assert_nothing_raised { Topic.find(1) } assert_nothing_raised { Reply.find(should_not_be_destroyed_reply.id) } end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index ae1dc35bff..4edaf79e9a 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1806,6 +1806,10 @@ class RelationTest < ActiveRecord::TestCase assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).take end + test "arel_attribute respects a custom table" do + assert_equal [posts(:welcome)], custom_post_relation.ranked_by_comments.limit_by(1).to_a + end + test "#load" do relation = Post.all assert_queries(1) do @@ -1912,6 +1916,19 @@ class RelationTest < ActiveRecord::TestCase end end + test "#where with set" do + david = authors(:david) + mary = authors(:mary) + + authors = Author.where(name: ["David", "Mary"].to_set) + assert_equal [david, mary], authors + end + + test "#where with empty set" do + authors = Author.where(name: Set.new) + assert_empty authors + end + private def custom_post_relation table_alias = Post.arel_table.alias("omg_posts") diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index 6302e84884..ca1defa332 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -229,7 +229,6 @@ if current_adapter?(:PostgreSQLAdapter) ActiveRecord::Base.stubs(:connection).returns(@connection) ActiveRecord::Base.stubs(:establish_connection).returns(true) - Kernel.stubs(:system) end def teardown @@ -333,7 +332,6 @@ if current_adapter?(:PostgreSQLAdapter) ActiveRecord::Base.stubs(:connection).returns(@connection) ActiveRecord::Base.stubs(:establish_connection).returns(true) - Kernel.stubs(:system) end def test_structure_load |