aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r--activerecord/test/cases/adapters/mysql/active_schema_test.rb37
-rw-r--r--activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb1
-rw-r--r--activerecord/test/cases/adapters/mysql/table_options_test.rb42
-rw-r--r--activerecord/test/cases/adapters/mysql2/active_schema_test.rb37
-rw-r--r--activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb1
-rw-r--r--activerecord/test/cases/adapters/mysql2/table_options_test.rb42
-rw-r--r--activerecord/test/cases/adapters/postgresql/collation_test.rb53
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb4
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb11
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb28
-rw-r--r--activerecord/test/cases/autosave_association_test.rb12
-rw-r--r--activerecord/test/cases/callbacks_test.rb2
-rw-r--r--activerecord/test/cases/connection_adapters/adapter_leasing_test.rb6
-rw-r--r--activerecord/test/cases/connection_adapters/connection_handler_test.rb46
-rw-r--r--activerecord/test/cases/connection_management_test.rb23
-rw-r--r--activerecord/test/cases/connection_pool_test.rb187
-rw-r--r--activerecord/test/cases/disconnected_test.rb4
-rw-r--r--activerecord/test/cases/fixtures_test.rb12
-rw-r--r--activerecord/test/cases/inheritance_test.rb119
-rw-r--r--activerecord/test/cases/locking_test.rb10
-rw-r--r--activerecord/test/cases/migration/references_foreign_key_test.rb20
-rw-r--r--activerecord/test/cases/primary_keys_test.rb8
-rw-r--r--activerecord/test/cases/relations_test.rb8
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb20
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb12
-rw-r--r--activerecord/test/cases/tasks/mysql_rake_test.rb11
-rw-r--r--activerecord/test/cases/timestamp_test.rb11
-rw-r--r--activerecord/test/cases/type/integer_test.rb2
28 files changed, 647 insertions, 122 deletions
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
index 6577d56240..57eb5d0e18 100644
--- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
@@ -59,6 +59,43 @@ class ActiveSchemaTest < ActiveRecord::TestCase
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15, :using => :btree)
end
+ def test_index_in_create
+ def (ActiveRecord::Base.connection).table_exists?(*); false; end
+
+ %w(SPATIAL FULLTEXT UNIQUE).each do |type|
+ expected = "CREATE TABLE `people` (#{type} INDEX `index_people_on_last_name` (`last_name`) ) ENGINE=InnoDB"
+ actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t|
+ t.index :last_name, type: type
+ end
+ assert_equal expected, actual
+ end
+
+ expected = "CREATE TABLE `people` ( INDEX `index_people_on_last_name` USING btree (`last_name`(10)) ) ENGINE=InnoDB"
+ actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t|
+ t.index :last_name, length: 10, using: :btree
+ end
+ assert_equal expected, actual
+ end
+
+ def test_index_in_bulk_change
+ def (ActiveRecord::Base.connection).table_exists?(*); true; end
+ def (ActiveRecord::Base.connection).index_name_exists?(*); false; end
+
+ %w(SPATIAL FULLTEXT UNIQUE).each do |type|
+ expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)"
+ actual = ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
+ t.index :last_name, type: type
+ end
+ assert_equal expected, actual
+ end
+
+ expected = "ALTER TABLE `peaple` ADD INDEX `index_peaple_on_last_name` USING btree (`last_name`(10)), ALGORITHM = COPY"
+ actual = ActiveRecord::Base.connection.change_table(:peaple, bulk: true) do |t|
+ t.index :last_name, length: 10, using: :btree, algorithm: :copy
+ end
+ assert_equal expected, actual
+ end
+
def test_drop_table
assert_equal "DROP TABLE `people`", drop_table(:people)
end
diff --git a/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb
index 340fc95503..345122b1ad 100644
--- a/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb
+++ b/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb
@@ -1,5 +1,4 @@
require "cases/helper"
-require 'models/person'
class MysqlCaseSensitivityTest < ActiveRecord::TestCase
class CollationTest < ActiveRecord::Base
diff --git a/activerecord/test/cases/adapters/mysql/table_options_test.rb b/activerecord/test/cases/adapters/mysql/table_options_test.rb
new file mode 100644
index 0000000000..0e5b0e8aec
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql/table_options_test.rb
@@ -0,0 +1,42 @@
+require "cases/helper"
+require 'support/schema_dumping_helper'
+
+class MysqlTableOptionsTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def teardown
+ @connection.drop_table "mysql_table_options", if_exists: true
+ end
+
+ test "table options with ENGINE" do
+ @connection.create_table "mysql_table_options", force: true, options: "ENGINE=MyISAM"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{ENGINE=MyISAM}, options
+ end
+
+ test "table options with ROW_FORMAT" do
+ @connection.create_table "mysql_table_options", force: true, options: "ROW_FORMAT=REDUNDANT"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{ROW_FORMAT=REDUNDANT}, options
+ end
+
+ test "table options with CHARSET" do
+ @connection.create_table "mysql_table_options", force: true, options: "CHARSET=utf8mb4"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{CHARSET=utf8mb4}, options
+ end
+
+ test "table options with COLLATE" do
+ @connection.create_table "mysql_table_options", force: true, options: "COLLATE=utf8mb4_bin"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{COLLATE=utf8mb4_bin}, options
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
index e87cd3886a..0ea556d4fa 100644
--- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
@@ -59,6 +59,43 @@ class ActiveSchemaTest < ActiveRecord::TestCase
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15, :using => :btree)
end
+ def test_index_in_create
+ def (ActiveRecord::Base.connection).table_exists?(*); false; end
+
+ %w(SPATIAL FULLTEXT UNIQUE).each do |type|
+ expected = "CREATE TABLE `people` (#{type} INDEX `index_people_on_last_name` (`last_name`) ) ENGINE=InnoDB"
+ actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t|
+ t.index :last_name, type: type
+ end
+ assert_equal expected, actual
+ end
+
+ expected = "CREATE TABLE `people` ( INDEX `index_people_on_last_name` USING btree (`last_name`(10)) ) ENGINE=InnoDB"
+ actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t|
+ t.index :last_name, length: 10, using: :btree
+ end
+ assert_equal expected, actual
+ end
+
+ def test_index_in_bulk_change
+ def (ActiveRecord::Base.connection).table_exists?(*); true; end
+ def (ActiveRecord::Base.connection).index_name_exists?(*); false; end
+
+ %w(SPATIAL FULLTEXT UNIQUE).each do |type|
+ expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)"
+ actual = ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
+ t.index :last_name, type: type
+ end
+ assert_equal expected, actual
+ end
+
+ expected = "ALTER TABLE `peaple` ADD INDEX `index_peaple_on_last_name` USING btree (`last_name`(10)), ALGORITHM = COPY"
+ actual = ActiveRecord::Base.connection.change_table(:peaple, bulk: true) do |t|
+ t.index :last_name, length: 10, using: :btree, algorithm: :copy
+ end
+ assert_equal expected, actual
+ end
+
def test_drop_table
assert_equal "DROP TABLE `people`", drop_table(:people)
end
diff --git a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb
index 09bebf3071..ccf3d84a44 100644
--- a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb
@@ -1,5 +1,4 @@
require "cases/helper"
-require 'models/person'
class Mysql2CaseSensitivityTest < ActiveRecord::TestCase
class CollationTest < ActiveRecord::Base
diff --git a/activerecord/test/cases/adapters/mysql2/table_options_test.rb b/activerecord/test/cases/adapters/mysql2/table_options_test.rb
new file mode 100644
index 0000000000..0e5b0e8aec
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/table_options_test.rb
@@ -0,0 +1,42 @@
+require "cases/helper"
+require 'support/schema_dumping_helper'
+
+class MysqlTableOptionsTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def teardown
+ @connection.drop_table "mysql_table_options", if_exists: true
+ end
+
+ test "table options with ENGINE" do
+ @connection.create_table "mysql_table_options", force: true, options: "ENGINE=MyISAM"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{ENGINE=MyISAM}, options
+ end
+
+ test "table options with ROW_FORMAT" do
+ @connection.create_table "mysql_table_options", force: true, options: "ROW_FORMAT=REDUNDANT"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{ROW_FORMAT=REDUNDANT}, options
+ end
+
+ test "table options with CHARSET" do
+ @connection.create_table "mysql_table_options", force: true, options: "CHARSET=utf8mb4"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{CHARSET=utf8mb4}, options
+ end
+
+ test "table options with COLLATE" do
+ @connection.create_table "mysql_table_options", force: true, options: "COLLATE=utf8mb4_bin"
+ output = dump_table_schema("mysql_table_options")
+ options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
+ assert_match %r{COLLATE=utf8mb4_bin}, options
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/collation_test.rb b/activerecord/test/cases/adapters/postgresql/collation_test.rb
new file mode 100644
index 0000000000..17ef5f304c
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/collation_test.rb
@@ -0,0 +1,53 @@
+require "cases/helper"
+require 'support/schema_dumping_helper'
+
+class PostgresqlCollationTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ @connection.create_table :postgresql_collations, force: true do |t|
+ t.string :string_c, collation: 'C'
+ t.text :text_posix, collation: 'POSIX'
+ end
+ end
+
+ def teardown
+ @connection.drop_table :postgresql_collations, if_exists: true
+ end
+
+ test "string column with collation" do
+ column = @connection.columns(:postgresql_collations).find { |c| c.name == 'string_c' }
+ assert_equal :string, column.type
+ assert_equal 'C', column.collation
+ end
+
+ test "text column with collation" do
+ column = @connection.columns(:postgresql_collations).find { |c| c.name == 'text_posix' }
+ assert_equal :text, column.type
+ assert_equal 'POSIX', column.collation
+ end
+
+ test "add column with collation" do
+ @connection.add_column :postgresql_collations, :title, :string, collation: 'C'
+
+ column = @connection.columns(:postgresql_collations).find { |c| c.name == 'title' }
+ assert_equal :string, column.type
+ assert_equal 'C', column.collation
+ end
+
+ test "change column with collation" do
+ @connection.add_column :postgresql_collations, :description, :string
+ @connection.change_column :postgresql_collations, :description, :text, collation: 'POSIX'
+
+ column = @connection.columns(:postgresql_collations).find { |c| c.name == 'description' }
+ assert_equal :text, column.type
+ assert_equal 'POSIX', column.collation
+ end
+
+ test "schema dump includes collation" do
+ output = dump_table_schema("postgresql_collations")
+ assert_match %r{t.string\s+"string_c",\s+collation: "C"$}, output
+ assert_match %r{t.text\s+"text_posix",\s+collation: "POSIX"$}, output
+ end
+end
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 95d00ab3a9..ba90c61d65 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -124,9 +124,9 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
where("id = :inc", :inc => counter)
}
- has_many :comments, :class => comments
+ has_many :comments, :anonymous_class => comments
}
- belongs_to :post, :class => posts, :inverse_of => false
+ belongs_to :post, :anonymous_class => posts, :inverse_of => false
}
assert_equal 0, counter
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 171cfbde44..2c4e2a875c 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -119,9 +119,9 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
developer_project = Class.new(ActiveRecord::Base) {
self.table_name = 'developers_projects'
- belongs_to :developer, :class => dev
+ belongs_to :developer, :anonymous_class => dev
}
- has_many :developer_projects, :class => developer_project, :foreign_key => 'developer_id'
+ has_many :developer_projects, :anonymous_class => developer_project, :foreign_key => 'developer_id'
}
dev = developer.first
named = Developer.find(dev.id)
@@ -140,13 +140,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
comments = Class.new(ActiveRecord::Base) {
self.table_name = 'comments'
self.inheritance_column = 'not_there'
- belongs_to :post, :class => post
+ belongs_to :post, :anonymous_class => post
default_scope -> {
counter += 1
where("id = :inc", :inc => counter)
}
}
- has_many :comments, :class => comments, :foreign_key => 'post_id'
+ has_many :comments, :anonymous_class => comments, :foreign_key => 'post_id'
}
assert_equal 0, counter
post = posts.first
@@ -2131,11 +2131,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
car = Car.create!
original_child = FailedBulb.create!(car: car)
- assert_raise(ActiveRecord::RecordNotDestroyed) do
+ error = assert_raise(ActiveRecord::RecordNotDestroyed) do
car.failed_bulbs = [FailedBulb.create!]
end
assert_equal [original_child], car.reload.failed_bulbs
+ assert_equal "Failed to destroy the record", error.message
end
test 'updates counter cache when default scope is given' do
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 5f52c65412..190cef55c4 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -84,11 +84,11 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
subscriber = make_model "Subscriber"
subscriber.primary_key = 'nick'
- subscription.belongs_to :book, class: book
- subscription.belongs_to :subscriber, class: subscriber
+ subscription.belongs_to :book, anonymous_class: book
+ subscription.belongs_to :subscriber, anonymous_class: subscriber
- book.has_many :subscriptions, class: subscription
- book.has_many :subscribers, through: :subscriptions, class: subscriber
+ book.has_many :subscriptions, anonymous_class: subscription
+ book.has_many :subscribers, through: :subscriptions, anonymous_class: subscriber
anonbook = book.first
namebook = Book.find anonbook.id
@@ -154,10 +154,10 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
lesson_student = make_model 'LessonStudent'
lesson_student.table_name = 'lessons_students'
- lesson_student.belongs_to :lesson, :class => lesson
- lesson_student.belongs_to :student, :class => student
- lesson.has_many :lesson_students, :class => lesson_student
- lesson.has_many :students, :through => :lesson_students, :class => student
+ lesson_student.belongs_to :lesson, :anonymous_class => lesson
+ lesson_student.belongs_to :student, :anonymous_class => student
+ lesson.has_many :lesson_students, :anonymous_class => lesson_student
+ lesson.has_many :students, :through => :lesson_students, :anonymous_class => student
[lesson, lesson_student, student]
end
@@ -1040,14 +1040,6 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
end
- def test_save_should_not_raise_exception_when_join_record_has_errors
- repair_validations(Categorization) do
- Categorization.validate { |r| r.errors[:base] << 'Invalid Categorization' }
- c = Category.create(:name => 'Fishing', :authors => [Author.first])
- c.save
- end
- end
-
def test_assign_array_to_new_record_builds_join_records
c = Category.new(:name => 'Fishing', :authors => [Author.first])
assert_equal 1, c.categorizations.size
@@ -1072,11 +1064,11 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
end
- def test_create_bang_returns_falsy_when_join_record_has_errors
+ def test_save_returns_falsy_when_join_record_has_errors
repair_validations(Categorization) do
Categorization.validate { |r| r.errors[:base] << 'Invalid Categorization' }
c = Category.new(:name => 'Fishing', :authors => [Author.first])
- assert !c.save
+ assert_not c.save
end
end
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 8f0d7bd037..80b5a0004d 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -43,7 +43,7 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
reference = Class.new(ActiveRecord::Base) {
self.table_name = "references"
def self.name; 'Reference'; end
- belongs_to :person, autosave: true, class: person
+ belongs_to :person, autosave: true, anonymous_class: person
}
u = person.create!(first_name: 'cool')
@@ -1278,6 +1278,16 @@ module AutosaveAssociationOnACollectionAssociationTests
assert_equal new_names, @pirate.reload.send(@association_name).map(&:name)
end
+ def test_should_update_children_when_autosave_is_true_and_parent_is_new_but_child_is_not
+ parrot = Parrot.create!(name: "Polly")
+ parrot.name = "Squawky"
+ pirate = Pirate.new(parrots: [parrot], catchphrase: "Arrrr")
+
+ pirate.save!
+
+ assert_equal "Squawky", parrot.reload.name
+ end
+
def test_should_automatically_validate_the_associated_models
@pirate.send(@association_name).each { |child| child.name = '' }
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index 3ae4a6eade..73ac30e547 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -451,6 +451,7 @@ class CallbacksTest < ActiveRecord::TestCase
assert !david.save
exc = assert_raise(ActiveRecord::RecordNotSaved) { david.save! }
assert_equal exc.record, david
+ assert_equal "Failed to save the record", exc.message
end
david = ImmutableDeveloper.find(1)
@@ -494,6 +495,7 @@ class CallbacksTest < ActiveRecord::TestCase
assert !david.destroy
exc = assert_raise(ActiveRecord::RecordNotDestroyed) { david.destroy! }
assert_equal exc.record, david
+ assert_equal "Failed to destroy the record", exc.message
end
assert_not_nil ImmutableDeveloper.find_by_id(1)
diff --git a/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb b/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb
index 662e19f35e..580568c8ac 100644
--- a/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb
+++ b/activerecord/test/cases/connection_adapters/adapter_leasing_test.rb
@@ -6,7 +6,7 @@ module ActiveRecord
class Pool < ConnectionPool
def insert_connection_for_test!(c)
synchronize do
- @connections << c
+ adopt_connection(c)
@available.add c
end
end
@@ -24,7 +24,9 @@ module ActiveRecord
def test_lease_twice
assert @adapter.lease, 'should lease adapter'
- assert_not @adapter.lease, 'should not lease adapter'
+ assert_raises(ActiveRecordError) do
+ @adapter.lease
+ end
end
def test_expire_mutates_in_use
diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
index b72f8ca88c..9b1865e8bb 100644
--- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb
+++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
@@ -46,6 +46,52 @@ module ActiveRecord
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_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(@klass)
+ 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
+ end
end
end
end
diff --git a/activerecord/test/cases/connection_management_test.rb b/activerecord/test/cases/connection_management_test.rb
index bab624b78a..dff6ea0fb0 100644
--- a/activerecord/test/cases/connection_management_test.rb
+++ b/activerecord/test/cases/connection_management_test.rb
@@ -26,29 +26,6 @@ module ActiveRecord
assert ActiveRecord::Base.connection_handler.active_connections?
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
- end
-
def test_app_delegation
manager = ConnectionManagement.new(@app)
diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb
index aa50efc979..c905772193 100644
--- a/activerecord/test/cases/connection_pool_test.rb
+++ b/activerecord/test/cases/connection_pool_test.rb
@@ -100,7 +100,7 @@ module ActiveRecord
t = Thread.new { @pool.checkout }
# make sure our thread is in the timeout section
- Thread.pass until t.status == "sleep"
+ Thread.pass until @pool.num_waiting_in_queue == 1
connection = cs.first
connection.close
@@ -112,7 +112,7 @@ module ActiveRecord
t = Thread.new { @pool.checkout }
# make sure our thread is in the timeout section
- Thread.pass until t.status == "sleep"
+ Thread.pass until @pool.num_waiting_in_queue == 1
connection = cs.first
@pool.remove connection
@@ -234,7 +234,7 @@ module ActiveRecord
mutex.synchronize { errors << e }
end
}
- Thread.pass until t.status == "sleep"
+ Thread.pass until @pool.num_waiting_in_queue == i
t
end
@@ -271,7 +271,7 @@ module ActiveRecord
mutex.synchronize { errors << e }
end
}
- Thread.pass until t.status == "sleep"
+ Thread.pass until @pool.num_waiting_in_queue == i
t
end
@@ -341,6 +341,185 @@ module ActiveRecord
handler.establish_connection anonymous, nil
}
end
+
+ def test_pool_sets_connection_schema_cache
+ connection = pool.checkout
+ schema_cache = SchemaCache.new connection
+ schema_cache.add(:posts)
+ pool.schema_cache = schema_cache
+
+ pool.with_connection do |conn|
+ assert_not_same pool.schema_cache, conn.schema_cache
+ assert_equal pool.schema_cache.size, conn.schema_cache.size
+ assert_same pool.schema_cache.columns(:posts), conn.schema_cache.columns(:posts)
+ end
+
+ pool.checkin connection
+ end
+
+ def test_concurrent_connection_establishment
+ assert_operator @pool.connections.size, :<=, 1
+
+ all_threads_in_new_connection = ActiveSupport::Concurrency::Latch.new(@pool.size - @pool.connections.size)
+ all_go = ActiveSupport::Concurrency::Latch.new
+
+ @pool.singleton_class.class_eval do
+ define_method(:new_connection) do
+ all_threads_in_new_connection.release
+ all_go.await
+ super()
+ end
+ end
+
+ connecting_threads = []
+ @pool.size.times do
+ connecting_threads << Thread.new { @pool.checkout }
+ end
+
+ begin
+ Timeout.timeout(5) do
+ # the kernel of the whole test is here, everything else is just scaffolding,
+ # this latch will not be released unless conn. pool allows for concurrent
+ # connection creation
+ all_threads_in_new_connection.await
+ end
+ rescue Timeout::Error
+ flunk 'pool unable to establish connections concurrently or implementation has ' <<
+ 'changed, this test then needs to patch a different :new_connection method'
+ ensure
+ # clean up the threads
+ all_go.release
+ connecting_threads.map(&:join)
+ end
+ end
+
+ def test_non_bang_disconnect_and_clear_reloadable_connections_throw_exception_if_threads_dont_return_their_conns
+ @pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
+ [:disconnect, :clear_reloadable_connections].each do |group_action_method|
+ @pool.with_connection do |connection|
+ assert_raises(ExclusiveConnectionTimeoutError) do
+ Thread.new { @pool.send(group_action_method) }.join
+ end
+ end
+ end
+ end
+
+ def test_disconnect_and_clear_reloadable_connections_attempt_to_wait_for_threads_to_return_their_conns
+ [:disconnect, :disconnect!, :clear_reloadable_connections, :clear_reloadable_connections!].each do |group_action_method|
+ begin
+ thread = timed_join_result = nil
+ @pool.with_connection do |connection|
+ thread = Thread.new { @pool.send(group_action_method) }
+
+ # give the other `thread` some time to get stuck in `group_action_method`
+ timed_join_result = thread.join(0.3)
+ # thread.join # => `nil` means the other thread hasn't finished running and is still waiting for us to
+ # release our connection
+ assert_nil timed_join_result
+
+ # assert that since this is within default timeout our connection hasn't been forcefully taken away from us
+ assert @pool.active_connection?
+ end
+ ensure
+ thread.join if thread && !timed_join_result # clean up the other thread
+ end
+ end
+ end
+
+ def test_bang_versions_of_disconnect_and_clear_reloadable_connections_if_unable_to_aquire_all_connections_proceed_anyway
+ @pool.checkout_timeout = 0.001 # no need to delay test suite by waiting the whole full default timeout
+ [:disconnect!, :clear_reloadable_connections!].each do |group_action_method|
+ @pool.with_connection do |connection|
+ Thread.new { @pool.send(group_action_method) }.join
+ # assert connection has been forcefully taken away from us
+ assert_not @pool.active_connection?
+ end
+ end
+ end
+
+ def test_disconnect_and_clear_reloadable_connections_are_able_to_preempt_other_waiting_threads
+ with_single_connection_pool do |pool|
+ [:disconnect, :disconnect!, :clear_reloadable_connections, :clear_reloadable_connections!].each do |group_action_method|
+ conn = pool.connection # drain the only available connection
+ second_thread_done = ActiveSupport::Concurrency::Latch.new
+
+ # create a first_thread and let it get into the FIFO queue first
+ first_thread = Thread.new do
+ pool.with_connection { second_thread_done.await }
+ end
+
+ # wait for first_thread to get in queue
+ Thread.pass until pool.num_waiting_in_queue == 1
+
+ # create a different, later thread, that will attempt to do a "group action",
+ # but because of the group action semantics it should be able to preempt the
+ # first_thread when a connection is made available
+ second_thread = Thread.new do
+ pool.send(group_action_method)
+ second_thread_done.release
+ end
+
+ # wait for second_thread to get in queue
+ Thread.pass until pool.num_waiting_in_queue == 2
+
+ # return the only available connection
+ pool.checkin(conn)
+
+ # if the second_thread is not able to preempt the first_thread,
+ # they will temporarily (until either of them timeouts with ConnectionTimeoutError)
+ # deadlock and a join(2) timeout will be reached
+ failed = true unless second_thread.join(2)
+
+ #--- post test clean up start
+ second_thread_done.release if failed
+
+ # after `pool.disconnect()` the first thread will be left stuck in queue, no need to wait for
+ # it to timeout with ConnectionTimeoutError
+ if (group_action_method == :disconnect || group_action_method == :disconnect!) && pool.num_waiting_in_queue > 0
+ pool.with_connection {} # create a new connection in case there are threads still stuck in a queue
+ end
+
+ first_thread.join
+ second_thread.join
+ #--- post test clean up end
+
+ flunk "#{group_action_method} is not able to preempt other waiting threads" if failed
+ end
+ end
+ end
+
+ def test_clear_reloadable_connections_creates_new_connections_for_waiting_threads_if_necessary
+ with_single_connection_pool do |pool|
+ conn = pool.connection # drain the only available connection
+ def conn.requires_reloading? # make sure it gets removed from the pool by clear_reloadable_connections
+ true
+ end
+
+ stuck_thread = Thread.new do
+ pool.with_connection {}
+ end
+
+ # wait for stuck_thread to get in queue
+ Thread.pass until pool.num_waiting_in_queue == 1
+
+ pool.clear_reloadable_connections
+
+ unless stuck_thread.join(2)
+ flunk 'clear_reloadable_connections must not let other connection waiting threads get stuck in queue'
+ end
+
+ assert_equal 0, pool.num_waiting_in_queue
+ end
+ end
+
+ private
+ def with_single_connection_pool
+ one_conn_spec = ActiveRecord::Base.connection_pool.spec.dup
+ one_conn_spec.config[:pool] = 1 # this is safe to do, because .dupped ConnectionSpecification also auto-dups its config
+ yield(pool = ConnectionPool.new(one_conn_spec))
+ ensure
+ pool.disconnect! if pool
+ end
end
end
end
diff --git a/activerecord/test/cases/disconnected_test.rb b/activerecord/test/cases/disconnected_test.rb
index 55f0e51717..c25089a420 100644
--- a/activerecord/test/cases/disconnected_test.rb
+++ b/activerecord/test/cases/disconnected_test.rb
@@ -21,7 +21,9 @@ class TestDisconnectedAdapter < ActiveRecord::TestCase
@connection.execute "SELECT count(*) from products"
@connection.disconnect!
assert_raises(ActiveRecord::StatementInvalid) do
- @connection.execute "SELECT count(*) from products"
+ silence_warnings do
+ @connection.execute "SELECT count(*) from products"
+ end
end
end
end
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index f8acdcb51e..97ba178b4d 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -279,10 +279,10 @@ class HasManyThroughFixture < ActiveSupport::TestCase
treasure = make_model "Treasure"
pt.table_name = "parrots_treasures"
- pt.belongs_to :parrot, :class => parrot
- pt.belongs_to :treasure, :class => treasure
+ pt.belongs_to :parrot, :anonymous_class => parrot
+ pt.belongs_to :treasure, :anonymous_class => treasure
- parrot.has_many :parrot_treasures, :class => pt
+ parrot.has_many :parrot_treasures, :anonymous_class => pt
parrot.has_many :treasures, :through => :parrot_treasures
parrots = File.join FIXTURES_ROOT, 'parrots'
@@ -297,10 +297,10 @@ class HasManyThroughFixture < ActiveSupport::TestCase
parrot = make_model "Parrot"
treasure = make_model "Treasure"
- pt.belongs_to :parrot, :class => parrot
- pt.belongs_to :treasure, :class => treasure
+ pt.belongs_to :parrot, :anonymous_class => parrot
+ pt.belongs_to :treasure, :anonymous_class => treasure
- parrot.has_many :parrot_treasures, :class => pt
+ parrot.has_many :parrot_treasures, :anonymous_class => pt
parrot.has_many :treasures, :through => :parrot_treasures
parrots = File.join FIXTURES_ROOT, 'parrots'
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 3268555cb8..f67d85603a 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -7,15 +7,32 @@ require 'models/subscriber'
require 'models/vegetables'
require 'models/shop'
+module InheritanceTestHelper
+ def with_store_full_sti_class(&block)
+ assign_store_full_sti_class true, &block
+ end
+
+ def without_store_full_sti_class(&block)
+ assign_store_full_sti_class false, &block
+ end
+
+ def assign_store_full_sti_class(flag)
+ old_store_full_sti_class = ActiveRecord::Base.store_full_sti_class
+ ActiveRecord::Base.store_full_sti_class = flag
+ yield
+ ensure
+ ActiveRecord::Base.store_full_sti_class = old_store_full_sti_class
+ end
+end
+
class InheritanceTest < ActiveRecord::TestCase
+ include InheritanceTestHelper
fixtures :companies, :projects, :subscribers, :accounts, :vegetables
def test_class_with_store_full_sti_class_returns_full_name
- old = ActiveRecord::Base.store_full_sti_class
- ActiveRecord::Base.store_full_sti_class = true
- assert_equal 'Namespaced::Company', Namespaced::Company.sti_name
- ensure
- ActiveRecord::Base.store_full_sti_class = old
+ with_store_full_sti_class do
+ assert_equal 'Namespaced::Company', Namespaced::Company.sti_name
+ end
end
def test_class_with_blank_sti_name
@@ -33,39 +50,31 @@ class InheritanceTest < ActiveRecord::TestCase
end
def test_class_without_store_full_sti_class_returns_demodulized_name
- old = ActiveRecord::Base.store_full_sti_class
- ActiveRecord::Base.store_full_sti_class = false
- assert_equal 'Company', Namespaced::Company.sti_name
- ensure
- ActiveRecord::Base.store_full_sti_class = old
+ without_store_full_sti_class do
+ assert_equal 'Company', Namespaced::Company.sti_name
+ end
end
def test_should_store_demodulized_class_name_with_store_full_sti_class_option_disabled
- old = ActiveRecord::Base.store_full_sti_class
- ActiveRecord::Base.store_full_sti_class = false
- item = Namespaced::Company.new
- assert_equal 'Company', item[:type]
- ensure
- ActiveRecord::Base.store_full_sti_class = old
+ without_store_full_sti_class do
+ item = Namespaced::Company.new
+ assert_equal 'Company', item[:type]
+ end
end
def test_should_store_full_class_name_with_store_full_sti_class_option_enabled
- old = ActiveRecord::Base.store_full_sti_class
- ActiveRecord::Base.store_full_sti_class = true
- item = Namespaced::Company.new
- assert_equal 'Namespaced::Company', item[:type]
- ensure
- ActiveRecord::Base.store_full_sti_class = old
+ with_store_full_sti_class do
+ item = Namespaced::Company.new
+ assert_equal 'Namespaced::Company', item[:type]
+ end
end
def test_different_namespace_subclass_should_load_correctly_with_store_full_sti_class_option
- old = ActiveRecord::Base.store_full_sti_class
- ActiveRecord::Base.store_full_sti_class = true
- item = Namespaced::Company.create :name => "Wolverine 2"
- assert_not_nil Company.find(item.id)
- assert_not_nil Namespaced::Company.find(item.id)
- ensure
- ActiveRecord::Base.store_full_sti_class = old
+ with_store_full_sti_class do
+ item = Namespaced::Company.create name: "Wolverine 2"
+ assert_not_nil Company.find(item.id)
+ assert_not_nil Namespaced::Company.find(item.id)
+ end
end
def test_company_descends_from_active_record
@@ -204,10 +213,28 @@ class InheritanceTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::SubclassNotFound) { Company.new(:type => 'Account') }
end
+ def test_new_with_unrelated_namespaced_type
+ without_store_full_sti_class do
+ e = assert_raises ActiveRecord::SubclassNotFound do
+ Namespaced::Company.new(type: 'Firm')
+ end
+
+ assert_equal "Invalid single-table inheritance type: Namespaced::Firm is not a subclass of Namespaced::Company", e.message
+ end
+ end
+
+
def test_new_with_complex_inheritance
assert_nothing_raised { Client.new(type: 'VerySpecialClient') }
end
+ def test_new_without_storing_full_sti_class
+ without_store_full_sti_class do
+ item = Company.new(type: 'SpecialCo')
+ assert_instance_of Company::SpecialCo, item
+ end
+ end
+
def test_new_with_autoload_paths
path = File.expand_path('../../models/autoloadable', __FILE__)
ActiveSupport::Dependencies.autoload_paths << path
@@ -331,6 +358,7 @@ class InheritanceTest < ActiveRecord::TestCase
end
class InheritanceComputeTypeTest < ActiveRecord::TestCase
+ include InheritanceTestHelper
fixtures :companies
def setup
@@ -344,27 +372,26 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
end
def test_instantiation_doesnt_try_to_require_corresponding_file
- ActiveRecord::Base.store_full_sti_class = false
- foo = Firm.first.clone
- foo.type = 'FirmOnTheFly'
- foo.save!
+ without_store_full_sti_class do
+ foo = Firm.first.clone
+ foo.type = 'FirmOnTheFly'
+ foo.save!
- # Should fail without FirmOnTheFly in the type condition.
- assert_raise(ActiveRecord::RecordNotFound) { Firm.find(foo.id) }
+ # Should fail without FirmOnTheFly in the type condition.
+ assert_raise(ActiveRecord::RecordNotFound) { Firm.find(foo.id) }
- # Nest FirmOnTheFly in the test case where Dependencies won't see it.
- self.class.const_set :FirmOnTheFly, Class.new(Firm)
- assert_raise(ActiveRecord::SubclassNotFound) { Firm.find(foo.id) }
+ # Nest FirmOnTheFly in the test case where Dependencies won't see it.
+ self.class.const_set :FirmOnTheFly, Class.new(Firm)
+ assert_raise(ActiveRecord::SubclassNotFound) { Firm.find(foo.id) }
- # Nest FirmOnTheFly in Firm where Dependencies will see it.
- # This is analogous to nesting models in a migration.
- Firm.const_set :FirmOnTheFly, Class.new(Firm)
+ # Nest FirmOnTheFly in Firm where Dependencies will see it.
+ # This is analogous to nesting models in a migration.
+ Firm.const_set :FirmOnTheFly, Class.new(Firm)
- # And instantiate will find the existing constant rather than trying
- # to require firm_on_the_fly.
- assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) }
- ensure
- ActiveRecord::Base.store_full_sti_class = true
+ # And instantiate will find the existing constant rather than trying
+ # to require firm_on_the_fly.
+ assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) }
+ end
end
def test_sti_type_from_attributes_disabled_in_non_sti_class
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index 9e4998a946..dbdcc84b7d 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -177,6 +177,16 @@ class OptimisticLockingTest < ActiveRecord::TestCase
assert_equal 1, p1.lock_version
end
+ def test_touch_stale_object
+ person = Person.create!(first_name: 'Mehmet Emin')
+ stale_person = Person.find(person.id)
+ person.update_attribute(:gender, 'M')
+
+ assert_raises(ActiveRecord::StaleObjectError) do
+ stale_person.touch
+ end
+ end
+
def test_lock_column_name_existing
t1 = LegacyThing.find(1)
t2 = LegacyThing.find(1)
diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb
index 87348d0f90..1594f99852 100644
--- a/activerecord/test/cases/migration/references_foreign_key_test.rb
+++ b/activerecord/test/cases/migration/references_foreign_key_test.rb
@@ -130,4 +130,24 @@ module ActiveRecord
end
end
end
+else
+class ReferencesWithoutForeignKeySupportTest < ActiveRecord::TestCase
+ setup do
+ @connection = ActiveRecord::Base.connection
+ @connection.create_table(:testing_parents, force: true)
+ end
+
+ teardown do
+ @connection.drop_table("testings", if_exists: true)
+ @connection.drop_table("testing_parents", if_exists: true)
+ end
+
+ test "ignores foreign keys defined with the table" do
+ @connection.create_table :testings do |t|
+ t.references :testing_parent, foreign_key: true
+ end
+
+ assert_includes @connection.tables, "testings"
+ end
+end
end
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index 83be9a75d8..b8433f0bba 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -175,6 +175,14 @@ class PrimaryKeysTest < ActiveRecord::TestCase
dashboard = Dashboard.first
assert_equal '2', dashboard.id
end
+
+ if current_adapter?(:PostgreSQLAdapter)
+ def test_serial_with_quoted_sequence_name
+ column = MixedCaseMonkey.columns_hash[MixedCaseMonkey.primary_key]
+ assert_equal "nextval('\"mixed_case_monkeys_monkeyID_seq\"'::regclass)", column.default_function
+ assert column.serial?
+ end
+ end
end
class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 0cf44388fa..b8e2041b6d 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -1657,6 +1657,10 @@ class RelationTest < ActiveRecord::TestCase
assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
end
+ test "find_by requires at least one argument" do
+ assert_raises(ArgumentError) { Post.all.find_by }
+ end
+
test "find_by! with hash conditions returns the first matching record" do
assert_equal posts(:eager_other), Post.order(:id).find_by!(author_id: 2)
end
@@ -1679,6 +1683,10 @@ class RelationTest < ActiveRecord::TestCase
end
end
+ test "find_by! requires at least one argument" do
+ assert_raises(ArgumentError) { Post.all.find_by! }
+ end
+
test "loaded relations cannot be mutated by multi value methods" do
relation = Post.all
relation.to_a
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 63612e33af..e6f0fe6f75 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -168,24 +168,24 @@ class SchemaDumperTest < ActiveRecord::TestCase
end
def test_schema_dumps_index_columns_in_right_order
- index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
+ index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_index/).first.strip
if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
- assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
+ assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
else
- assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index"', index_definition
+ assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index"', index_definition
end
end
def test_schema_dumps_partial_indices
- index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip
+ index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_partial_index/).first.strip
if current_adapter?(:PostgreSQLAdapter)
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter)
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
elsif current_adapter?(:SQLite3Adapter) && ActiveRecord::Base.connection.supports_partial_index?
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
else
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition
+ assert_equal 't.index ["firm_id", "type"], name: "company_partial_index"', index_definition
end
end
@@ -232,8 +232,8 @@ class SchemaDumperTest < ActiveRecord::TestCase
def test_schema_dumps_index_type
output = standard_dump
- assert_match %r{add_index "key_tests", \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
- assert_match %r{add_index "key_tests", \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
+ assert_match %r{t\.index \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
+ assert_match %r{t\.index \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
end
end
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 4137b20c4a..0dbc60940e 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -153,6 +153,18 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal expected_7, received_7
end
+ def test_unscope_comparison_where_clauses
+ # unscoped for WHERE (`developers`.`id` <= 2)
+ expected = Developer.order('salary DESC').collect(&:name)
+ received = DeveloperOrderedBySalary.where(id: -Float::INFINITY..2).unscope(where: :id).collect { |dev| dev.name }
+ assert_equal expected, received
+
+ # unscoped for WHERE (`developers`.`id` < 2)
+ expected = Developer.order('salary DESC').collect(&:name)
+ received = DeveloperOrderedBySalary.where(id: -Float::INFINITY...2).unscope(where: :id).collect { |dev| dev.name }
+ assert_equal expected, received
+ end
+
def test_unscope_multiple_where_clauses
expected = Developer.order('salary DESC').collect(&:name)
received = DeveloperOrderedBySalary.where(name: 'Jamis').where(id: 1).unscope(where: [:name, :id]).collect(&:name)
diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb
index f58535f044..8d69741a4a 100644
--- a/activerecord/test/cases/tasks/mysql_rake_test.rb
+++ b/activerecord/test/cases/tasks/mysql_rake_test.rb
@@ -283,12 +283,21 @@ module ActiveRecord
def test_structure_dump_with_port_number
filename = "awesome-file.sql"
- Kernel.expects(:system).with("mysqldump", "--port", "10000", "--result-file", filename, "--no-data", "test-db").returns(true)
+ Kernel.expects(:system).with("mysqldump", "--port=10000", "--result-file", filename, "--no-data", "test-db").returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_dump(
@configuration.merge('port' => 10000),
filename)
end
+
+ def test_structure_dump_with_ssl
+ filename = "awesome-file.sql"
+ Kernel.expects(:system).with("mysqldump", "--ssl-ca=ca.crt", "--result-file", filename, "--no-data", "test-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(
+ @configuration.merge("sslca" => "ca.crt"),
+ filename)
+ end
end
class MySQLStructureLoadTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index 7c89b4b9e8..5dab32995c 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -446,6 +446,17 @@ class TimestampTest < ActiveRecord::TestCase
toy = Toy.first
assert_equal [:created_at, :updated_at], toy.send(:all_timestamp_attributes_in_model)
end
+
+ def test_index_is_created_for_both_timestamps
+ ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
+ t.timestamps(:foos, null: true, index: true)
+ end
+
+ indexes = ActiveRecord::Base.connection.indexes('foos')
+ assert_equal ['created_at', 'updated_at'], indexes.flat_map(&:columns).sort
+ ensure
+ ActiveRecord::Base.connection.drop_table(:foos)
+ end
end
class TimestampsWithoutTransactionTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/type/integer_test.rb b/activerecord/test/cases/type/integer_test.rb
index 84fb05dd8e..0dcdbd0667 100644
--- a/activerecord/test/cases/type/integer_test.rb
+++ b/activerecord/test/cases/type/integer_test.rb
@@ -21,7 +21,7 @@ module ActiveRecord
type = Type::Integer.new
assert_nil type.cast([1,2])
assert_nil type.cast({1 => 2})
- assert_nil type.cast((1..2))
+ assert_nil type.cast(1..2)
end
test "casting ActiveRecord models" do