aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/tasks')
-rw-r--r--activerecord/test/cases/tasks/database_tasks_test.rb692
-rw-r--r--activerecord/test/cases/tasks/mysql_rake_test.rb319
-rw-r--r--activerecord/test/cases/tasks/postgresql_rake_test.rb372
-rw-r--r--activerecord/test/cases/tasks/sqlite_rake_test.rb267
4 files changed, 1650 insertions, 0 deletions
diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb
new file mode 100644
index 0000000000..21226352ff
--- /dev/null
+++ b/activerecord/test/cases/tasks/database_tasks_test.rb
@@ -0,0 +1,692 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "active_record/tasks/database_tasks"
+
+module ActiveRecord
+ module DatabaseTasksSetupper
+ def setup
+ @mysql_tasks, @postgresql_tasks, @sqlite_tasks = stub, stub, stub
+ ActiveRecord::Tasks::MySQLDatabaseTasks.stubs(:new).returns @mysql_tasks
+ ActiveRecord::Tasks::PostgreSQLDatabaseTasks.stubs(:new).returns @postgresql_tasks
+ ActiveRecord::Tasks::SQLiteDatabaseTasks.stubs(:new).returns @sqlite_tasks
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+ end
+
+ ADAPTERS_TASKS = {
+ mysql2: :mysql_tasks,
+ postgresql: :postgresql_tasks,
+ sqlite3: :sqlite_tasks
+ }
+
+ class DatabaseTasksUtilsTask < ActiveRecord::TestCase
+ def test_raises_an_error_when_called_with_protected_environment
+ ActiveRecord::MigrationContext.any_instance.stubs(:current_version).returns(1)
+
+ protected_environments = ActiveRecord::Base.protected_environments
+ current_env = ActiveRecord::Base.connection.migration_context.current_environment
+ assert_not_includes protected_environments, current_env
+ # Assert no error
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+
+ ActiveRecord::Base.protected_environments = [current_env]
+ assert_raise(ActiveRecord::ProtectedEnvironmentError) do
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+ end
+ ensure
+ ActiveRecord::Base.protected_environments = protected_environments
+ end
+
+ def test_raises_an_error_when_called_with_protected_environment_which_name_is_a_symbol
+ ActiveRecord::MigrationContext.any_instance.stubs(:current_version).returns(1)
+
+ protected_environments = ActiveRecord::Base.protected_environments
+ current_env = ActiveRecord::Base.connection.migration_context.current_environment
+ assert_not_includes protected_environments, current_env
+ # Assert no error
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+
+ ActiveRecord::Base.protected_environments = [current_env.to_sym]
+ assert_raise(ActiveRecord::ProtectedEnvironmentError) do
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+ end
+ ensure
+ ActiveRecord::Base.protected_environments = protected_environments
+ end
+
+ def test_raises_an_error_if_no_migrations_have_been_made
+ ActiveRecord::InternalMetadata.stubs(:table_exists?).returns(false)
+ ActiveRecord::MigrationContext.any_instance.stubs(:current_version).returns(1)
+
+ assert_raise(ActiveRecord::NoEnvironmentInSchemaError) do
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+ end
+ end
+ end
+
+ class DatabaseTasksRegisterTask < ActiveRecord::TestCase
+ def test_register_task
+ klazz = Class.new do
+ def initialize(*arguments); end
+ def structure_dump(filename); end
+ end
+ instance = klazz.new
+
+ klazz.stubs(:new).returns instance
+ instance.expects(:structure_dump).with("awesome-file.sql", nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz)
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :foo }, "awesome-file.sql")
+ end
+
+ def test_unregistered_task
+ assert_raise(ActiveRecord::Tasks::DatabaseNotSupported) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :bar }, "awesome-file.sql")
+ end
+ end
+ end
+
+ class DatabaseTasksCreateTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_create") do
+ eval("@#{v}").expects(:create)
+ ActiveRecord::Tasks::DatabaseTasks.create "adapter" => k
+ end
+ end
+ end
+
+ class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
+ def test_dump_schema_cache
+ path = "/tmp/my_schema_cache.yml"
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, path)
+ assert File.file?(path)
+ ensure
+ ActiveRecord::Base.clear_cache!
+ FileUtils.rm_rf(path)
+ end
+ end
+
+ class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
+ def setup
+ @configurations = { "development" => { "database" => "my-db" } }
+
+ ActiveRecord::Base.stubs(:configurations).returns(@configurations)
+ # To refrain from connecting to a newly created empty DB in sqlite3_mem tests
+ ActiveRecord::Base.connection_handler.stubs(:establish_connection)
+ end
+
+ def test_ignores_configurations_without_databases
+ @configurations["development"].merge!("database" => nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).never
+
+ ActiveRecord::Tasks::DatabaseTasks.create_all
+ end
+
+ def test_ignores_remote_databases
+ @configurations["development"].merge!("host" => "my.server.tld")
+ $stderr.stubs(:puts).returns(nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).never
+
+ ActiveRecord::Tasks::DatabaseTasks.create_all
+ end
+
+ def test_warning_for_remote_databases
+ @configurations["development"].merge!("host" => "my.server.tld")
+
+ $stderr.expects(:puts).with("This task only modifies local databases. my-db is on a remote host.")
+
+ ActiveRecord::Tasks::DatabaseTasks.create_all
+ end
+
+ def test_creates_configurations_with_local_ip
+ @configurations["development"].merge!("host" => "127.0.0.1")
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create)
+
+ ActiveRecord::Tasks::DatabaseTasks.create_all
+ end
+
+ def test_creates_configurations_with_local_host
+ @configurations["development"].merge!("host" => "localhost")
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create)
+
+ ActiveRecord::Tasks::DatabaseTasks.create_all
+ end
+
+ def test_creates_configurations_with_blank_hosts
+ @configurations["development"].merge!("host" => nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create)
+
+ ActiveRecord::Tasks::DatabaseTasks.create_all
+ end
+ end
+
+ class DatabaseTasksCreateCurrentTest < ActiveRecord::TestCase
+ def setup
+ @configurations = {
+ "development" => { "database" => "dev-db" },
+ "test" => { "database" => "test-db" },
+ "production" => { "database" => "prod-db" }
+ }
+
+ ActiveRecord::Base.stubs(:configurations).returns(@configurations)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_creates_current_environment_database
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).
+ with("database" => "prod-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.create_current(
+ ActiveSupport::StringInquirer.new("production")
+ )
+ end
+
+ def test_creates_test_and_development_databases_when_env_was_not_specified
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).
+ with("database" => "dev-db")
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).
+ with("database" => "test-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.create_current(
+ ActiveSupport::StringInquirer.new("development")
+ )
+ end
+
+ def test_creates_test_and_development_databases_when_rails_env_is_development
+ old_env = ENV["RAILS_ENV"]
+ ENV["RAILS_ENV"] = "development"
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).
+ with("database" => "dev-db")
+ ActiveRecord::Tasks::DatabaseTasks.expects(:create).
+ with("database" => "test-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.create_current(
+ ActiveSupport::StringInquirer.new("development")
+ )
+ ensure
+ ENV["RAILS_ENV"] = old_env
+ end
+
+ def test_establishes_connection_for_the_given_environment
+ ActiveRecord::Tasks::DatabaseTasks.stubs(:create).returns true
+
+ ActiveRecord::Base.expects(:establish_connection).with(:development)
+
+ ActiveRecord::Tasks::DatabaseTasks.create_current(
+ ActiveSupport::StringInquirer.new("development")
+ )
+ end
+ end
+
+ class DatabaseTasksDropTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_drop") do
+ eval("@#{v}").expects(:drop)
+ ActiveRecord::Tasks::DatabaseTasks.drop "adapter" => k
+ end
+ end
+ end
+
+ class DatabaseTasksDropAllTest < ActiveRecord::TestCase
+ def setup
+ @configurations = { development: { "database" => "my-db" } }
+
+ ActiveRecord::Base.stubs(:configurations).returns(@configurations)
+ end
+
+ def test_ignores_configurations_without_databases
+ @configurations[:development].merge!("database" => nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).never
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
+ end
+
+ def test_ignores_remote_databases
+ @configurations[:development].merge!("host" => "my.server.tld")
+ $stderr.stubs(:puts).returns(nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).never
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
+ end
+
+ def test_warning_for_remote_databases
+ @configurations[:development].merge!("host" => "my.server.tld")
+
+ $stderr.expects(:puts).with("This task only modifies local databases. my-db is on a remote host.")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
+ end
+
+ def test_drops_configurations_with_local_ip
+ @configurations[:development].merge!("host" => "127.0.0.1")
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop)
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
+ end
+
+ def test_drops_configurations_with_local_host
+ @configurations[:development].merge!("host" => "localhost")
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop)
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
+ end
+
+ def test_drops_configurations_with_blank_hosts
+ @configurations[:development].merge!("host" => nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop)
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_all
+ end
+ end
+
+ class DatabaseTasksDropCurrentTest < ActiveRecord::TestCase
+ def setup
+ @configurations = {
+ "development" => { "database" => "dev-db" },
+ "test" => { "database" => "test-db" },
+ "production" => { "database" => "prod-db" }
+ }
+
+ ActiveRecord::Base.stubs(:configurations).returns(@configurations)
+ end
+
+ def test_drops_current_environment_database
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).
+ with("database" => "prod-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_current(
+ ActiveSupport::StringInquirer.new("production")
+ )
+ end
+
+ def test_drops_test_and_development_databases_when_env_was_not_specified
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).
+ with("database" => "dev-db")
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).
+ with("database" => "test-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_current(
+ ActiveSupport::StringInquirer.new("development")
+ )
+ end
+
+ def test_drops_testand_development_databases_when_rails_env_is_development
+ old_env = ENV["RAILS_ENV"]
+ ENV["RAILS_ENV"] = "development"
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).
+ with("database" => "dev-db")
+ ActiveRecord::Tasks::DatabaseTasks.expects(:drop).
+ with("database" => "test-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop_current(
+ ActiveSupport::StringInquirer.new("development")
+ )
+ ensure
+ ENV["RAILS_ENV"] = old_env
+ end
+ end
+
+ if current_adapter?(:SQLite3Adapter) && !in_memory_db?
+ class DatabaseTasksMigrateTest < ActiveRecord::TestCase
+ self.use_transactional_tests = false
+
+ # Use a memory db here to avoid having to rollback at the end
+ setup do
+ migrations_path = MIGRATIONS_ROOT + "/valid"
+ file = ActiveRecord::Base.connection.raw_connection.filename
+ @conn = ActiveRecord::Base.establish_connection adapter: "sqlite3",
+ database: ":memory:", migrations_paths: migrations_path
+ source_db = SQLite3::Database.new file
+ dest_db = ActiveRecord::Base.connection.raw_connection
+ backup = SQLite3::Backup.new(dest_db, "main", source_db, "main")
+ backup.step(-1)
+ backup.finish
+ end
+
+ teardown do
+ @conn.release_connection if @conn
+ ActiveRecord::Base.establish_connection :arunit
+ end
+
+ def test_migrate_set_and_unset_verbose_and_version_env_vars
+ verbose, version = ENV["VERBOSE"], ENV["VERSION"]
+ ENV["VERSION"] = "2"
+ ENV["VERBOSE"] = "false"
+
+ # run down migration because it was already run on copied db
+ assert_empty capture_migration_output
+
+ ENV.delete("VERSION")
+ ENV.delete("VERBOSE")
+
+ # re-run up migration
+ assert_includes capture_migration_output, "migrating"
+ ensure
+ ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ end
+
+ def test_migrate_set_and_unset_empty_values_for_verbose_and_version_env_vars
+ verbose, version = ENV["VERBOSE"], ENV["VERSION"]
+
+ ENV["VERSION"] = "2"
+ ENV["VERBOSE"] = "false"
+
+ # run down migration because it was already run on copied db
+ assert_empty capture_migration_output
+
+ ENV["VERBOSE"] = ""
+ ENV["VERSION"] = ""
+
+ # re-run up migration
+ assert_includes capture_migration_output, "migrating"
+ ensure
+ ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ end
+
+ def test_migrate_set_and_unset_nonsense_values_for_verbose_and_version_env_vars
+ verbose, version = ENV["VERBOSE"], ENV["VERSION"]
+
+ # run down migration because it was already run on copied db
+ ENV["VERSION"] = "2"
+ ENV["VERBOSE"] = "false"
+
+ assert_empty capture_migration_output
+
+ ENV["VERBOSE"] = "yes"
+ ENV["VERSION"] = "2"
+
+ # run no migration because 2 was already run
+ assert_empty capture_migration_output
+ ensure
+ ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ end
+
+ private
+ def capture_migration_output
+ capture(:stdout) do
+ ActiveRecord::Tasks::DatabaseTasks.migrate
+ end
+ end
+ end
+ end
+
+ class DatabaseTasksMigrateErrorTest < ActiveRecord::TestCase
+ self.use_transactional_tests = false
+
+ def test_migrate_raise_error_on_invalid_version_format
+ version = ENV["VERSION"]
+
+ ENV["VERSION"] = "unknown"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "0.1.11"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1.1.11"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "0 "
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1."
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1_"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1_name"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_match(/Invalid format of target version/, e.message)
+ ensure
+ ENV["VERSION"] = version
+ end
+
+ def test_migrate_raise_error_on_failed_check_target_version
+ ActiveRecord::Tasks::DatabaseTasks.stubs(:check_target_version).raises("foo")
+
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate }
+ assert_equal "foo", e.message
+ end
+
+ def test_migrate_clears_schema_cache_afterward
+ ActiveRecord::Base.expects(:clear_cache!)
+ ActiveRecord::Tasks::DatabaseTasks.migrate
+ end
+ end
+
+ class DatabaseTasksPurgeTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_purge") do
+ eval("@#{v}").expects(:purge)
+ ActiveRecord::Tasks::DatabaseTasks.purge "adapter" => k
+ end
+ end
+ end
+
+ class DatabaseTasksPurgeCurrentTest < ActiveRecord::TestCase
+ def test_purges_current_environment_database
+ configurations = {
+ "development" => { "database" => "dev-db" },
+ "test" => { "database" => "test-db" },
+ "production" => { "database" => "prod-db" }
+ }
+ ActiveRecord::Base.stubs(:configurations).returns(configurations)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:purge).
+ with("database" => "prod-db")
+ ActiveRecord::Base.expects(:establish_connection).with(:production)
+
+ ActiveRecord::Tasks::DatabaseTasks.purge_current("production")
+ end
+ end
+
+ class DatabaseTasksPurgeAllTest < ActiveRecord::TestCase
+ def test_purge_all_local_configurations
+ configurations = { development: { "database" => "my-db" } }
+ ActiveRecord::Base.stubs(:configurations).returns(configurations)
+
+ ActiveRecord::Tasks::DatabaseTasks.expects(:purge).
+ with("database" => "my-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.purge_all
+ end
+ end
+
+ class DatabaseTasksCharsetTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_charset") do
+ eval("@#{v}").expects(:charset)
+ ActiveRecord::Tasks::DatabaseTasks.charset "adapter" => k
+ end
+ end
+ end
+
+ class DatabaseTasksCollationTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_collation") do
+ eval("@#{v}").expects(:collation)
+ ActiveRecord::Tasks::DatabaseTasks.collation "adapter" => k
+ end
+ end
+ end
+
+ class DatabaseTaskTargetVersionTest < ActiveRecord::TestCase
+ def test_target_version_returns_nil_if_version_does_not_exist
+ version = ENV.delete("VERSION")
+ assert_nil ActiveRecord::Tasks::DatabaseTasks.target_version
+ ensure
+ ENV["VERSION"] = version
+ end
+
+ def test_target_version_returns_nil_if_version_is_empty
+ version = ENV["VERSION"]
+
+ ENV["VERSION"] = ""
+ assert_nil ActiveRecord::Tasks::DatabaseTasks.target_version
+ ensure
+ ENV["VERSION"] = version
+ end
+
+ def test_target_version_returns_converted_to_integer_env_version_if_version_exists
+ version = ENV["VERSION"]
+
+ ENV["VERSION"] = "0"
+ assert_equal ENV["VERSION"].to_i, ActiveRecord::Tasks::DatabaseTasks.target_version
+
+ ENV["VERSION"] = "42"
+ assert_equal ENV["VERSION"].to_i, ActiveRecord::Tasks::DatabaseTasks.target_version
+
+ ENV["VERSION"] = "042"
+ assert_equal ENV["VERSION"].to_i, ActiveRecord::Tasks::DatabaseTasks.target_version
+ ensure
+ ENV["VERSION"] = version
+ end
+ end
+
+ class DatabaseTaskCheckTargetVersionTest < ActiveRecord::TestCase
+ def test_check_target_version_does_not_raise_error_on_empty_version
+ version = ENV["VERSION"]
+ ENV["VERSION"] = ""
+ assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ ensure
+ ENV["VERSION"] = version
+ end
+
+ def test_check_target_version_does_not_raise_error_if_version_is_not_setted
+ version = ENV.delete("VERSION")
+ assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ ensure
+ ENV["VERSION"] = version
+ end
+
+ def test_check_target_version_raises_error_on_invalid_version_format
+ version = ENV["VERSION"]
+
+ ENV["VERSION"] = "unknown"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "0.1.11"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1.1.11"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "0 "
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1."
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1_"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+
+ ENV["VERSION"] = "1_name"
+ e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ assert_match(/Invalid format of target version/, e.message)
+ ensure
+ ENV["VERSION"] = version
+ end
+
+ def test_check_target_version_does_not_raise_error_on_valid_version_format
+ version = ENV["VERSION"]
+
+ ENV["VERSION"] = "0"
+ assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+
+ ENV["VERSION"] = "1"
+ assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+
+ ENV["VERSION"] = "001"
+ assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+
+ ENV["VERSION"] = "001_name.rb"
+ assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version }
+ ensure
+ ENV["VERSION"] = version
+ end
+ end
+
+ class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_structure_dump") do
+ eval("@#{v}").expects(:structure_dump).with("awesome-file.sql", nil)
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => k }, "awesome-file.sql")
+ end
+ end
+ end
+
+ class DatabaseTasksStructureLoadTest < ActiveRecord::TestCase
+ include DatabaseTasksSetupper
+
+ ADAPTERS_TASKS.each do |k, v|
+ define_method("test_#{k}_structure_load") do
+ eval("@#{v}").expects(:structure_load).with("awesome-file.sql", nil)
+ ActiveRecord::Tasks::DatabaseTasks.structure_load({ "adapter" => k }, "awesome-file.sql")
+ end
+ end
+ end
+
+ class DatabaseTasksCheckSchemaFileTest < ActiveRecord::TestCase
+ def test_check_schema_file
+ Kernel.expects(:abort).with(regexp_matches(/awesome-file.sql/))
+ ActiveRecord::Tasks::DatabaseTasks.check_schema_file("awesome-file.sql")
+ end
+ end
+
+ class DatabaseTasksCheckSchemaFileDefaultsTest < ActiveRecord::TestCase
+ def test_check_schema_file_defaults
+ ActiveRecord::Tasks::DatabaseTasks.stubs(:db_dir).returns("/tmp")
+ assert_equal "/tmp/schema.rb", ActiveRecord::Tasks::DatabaseTasks.schema_file
+ end
+ end
+
+ class DatabaseTasksCheckSchemaFileSpecifiedFormatsTest < ActiveRecord::TestCase
+ { ruby: "schema.rb", sql: "structure.sql" }.each_pair do |fmt, filename|
+ define_method("test_check_schema_file_for_#{fmt}_format") do
+ ActiveRecord::Tasks::DatabaseTasks.stubs(:db_dir).returns("/tmp")
+ assert_equal "/tmp/#{filename}", ActiveRecord::Tasks::DatabaseTasks.schema_file(fmt)
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb
new file mode 100644
index 0000000000..047153e7cc
--- /dev/null
+++ b/activerecord/test/cases/tasks/mysql_rake_test.rb
@@ -0,0 +1,319 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "active_record/tasks/database_tasks"
+
+if current_adapter?(:Mysql2Adapter)
+ module ActiveRecord
+ class MysqlDBCreateTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true)
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_establishes_connection_without_database
+ ActiveRecord::Base.expects(:establish_connection).
+ with("adapter" => "mysql2", "database" => nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ def test_creates_database_with_no_default_options
+ @connection.expects(:create_database).
+ with("my-app-db", {})
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ def test_creates_database_with_given_encoding
+ @connection.expects(:create_database).
+ with("my-app-db", charset: "latin1")
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge("encoding" => "latin1")
+ end
+
+ def test_creates_database_with_given_collation
+ @connection.expects(:create_database).
+ with("my-app-db", collation: "latin1_swedish_ci")
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge("collation" => "latin1_swedish_ci")
+ end
+
+ def test_establishes_connection_to_database
+ ActiveRecord::Base.expects(:establish_connection).with(@configuration)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ def test_when_database_created_successfully_outputs_info_to_stdout
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+
+ assert_equal "Created database 'my-app-db'\n", $stdout.string
+ end
+
+ def test_create_when_database_exists_outputs_info_to_stderr
+ ActiveRecord::Base.connection.stubs(:create_database).raises(
+ ActiveRecord::Tasks::DatabaseAlreadyExists
+ )
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+
+ assert_equal "Database 'my-app-db' already exists\n", $stderr.string
+ end
+ end
+
+ class MysqlDBCreateWithInvalidPermissionsTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub("Connection", create_database: true)
+ @error = Mysql2::Error.new("Invalid permissions")
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "my-app-db",
+ "username" => "pat",
+ "password" => "wossname"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).raises(@error)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_raises_error
+ assert_raises(Mysql2::Error) do
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+ end
+ end
+
+ class MySQLDBDropTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(drop_database: true)
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_establishes_connection_to_mysql_database
+ ActiveRecord::Base.expects(:establish_connection).with @configuration
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration
+ end
+
+ def test_drops_database
+ @connection.expects(:drop_database).with("my-app-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration
+ end
+
+ def test_when_database_dropped_successfully_outputs_info_to_stdout
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration
+
+ assert_equal "Dropped database 'my-app-db'\n", $stdout.string
+ end
+ end
+
+ class MySQLPurgeTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(recreate_database: true)
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "test-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_establishes_connection_to_the_appropriate_database
+ ActiveRecord::Base.expects(:establish_connection).with(@configuration)
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+
+ def test_recreates_database_with_no_default_options
+ @connection.expects(:recreate_database).
+ with("test-db", {})
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+
+ def test_recreates_database_with_the_given_options
+ @connection.expects(:recreate_database).
+ with("test-db", charset: "latin", collation: "latin1_swedish_ci")
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration.merge(
+ "encoding" => "latin", "collation" => "latin1_swedish_ci")
+ end
+ end
+
+ class MysqlDBCharsetTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true)
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_db_retrieves_charset
+ @connection.expects(:charset)
+ ActiveRecord::Tasks::DatabaseTasks.charset @configuration
+ end
+ end
+
+ class MysqlDBCollationTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true)
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_db_retrieves_collation
+ @connection.expects(:collation)
+ ActiveRecord::Tasks::DatabaseTasks.collation @configuration
+ end
+ end
+
+ class MySQLStructureDumpTest < ActiveRecord::TestCase
+ def setup
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "test-db"
+ }
+ end
+
+ def test_structure_dump
+ filename = "awesome-file.sql"
+ Kernel.expects(:system).with("mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
+ end
+
+ def test_structure_dump_with_extra_flags
+ filename = "awesome-file.sql"
+ expected_command = ["mysqldump", "--noop", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
+
+ assert_called_with(Kernel, :system, expected_command, returns: true) do
+ with_structure_dump_flags(["--noop"]) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
+ end
+ end
+ end
+
+ def test_structure_dump_with_ignore_tables
+ filename = "awesome-file.sql"
+ ActiveRecord::SchemaDumper.expects(:ignore_tables).returns(["foo", "bar"])
+
+ Kernel.expects(:system).with("mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "--ignore-table=test-db.foo", "--ignore-table=test-db.bar", "test-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
+ end
+
+ def test_warn_when_external_structure_dump_command_execution_fails
+ filename = "awesome-file.sql"
+ Kernel.expects(:system)
+ .with("mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db")
+ .returns(false)
+
+ e = assert_raise(RuntimeError) {
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
+ }
+ assert_match(/^failed to execute: `mysqldump`$/, e.message)
+ end
+
+ def test_structure_dump_with_port_number
+ filename = "awesome-file.sql"
+ Kernel.expects(:system).with("mysqldump", "--port=10000", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "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", "--routines", "--skip-comments", "test-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(
+ @configuration.merge("sslca" => "ca.crt"),
+ filename)
+ end
+
+ private
+ def with_structure_dump_flags(flags)
+ old = ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = flags
+ yield
+ ensure
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = old
+ end
+ end
+
+ class MySQLStructureLoadTest < ActiveRecord::TestCase
+ def setup
+ @configuration = {
+ "adapter" => "mysql2",
+ "database" => "test-db"
+ }
+ end
+
+ def test_structure_load
+ filename = "awesome-file.sql"
+ expected_command = ["mysql", "--noop", "--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db"]
+
+ assert_called_with(Kernel, :system, expected_command, returns: true) do
+ with_structure_load_flags(["--noop"]) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
+ end
+ end
+ end
+
+ private
+ def with_structure_load_flags(flags)
+ old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags
+ ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = flags
+ yield
+ ensure
+ ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = old
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb
new file mode 100644
index 0000000000..ca1defa332
--- /dev/null
+++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb
@@ -0,0 +1,372 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "active_record/tasks/database_tasks"
+
+if current_adapter?(:PostgreSQLAdapter)
+ module ActiveRecord
+ class PostgreSQLDBCreateTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true)
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_establishes_connection_to_postgresql_database
+ ActiveRecord::Base.expects(:establish_connection).with(
+ "adapter" => "postgresql",
+ "database" => "postgres",
+ "schema_search_path" => "public"
+ )
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ def test_creates_database_with_default_encoding
+ @connection.expects(:create_database).
+ with("my-app-db", @configuration.merge("encoding" => "utf8"))
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ def test_creates_database_with_given_encoding
+ @connection.expects(:create_database).
+ with("my-app-db", @configuration.merge("encoding" => "latin"))
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.
+ merge("encoding" => "latin")
+ end
+
+ def test_creates_database_with_given_collation_and_ctype
+ @connection.expects(:create_database).
+ with("my-app-db", @configuration.merge("encoding" => "utf8", "collation" => "ja_JP.UTF8", "ctype" => "ja_JP.UTF8"))
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.
+ merge("collation" => "ja_JP.UTF8", "ctype" => "ja_JP.UTF8")
+ end
+
+ def test_establishes_connection_to_new_database
+ ActiveRecord::Base.expects(:establish_connection).with(@configuration)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ def test_db_create_with_error_prints_message
+ ActiveRecord::Base.stubs(:establish_connection).raises(Exception)
+
+ $stderr.stubs(:puts).returns(true)
+ $stderr.expects(:puts).
+ with("Couldn't create database for #{@configuration.inspect}")
+
+ assert_raises(Exception) { ActiveRecord::Tasks::DatabaseTasks.create @configuration }
+ end
+
+ def test_when_database_created_successfully_outputs_info_to_stdout
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+
+ assert_equal "Created database 'my-app-db'\n", $stdout.string
+ end
+
+ def test_create_when_database_exists_outputs_info_to_stderr
+ ActiveRecord::Base.connection.stubs(:create_database).raises(
+ ActiveRecord::Tasks::DatabaseAlreadyExists
+ )
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+
+ assert_equal "Database 'my-app-db' already exists\n", $stderr.string
+ end
+ end
+
+ class PostgreSQLDBDropTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(drop_database: true)
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_establishes_connection_to_postgresql_database
+ ActiveRecord::Base.expects(:establish_connection).with(
+ "adapter" => "postgresql",
+ "database" => "postgres",
+ "schema_search_path" => "public"
+ )
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration
+ end
+
+ def test_drops_database
+ @connection.expects(:drop_database).with("my-app-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration
+ end
+
+ def test_when_database_dropped_successfully_outputs_info_to_stdout
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration
+
+ assert_equal "Dropped database 'my-app-db'\n", $stdout.string
+ end
+ end
+
+ class PostgreSQLPurgeTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true, drop_database: true)
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:clear_active_connections!).returns(true)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_clears_active_connections
+ ActiveRecord::Base.expects(:clear_active_connections!)
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+
+ def test_establishes_connection_to_postgresql_database
+ ActiveRecord::Base.expects(:establish_connection).with(
+ "adapter" => "postgresql",
+ "database" => "postgres",
+ "schema_search_path" => "public"
+ )
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+
+ def test_drops_database
+ @connection.expects(:drop_database).with("my-app-db")
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+
+ def test_creates_database
+ @connection.expects(:create_database).
+ with("my-app-db", @configuration.merge("encoding" => "utf8"))
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+
+ def test_establishes_connection
+ ActiveRecord::Base.expects(:establish_connection).with(@configuration)
+
+ ActiveRecord::Tasks::DatabaseTasks.purge @configuration
+ end
+ end
+
+ class PostgreSQLDBCharsetTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true)
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_db_retrieves_charset
+ @connection.expects(:encoding)
+ ActiveRecord::Tasks::DatabaseTasks.charset @configuration
+ end
+ end
+
+ class PostgreSQLDBCollationTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(create_database: true)
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_db_retrieves_collation
+ @connection.expects(:collation)
+ ActiveRecord::Tasks::DatabaseTasks.collation @configuration
+ end
+ end
+
+ class PostgreSQLStructureDumpTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub(schema_search_path: nil, structure_dump: true)
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+ @filename = "/tmp/awesome-file.sql"
+ FileUtils.touch(@filename)
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def teardown
+ FileUtils.rm_f(@filename)
+ end
+
+ def test_structure_dump
+ Kernel.expects(:system).with("pg_dump", "-s", "-x", "-O", "-f", @filename, "my-app-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+ end
+
+ def test_structure_dump_header_comments_removed
+ Kernel.stubs(:system).returns(true)
+ File.write(@filename, "-- header comment\n\n-- more header comment\n statement \n-- lower comment\n")
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+
+ assert_equal [" statement \n", "-- lower comment\n"], File.readlines(@filename).first(2)
+ end
+
+ def test_structure_dump_with_extra_flags
+ expected_command = ["pg_dump", "-s", "-x", "-O", "-f", @filename, "--noop", "my-app-db"]
+
+ assert_called_with(Kernel, :system, expected_command, returns: true) do
+ with_structure_dump_flags(["--noop"]) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+ end
+ end
+ end
+
+ def test_structure_dump_with_ignore_tables
+ ActiveRecord::SchemaDumper.expects(:ignore_tables).returns(["foo", "bar"])
+
+ Kernel.expects(:system).with("pg_dump", "-s", "-x", "-O", "-f", @filename, "-T", "foo", "-T", "bar", "my-app-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+ end
+
+ def test_structure_dump_with_schema_search_path
+ @configuration["schema_search_path"] = "foo,bar"
+
+ Kernel.expects(:system).with("pg_dump", "-s", "-x", "-O", "-f", @filename, "--schema=foo", "--schema=bar", "my-app-db").returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+ end
+
+ def test_structure_dump_with_schema_search_path_and_dump_schemas_all
+ @configuration["schema_search_path"] = "foo,bar"
+
+ Kernel.expects(:system).with("pg_dump", "-s", "-x", "-O", "-f", @filename, "my-app-db").returns(true)
+
+ with_dump_schemas(:all) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+ end
+ end
+
+ def test_structure_dump_with_dump_schemas_string
+ Kernel.expects(:system).with("pg_dump", "-s", "-x", "-O", "-f", @filename, "--schema=foo", "--schema=bar", "my-app-db").returns(true)
+
+ with_dump_schemas("foo,bar") do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
+ end
+ end
+
+ def test_structure_dump_execution_fails
+ filename = "awesome-file.sql"
+ Kernel.expects(:system).with("pg_dump", "-s", "-x", "-O", "-f", filename, "my-app-db").returns(nil)
+
+ e = assert_raise(RuntimeError) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
+ end
+ assert_match("failed to execute:", e.message)
+ end
+
+ private
+ def with_dump_schemas(value, &block)
+ old_dump_schemas = ActiveRecord::Base.dump_schemas
+ ActiveRecord::Base.dump_schemas = value
+ yield
+ ensure
+ ActiveRecord::Base.dump_schemas = old_dump_schemas
+ end
+
+ def with_structure_dump_flags(flags)
+ old = ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = flags
+ yield
+ ensure
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = old
+ end
+ end
+
+ class PostgreSQLStructureLoadTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub
+ @configuration = {
+ "adapter" => "postgresql",
+ "database" => "my-app-db"
+ }
+
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_structure_load
+ filename = "awesome-file.sql"
+ Kernel.expects(:system).with("psql", "-v", "ON_ERROR_STOP=1", "-q", "-f", filename, @configuration["database"]).returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
+ end
+
+ def test_structure_load_with_extra_flags
+ filename = "awesome-file.sql"
+ expected_command = ["psql", "-v", "ON_ERROR_STOP=1", "-q", "-f", filename, "--noop", @configuration["database"]]
+
+ assert_called_with(Kernel, :system, expected_command, returns: true) do
+ with_structure_load_flags(["--noop"]) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
+ end
+ end
+ end
+
+ def test_structure_load_accepts_path_with_spaces
+ filename = "awesome file.sql"
+ Kernel.expects(:system).with("psql", "-v", "ON_ERROR_STOP=1", "-q", "-f", filename, @configuration["database"]).returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
+ end
+
+ private
+ def with_structure_load_flags(flags)
+ old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags
+ ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = flags
+ yield
+ ensure
+ ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = old
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/tasks/sqlite_rake_test.rb b/activerecord/test/cases/tasks/sqlite_rake_test.rb
new file mode 100644
index 0000000000..d7e3caa2ff
--- /dev/null
+++ b/activerecord/test/cases/tasks/sqlite_rake_test.rb
@@ -0,0 +1,267 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "active_record/tasks/database_tasks"
+require "pathname"
+
+if current_adapter?(:SQLite3Adapter)
+ module ActiveRecord
+ class SqliteDBCreateTest < ActiveRecord::TestCase
+ def setup
+ @database = "db_create.sqlite3"
+ @connection = stub :connection
+ @configuration = {
+ "adapter" => "sqlite3",
+ "database" => @database
+ }
+
+ File.stubs(:exist?).returns(false)
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_db_checks_database_exists
+ File.expects(:exist?).with(@database).returns(false)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root"
+ end
+
+ def test_when_db_created_successfully_outputs_info_to_stdout
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root"
+
+ assert_equal "Created database '#{@database}'\n", $stdout.string
+ end
+
+ def test_db_create_when_file_exists
+ File.stubs(:exist?).returns(true)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root"
+
+ assert_equal "Database '#{@database}' already exists\n", $stderr.string
+ end
+
+ def test_db_create_with_file_does_nothing
+ File.stubs(:exist?).returns(true)
+ $stderr.stubs(:puts).returns(nil)
+
+ ActiveRecord::Base.expects(:establish_connection).never
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root"
+ end
+
+ def test_db_create_establishes_a_connection
+ ActiveRecord::Base.expects(:establish_connection).with(@configuration)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root"
+ end
+
+ def test_db_create_with_error_prints_message
+ ActiveRecord::Base.stubs(:establish_connection).raises(Exception)
+
+ $stderr.stubs(:puts).returns(true)
+ $stderr.expects(:puts).
+ with("Couldn't create database for #{@configuration.inspect}")
+
+ assert_raises(Exception) { ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root" }
+ end
+ end
+
+ class SqliteDBDropTest < ActiveRecord::TestCase
+ def setup
+ @database = "db_create.sqlite3"
+ @path = stub(to_s: "/absolute/path", absolute?: true)
+ @configuration = {
+ "adapter" => "sqlite3",
+ "database" => @database
+ }
+
+ Pathname.stubs(:new).returns(@path)
+ File.stubs(:join).returns("/former/relative/path")
+ FileUtils.stubs(:rm).returns(true)
+
+ $stdout, @original_stdout = StringIO.new, $stdout
+ $stderr, @original_stderr = StringIO.new, $stderr
+ end
+
+ def teardown
+ $stdout, $stderr = @original_stdout, @original_stderr
+ end
+
+ def test_creates_path_from_database
+ Pathname.expects(:new).with(@database).returns(@path)
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration, "/rails/root"
+ end
+
+ def test_removes_file_with_absolute_path
+ File.stubs(:exist?).returns(true)
+ @path.stubs(:absolute?).returns(true)
+
+ FileUtils.expects(:rm).with("/absolute/path")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration, "/rails/root"
+ end
+
+ def test_generates_absolute_path_with_given_root
+ @path.stubs(:absolute?).returns(false)
+
+ File.expects(:join).with("/rails/root", @path).
+ returns("/former/relative/path")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration, "/rails/root"
+ end
+
+ def test_removes_file_with_relative_path
+ File.stubs(:exist?).returns(true)
+ @path.stubs(:absolute?).returns(false)
+
+ FileUtils.expects(:rm).with("/former/relative/path")
+
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration, "/rails/root"
+ end
+
+ def test_when_db_dropped_successfully_outputs_info_to_stdout
+ ActiveRecord::Tasks::DatabaseTasks.drop @configuration, "/rails/root"
+
+ assert_equal "Dropped database '#{@database}'\n", $stdout.string
+ end
+ end
+
+ class SqliteDBCharsetTest < ActiveRecord::TestCase
+ def setup
+ @database = "db_create.sqlite3"
+ @connection = stub :connection
+ @configuration = {
+ "adapter" => "sqlite3",
+ "database" => @database
+ }
+
+ File.stubs(:exist?).returns(false)
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_db_retrieves_charset
+ @connection.expects(:encoding)
+ ActiveRecord::Tasks::DatabaseTasks.charset @configuration, "/rails/root"
+ end
+ end
+
+ class SqliteDBCollationTest < ActiveRecord::TestCase
+ def setup
+ @database = "db_create.sqlite3"
+ @connection = stub :connection
+ @configuration = {
+ "adapter" => "sqlite3",
+ "database" => @database
+ }
+
+ File.stubs(:exist?).returns(false)
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).returns(true)
+ end
+
+ def test_db_retrieves_collation
+ assert_raise NoMethodError do
+ ActiveRecord::Tasks::DatabaseTasks.collation @configuration, "/rails/root"
+ end
+ end
+ end
+
+ class SqliteStructureDumpTest < ActiveRecord::TestCase
+ def setup
+ @database = "db_create.sqlite3"
+ @configuration = {
+ "adapter" => "sqlite3",
+ "database" => @database
+ }
+
+ `sqlite3 #{@database} 'CREATE TABLE bar(id INTEGER)'`
+ `sqlite3 #{@database} 'CREATE TABLE foo(id INTEGER)'`
+ end
+
+ def test_structure_dump
+ dbfile = @database
+ filename = "awesome-file.sql"
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump @configuration, filename, "/rails/root"
+ assert File.exist?(dbfile)
+ assert File.exist?(filename)
+ assert_match(/CREATE TABLE foo/, File.read(filename))
+ assert_match(/CREATE TABLE bar/, File.read(filename))
+ ensure
+ FileUtils.rm_f(filename)
+ FileUtils.rm_f(dbfile)
+ end
+
+ def test_structure_dump_with_ignore_tables
+ dbfile = @database
+ filename = "awesome-file.sql"
+ ActiveRecord::SchemaDumper.expects(:ignore_tables).returns(["foo"])
+
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename, "/rails/root")
+ assert File.exist?(dbfile)
+ assert File.exist?(filename)
+ assert_match(/bar/, File.read(filename))
+ assert_no_match(/foo/, File.read(filename))
+ ensure
+ FileUtils.rm_f(filename)
+ FileUtils.rm_f(dbfile)
+ end
+
+ def test_structure_dump_execution_fails
+ dbfile = @database
+ filename = "awesome-file.sql"
+ Kernel.expects(:system).with("sqlite3", "--noop", "db_create.sqlite3", ".schema", out: "awesome-file.sql").returns(nil)
+
+ e = assert_raise(RuntimeError) do
+ with_structure_dump_flags(["--noop"]) do
+ quietly { ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename, "/rails/root") }
+ end
+ end
+ assert_match("failed to execute:", e.message)
+ ensure
+ FileUtils.rm_f(filename)
+ FileUtils.rm_f(dbfile)
+ end
+
+ private
+ def with_structure_dump_flags(flags)
+ old = ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = flags
+ yield
+ ensure
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = old
+ end
+ end
+
+ class SqliteStructureLoadTest < ActiveRecord::TestCase
+ def setup
+ @database = "db_create.sqlite3"
+ @configuration = {
+ "adapter" => "sqlite3",
+ "database" => @database
+ }
+ end
+
+ def test_structure_load
+ dbfile = @database
+ filename = "awesome-file.sql"
+
+ open(filename, "w") { |f| f.puts("select datetime('now', 'localtime');") }
+ ActiveRecord::Tasks::DatabaseTasks.structure_load @configuration, filename, "/rails/root"
+ assert File.exist?(dbfile)
+ ensure
+ FileUtils.rm_f(filename)
+ FileUtils.rm_f(dbfile)
+ end
+ end
+ end
+end