diff options
Diffstat (limited to 'railties/test/application/rake/dbs_test.rb')
-rw-r--r-- | railties/test/application/rake/dbs_test.rb | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb new file mode 100644 index 0000000000..84ac2f057e --- /dev/null +++ b/railties/test/application/rake/dbs_test.rb @@ -0,0 +1,388 @@ +# frozen_string_literal: true + +require "isolation/abstract_unit" + +module ApplicationTests + module RakeTests + class RakeDbsTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + FileUtils.rm_rf("#{app_path}/config/environments") + end + + def teardown + teardown_app + end + + def database_url_db_name + "db/database_url_db.sqlite3" + end + + def set_database_url + ENV["DATABASE_URL"] = "sqlite3:#{database_url_db_name}" + # ensure it's using the DATABASE_URL + FileUtils.rm_rf("#{app_path}/config/database.yml") + end + + def db_create_and_drop(expected_database, environment_loaded: true) + Dir.chdir(app_path) do + output = rails("db:create") + assert_match(/Created database/, output) + assert File.exist?(expected_database) + yield if block_given? + assert_equal expected_database, ActiveRecord::Base.connection_config[:database] if environment_loaded + output = rails("db:drop") + assert_match(/Dropped database/, output) + assert_not File.exist?(expected_database) + end + end + + test "db:create and db:drop without database url" do + require "#{app_path}/config/environment" + db_create_and_drop ActiveRecord::Base.configurations[Rails.env]["database"] + end + + test "db:create and db:drop with database url" do + require "#{app_path}/config/environment" + set_database_url + db_create_and_drop database_url_db_name + end + + test "db:create and db:drop respect environment setting" do + app_file "config/database.yml", <<-YAML + development: + database: db/development.sqlite3 + adapter: sqlite3 + YAML + + app_file "config/environments/development.rb", <<-RUBY + Rails.application.configure do + config.read_encrypted_secrets = true + end + RUBY + + app_file "lib/tasks/check_env.rake", <<-RUBY + Rake::Task["db:create"].enhance do + File.write("tmp/config_value", Rails.application.config.read_encrypted_secrets) + end + RUBY + + db_create_and_drop("db/development.sqlite3", environment_loaded: false) do + assert File.exist?("tmp/config_value") + assert_equal "true", File.read("tmp/config_value") + end + end + + def with_database_existing + Dir.chdir(app_path) do + set_database_url + rails "db:create" + yield + rails "db:drop" + end + end + + test "db:create failure because database exists" do + with_database_existing do + output = rails("db:create") + assert_match(/already exists/, output) + end + end + + def with_bad_permissions + Dir.chdir(app_path) do + set_database_url + FileUtils.chmod("-w", "db") + yield + FileUtils.chmod("+w", "db") + end + end + + test "db:create failure because bad permissions" do + with_bad_permissions do + output = rails("db:create", allow_failure: true) + assert_match("Couldn't create '#{database_url_db_name}' database. Please check your configuration.", output) + assert_equal 1, $?.exitstatus + end + end + + test "db:create works when schema cache exists and database does not exist" do + use_postgresql + + begin + rails %w(db:create db:migrate db:schema:cache:dump) + + rails "db:drop" + rails "db:create" + assert_equal 0, $?.exitstatus + ensure + rails "db:drop" rescue nil + end + end + + test "db:drop failure because database does not exist" do + output = rails("db:drop:_unsafe", "--trace") + assert_match(/does not exist/, output) + end + + test "db:drop failure because bad permissions" do + with_database_existing do + with_bad_permissions do + output = rails("db:drop", allow_failure: true) + assert_match(/Couldn't drop/, output) + assert_equal 1, $?.exitstatus + end + end + end + + def db_migrate_and_status(expected_database) + rails "generate", "model", "book", "title:string" + rails "db:migrate" + output = rails("db:migrate:status") + assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output) + assert_match(/up\s+\d{14}\s+Create books/, output) + end + + test "db:migrate and db:migrate:status without database_url" do + require "#{app_path}/config/environment" + db_migrate_and_status ActiveRecord::Base.configurations[Rails.env]["database"] + end + + test "db:migrate and db:migrate:status with database_url" do + require "#{app_path}/config/environment" + set_database_url + db_migrate_and_status database_url_db_name + end + + def db_schema_dump + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:schema:dump" + schema_dump = File.read("db/schema.rb") + assert_match(/create_table \"books\"/, schema_dump) + end + end + + test "db:schema:dump without database_url" do + db_schema_dump + end + + test "db:schema:dump with database_url" do + set_database_url + db_schema_dump + end + + def db_fixtures_load(expected_database) + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:fixtures:load" + assert_match expected_database, ActiveRecord::Base.connection_config[:database] + require "#{app_path}/app/models/book" + assert_equal 2, Book.count + end + end + + test "db:fixtures:load without database_url" do + require "#{app_path}/config/environment" + db_fixtures_load ActiveRecord::Base.configurations[Rails.env]["database"] + end + + test "db:fixtures:load with database_url" do + require "#{app_path}/config/environment" + set_database_url + db_fixtures_load database_url_db_name + end + + test "db:fixtures:load with namespaced fixture" do + require "#{app_path}/config/environment" + + rails "generate", "model", "admin::book", "title:string" + rails "db:migrate", "db:fixtures:load" + require "#{app_path}/app/models/admin/book" + assert_equal 2, Admin::Book.count + end + + def db_structure_dump_and_load(expected_database) + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:structure:dump" + structure_dump = File.read("db/structure.sql") + assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"books\"/, structure_dump) + rails "environment", "db:drop", "db:structure:load" + assert_match expected_database, ActiveRecord::Base.connection_config[:database] + require "#{app_path}/app/models/book" + # if structure is not loaded correctly, exception would be raised + assert_equal 0, Book.count + end + end + + test "db:structure:dump and db:structure:load without database_url" do + require "#{app_path}/config/environment" + db_structure_dump_and_load ActiveRecord::Base.configurations[Rails.env]["database"] + end + + test "db:structure:dump and db:structure:load with database_url" do + require "#{app_path}/config/environment" + set_database_url + db_structure_dump_and_load database_url_db_name + end + + test "db:structure:dump and db:structure:load set ar_internal_metadata" do + require "#{app_path}/config/environment" + db_structure_dump_and_load ActiveRecord::Base.configurations[Rails.env]["database"] + + assert_equal "test", rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip + assert_equal "development", rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip + end + + test "db:structure:dump does not dump schema information when no migrations are used" do + # create table without migrations + rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }" + + stderr_output = capture(:stderr) { rails("db:structure:dump", stderr: true, allow_failure: true) } + assert_empty stderr_output + structure_dump = File.read("#{app_path}/db/structure.sql") + assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump) + end + + test "db:schema:load and db:structure:load do not purge the existing database" do + rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }" + + app_file "db/schema.rb", <<-RUBY + ActiveRecord::Schema.define(version: 20140423102712) do + create_table(:comments) {} + end + RUBY + + list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip } + + assert_equal '["posts"]', list_tables[] + rails "db:schema:load" + assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[] + + app_file "db/structure.sql", <<-SQL + CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255)); + SQL + + rails "db:structure:load" + assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[] + end + + test "db:schema:load with inflections" do + app_file "config/initializers/inflection.rb", <<-RUBY + ActiveSupport::Inflector.inflections do |inflect| + inflect.irregular 'goose', 'geese' + end + RUBY + app_file "config/initializers/primary_key_table_name.rb", <<-RUBY + ActiveRecord::Base.primary_key_prefix_type = :table_name + RUBY + app_file "db/schema.rb", <<-RUBY + ActiveRecord::Schema.define(version: 20140423102712) do + create_table("goose".pluralize) do |t| + t.string :name + end + end + RUBY + + rails "db:schema:load" + + tables = rails("runner", "p ActiveRecord::Base.connection.tables").strip + assert_match(/"geese"/, tables) + + columns = rails("runner", "p ActiveRecord::Base.connection.columns('geese').map(&:name)").strip + assert_equal columns, '["gooseid", "name"]' + end + + test "db:schema:load fails if schema.rb doesn't exist yet" do + stderr_output = capture(:stderr) { rails("db:schema:load", stderr: true, allow_failure: true) } + assert_match(/Run `rails db:migrate` to create it/, stderr_output) + end + + def db_test_load_structure + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate", "db:structure:dump", "db:test:load_structure" + ActiveRecord::Base.configurations = Rails.application.config.database_configuration + ActiveRecord::Base.establish_connection :test + require "#{app_path}/app/models/book" + # if structure is not loaded correctly, exception would be raised + assert_equal 0, Book.count + assert_match ActiveRecord::Base.configurations["test"]["database"], + ActiveRecord::Base.connection_config[:database] + end + end + + test "db:test:load_structure without database_url" do + require "#{app_path}/config/environment" + db_test_load_structure + end + + test "db:setup loads schema and seeds database" do + @old_rails_env = ENV["RAILS_ENV"] + @old_rack_env = ENV["RACK_ENV"] + ENV.delete "RAILS_ENV" + ENV.delete "RACK_ENV" + + app_file "db/schema.rb", <<-RUBY + ActiveRecord::Schema.define(version: "1") do + create_table :users do |t| + t.string :name + end + end + RUBY + + app_file "db/seeds.rb", <<-RUBY + puts ActiveRecord::Base.connection_config[:database] + RUBY + + database_path = rails("db:setup") + assert_equal "development.sqlite3", File.basename(database_path.strip) + ensure + ENV["RAILS_ENV"] = @old_rails_env + ENV["RACK_ENV"] = @old_rack_env + end + + test "db:setup sets ar_internal_metadata" do + app_file "db/schema.rb", "" + rails "db:setup" + + test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip } + development_environment = lambda { rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip } + + assert_equal "test", test_environment.call + assert_equal "development", development_environment.call + + app_file "db/structure.sql", "" + app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY + Rails.application.config.active_record.schema_format = :sql + RUBY + + rails "db:setup" + + assert_equal "test", test_environment.call + assert_equal "development", development_environment.call + end + + test "db:test:prepare sets test ar_internal_metadata" do + app_file "db/schema.rb", "" + rails "db:test:prepare" + + test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip } + + assert_equal "test", test_environment.call + + app_file "db/structure.sql", "" + app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY + Rails.application.config.active_record.schema_format = :sql + RUBY + + rails "db:test:prepare" + + assert_equal "test", test_environment.call + end + end + end +end |