From c1a215a06b7b8202dbb4f090bf7eefb661bf438a Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 12 Feb 2020 16:30:33 -0500 Subject: [PATCH] Add schema cache tests The schema cache tests test the following scenarios: 1) The default case works (single db, primary spec name (dev is default to primary in 2-tier config), standard default schema cache filename) 2) Primary always wins over other entries 3) A custom schema cache filename works when set in the configuration 4) A custom schema cache filename works when set in the ENV Cases that don't work: 1) A non-primary database entry picks up a namespaced schema cache file This can't work currently because there's no way of knowing which cache we actually want. In this railtie we can only load ActiveRecord::Base's schema cache. If we grab the first config we risk loading a cache for another connection because order is not guaranteed. 2) Multi-db schema caches The reasons are similar to above. In addition we can't loop through the configs, establish a connection, and load the cache because we don't know what parent class to establish a connection to. In that case AR Base will always get the cache and it would cause the last one to win and therefore be loaded on the wrong connection. The real fix for these issues is to get rid of the railtie entirely, but for now we needed to set this back to what the behavior was before recent changes but with the ability to pass a custom key. Co-authored-by: Katrina Owen --- railties/test/application/rake/dbs_test.rb | 76 +++++++++++++++++++ .../test/application/rake/multi_dbs_test.rb | 19 +++++ 2 files changed, 95 insertions(+) diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index 975acb6a2d..c5aa0008f8 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -361,6 +361,82 @@ module ApplicationTests db_schema_dump end + def db_schema_cache_dump(filename = "db/schema_cache.yml") + Dir.chdir(app_path) do + rails "db:schema:cache:dump" + + cache_size = lambda { rails("runner", "p ActiveRecord::Base.connection.schema_cache.size").strip } + cache_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.schema_cache.columns('books')").strip } + + assert_equal "12", cache_size[] + assert_includes cache_tables[], "id", "expected cache_tables to include an id entry" + assert_includes cache_tables[], "title", "expected cache_tables to include a title entry" + end + end + + test "db:schema:cache:dump" do + db_schema_dump + db_schema_cache_dump + end + + test "db:schema:cache:dump with custom filename" do + Dir.chdir(app_path) do + File.open("#{app_path}/config/database.yml", "w") do |f| + f.puts <<-YAML + default: &default + adapter: sqlite3 + pool: 5 + timeout: 5000 + variables: + statement_timeout: 1000 + development: + <<: *default + database: db/development.sqlite3 + schema_cache_path: db/special_schema_cache.yml + YAML + end + end + + db_schema_dump + db_schema_cache_dump("db/special_schema_cache.yml") + end + + test "db:schema:cache:dump custom env" do + @old_schema_cache_env = ENV["SCHEMA_CACHE"] + filename = "db/special_schema_cache.yml" + ENV["SCHEMA_CACHE"] = filename + + db_schema_dump + db_schema_cache_dump(filename) + ensure + ENV["SCHEMA_CACHE"] = @old_schema_cache_env + end + + test "db:schema:cache:dump primary wins" do + Dir.chdir(app_path) do + File.open("#{app_path}/config/database.yml", "w") do |f| + f.puts <<-YAML + default: &default + adapter: sqlite3 + pool: 5 + timeout: 5000 + variables: + statement_timeout: 1000 + development: + some_entry: + <<: *default + database: db/development_other.sqlite3 + primary: + <<: *default + database: db/development.sqlite3 + YAML + end + end + + db_schema_dump + db_schema_cache_dump + end + def db_fixtures_load(expected_database) Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index 8e1a214acd..e841fdd1e6 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -311,6 +311,25 @@ module ApplicationTests db_migrate_and_schema_cache_dump end + # Note that schema cache loader depends on the connection and + # does not work for all connections. + test "schema_cache is loaded on primary db in multi-db app" do + require "#{app_path}/config/environment" + db_migrate_and_schema_cache_dump + + cache_size_a = lambda { rails("runner", "p ActiveRecord::Base.connection.schema_cache.size").strip } + cache_tables_a = lambda { rails("runner", "p ActiveRecord::Base.connection.schema_cache.columns('books')").strip } + cache_size_b = lambda { rails("runner", "p AnimalsBase.connection.schema_cache.size").strip } + cache_tables_b = lambda { rails("runner", "p AnimalsBase.connection.schema_cache.columns('dogs')").strip } + + assert_equal "12", cache_size_a[] + assert_includes cache_tables_a[], "title", "expected cache_tables_a to include a title entry" + + # Will be 0 because it's not loaded by the railtie + assert_equal "0", cache_size_b[] + assert_includes cache_tables_b[], "name", "expected cache_tables_b to include a name entry" + end + test "db:schema:cache:clear works on all databases" do require "#{app_path}/config/environment" db_migrate_and_schema_cache_dump_and_schema_cache_clear