aboutsummaryrefslogblamecommitdiffstats
path: root/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb
blob: ee2972101f8daebac1431da5e9d6ddf65d080b77 (plain) (tree)
1
2
3
4
5
6
7
8
9

                             






                                                                      
                                                   
                                                     



                                                    
                                            
                                              


                                

                                                                  


                                    


                                                                                     


                                                                    
                                                        

                                                                                                    
                                                                                                                     


                                     
                                                                                  

                                                        


                                                                                                   
                                                                                                             

                                     







                                                                                       
 
                                                                                 

                                                        


                                                                                                   
                                                                                                             


                                     
                                                       
                                                        

                                                                                                                      
                                                                                                                          


                                     









                                                                                                                                                                 
                                                                
                                                        
                                                                                                  




                                            
                                                          
                                                                    

                                                                                                          
                                                                                            









                                                                                   
                                                        

                                                                                                        
                                                                                               



                                                       
                                                      

                                                                                                                       
                                                                                                                 







































                                                                                     
                                                        






                                                    






                                        


                                                     

                                                        







                                                       








                                          

         
                                                    

                                                        







                                                       








                                          

         
                                                   
                                                         









                                                    
                                            
                                                                



                                                                               
                                                






                                                


















                                                                                                                       
                                                   
                                                        
 
                                                         











                                                  
                                                        
 
                                                                                                               









                                                  






























                                                                                    










                                                        

                                                                                          






                                     






























                                                                                          
         















                                                                                                                                         


       
# frozen_string_literal: true

require "cases/helper"

module ActiveRecord
  module ConnectionAdapters
    class MergeAndResolveDefaultUrlConfigTest < ActiveRecord::TestCase
      def setup
        @previous_database_url = ENV.delete("DATABASE_URL")
        @previous_rack_env = ENV.delete("RACK_ENV")
        @previous_rails_env = ENV.delete("RAILS_ENV")
      end

      teardown do
        ENV["DATABASE_URL"] = @previous_database_url
        ENV["RACK_ENV"] = @previous_rack_env
        ENV["RAILS_ENV"] = @previous_rails_env
      end

      def resolve_config(config)
        configs = ActiveRecord::DatabaseConfigurations.new(config)
        configs.to_h
      end

      def resolve_spec(spec, config)
        configs = ActiveRecord::DatabaseConfigurations.new(config)
        resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(configs)
        resolver.resolve(spec, spec)
      end

      def test_resolver_with_database_uri_and_current_env_symbol_key
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        config   = { "not_production" => {  "adapter" => "not_postgres", "database" => "not_foo" } }
        actual   = resolve_spec(:default_env, config)
        expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "default_env" }
        assert_equal expected, actual
      end

      def test_resolver_with_database_uri_and_current_env_symbol_key_and_rails_env
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        ENV["RAILS_ENV"]    = "foo"

        config   = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
        actual   = resolve_spec(:foo, config)
        expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "foo" }
        assert_equal expected, actual
      end

      def test_resolver_with_nil_database_url_and_current_env
        ENV["RAILS_ENV"] = "foo"
        config = { "foo" => { "adapter" => "postgres", "url" => ENV["DATABASE_URL"] } }
        actual   = resolve_spec(:foo, config)
        expected = { "adapter" => "postgres", "url" => nil, "name" => "foo" }
        assert_equal expected, actual
      end

      def test_resolver_with_database_uri_and_current_env_symbol_key_and_rack_env
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        ENV["RACK_ENV"]     = "foo"

        config   = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
        actual   = resolve_spec(:foo, config)
        expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "foo" }
        assert_equal expected, actual
      end

      def test_resolver_with_database_uri_and_known_key
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        config   = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
        actual   = resolve_spec(:production, config)
        expected = { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost", "name" => "production" }
        assert_equal expected, actual
      end

      def test_resolver_with_database_uri_and_multiple_envs
        ENV["DATABASE_URL"] = "postgres://localhost"
        ENV["RAILS_ENV"] = "test"

        config   = { "production" => { "adapter" => "postgresql", "database" => "foo_prod" }, "test" => { "adapter" => "postgresql", "database" => "foo_test" } }
        actual   = resolve_spec(:test, config)
        expected = { "adapter" => "postgresql", "database" => "foo_test", "host" => "localhost", "name" => "test" }
        assert_equal expected, actual
      end

      def test_resolver_with_database_uri_and_unknown_symbol_key
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        config = { "not_production" => {  "adapter" => "not_postgres", "database" => "not_foo" } }
        assert_raises AdapterNotSpecified do
          resolve_spec(:production, config)
        end
      end

      def test_resolver_with_database_uri_and_supplied_url
        ENV["DATABASE_URL"] = "not-postgres://not-localhost/not_foo"
        config   = { "production" => {  "adapter" => "also_not_postgres", "database" => "also_not_foo" } }
        actual   = resolve_spec("postgres://localhost/foo", config)
        expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" }
        assert_equal expected, actual
      end

      def test_jdbc_url
        config   = { "production" => { "url" => "jdbc:postgres://localhost/foo" } }
        actual   = resolve_config(config)
        assert_equal config, actual
      end

      def test_environment_does_not_exist_in_config_url_does_exist
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        config      = { "not_default_env" => {  "adapter" => "not_postgres", "database" => "not_foo" } }
        actual      = resolve_config(config)
        expect_prod = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" }
        assert_equal expect_prod, actual["default_env"]
      end

      def test_url_with_hyphenated_scheme
        ENV["DATABASE_URL"] = "ibm-db://localhost/foo"
        config   = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
        actual   = resolve_spec(:default_env, config)
        expected = { "adapter" => "ibm_db", "database" => "foo", "host" => "localhost", "name" => "default_env" }
        assert_equal expected, actual
      end

      def test_string_connection
        config   = { "default_env" => "postgres://localhost/foo" }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "adapter"  => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost"
                      }
                    }
        assert_equal expected, actual
      end

      def test_url_sub_key
        config   = { "default_env" => { "url" => "postgres://localhost/foo" } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "adapter"  => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost"
                      }
                    }
        assert_equal expected, actual
      end

      def test_hash
        config = { "production" => { "adapter" => "postgres", "database" => "foo" } }
        actual = resolve_config(config)
        assert_equal config, actual
      end

      def test_blank
        config = {}
        actual = resolve_config(config)
        assert_equal config, actual
      end

      def test_blank_with_database_url
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = {}
        actual   = resolve_config(config)
        expected = { "adapter"  => "postgresql",
                     "database" => "foo",
                     "host"     => "localhost" }
        assert_equal expected, actual["default_env"]
        assert_nil actual["production"]
        assert_nil actual["development"]
        assert_nil actual["test"]
        assert_nil actual[:default_env]
        assert_nil actual[:production]
        assert_nil actual[:development]
        assert_nil actual[:test]
      end

      def test_blank_with_database_url_with_rails_env
        ENV["RAILS_ENV"] = "not_production"
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = {}
        actual   = resolve_config(config)
        expected = { "adapter"  => "postgresql",
                     "database" => "foo",
                     "host"     => "localhost" }

        assert_equal expected, actual["not_production"]
        assert_nil actual["production"]
        assert_nil actual["default_env"]
        assert_nil actual["development"]
        assert_nil actual["test"]
        assert_nil actual[:default_env]
        assert_nil actual[:not_production]
        assert_nil actual[:production]
        assert_nil actual[:development]
        assert_nil actual[:test]
      end

      def test_blank_with_database_url_with_rack_env
        ENV["RACK_ENV"] = "not_production"
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = {}
        actual   = resolve_config(config)
        expected = { "adapter"  => "postgresql",
                     "database" => "foo",
                     "host"     => "localhost" }

        assert_equal expected, actual["not_production"]
        assert_nil actual["production"]
        assert_nil actual["default_env"]
        assert_nil actual["development"]
        assert_nil actual["test"]
        assert_nil actual[:default_env]
        assert_nil actual[:not_production]
        assert_nil actual[:production]
        assert_nil actual[:development]
        assert_nil actual[:test]
      end

      def test_database_url_with_ipv6_host_and_port
        ENV["DATABASE_URL"] = "postgres://[::1]:5454/foo"

        config   = {}
        actual   = resolve_config(config)
        expected = { "adapter"  => "postgresql",
                     "database" => "foo",
                     "host"     => "::1",
                     "port"     => 5454 }
        assert_equal expected, actual["default_env"]
      end

      def test_url_sub_key_with_database_url
        ENV["DATABASE_URL"] = "NOT-POSTGRES://localhost/NOT_FOO"

        config   = { "default_env" => { "url" => "postgres://localhost/foo" } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                    { "adapter" => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost"
                      }
                    }
        assert_equal expected, actual
      end

      def test_no_url_sub_key_with_database_url_doesnt_trample_other_envs
        ENV["DATABASE_URL"] = "postgres://localhost/baz"

        config   = { "default_env" => { "database" => "foo" }, "other_env" => { "url" => "postgres://foohost/bardb" } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "database" => "baz",
                      "adapter" => "postgresql",
                      "host" => "localhost"
                     },
                     "other_env" =>
                      { "adapter" => "postgresql",
                       "database" => "bardb",
                       "host"     => "foohost"
                      }
                    }
        assert_equal expected, actual
      end

      def test_merge_no_conflicts_with_database_url
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = { "default_env" => { "pool" => "5" } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "adapter"  => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost",
                       "pool"     => "5"
                      }
                    }
        assert_equal expected, actual
      end

      def test_merge_conflicts_with_database_url
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = { "default_env" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "adapter"  => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost",
                       "pool"     => "5"
                      }
                    }
        assert_equal expected, actual
      end

      def test_merge_no_conflicts_with_database_url_and_adapter
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = { "default_env" => { "adapter" => "postgresql", "pool" => "5" } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "adapter"  => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost",
                       "pool"     => "5"
                     }
        }
        assert_equal expected, actual
      end

      def test_merge_no_conflicts_with_database_url_and_numeric_pool
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config   = { "default_env" => { "pool" => 5 } }
        actual   = resolve_config(config)
        expected = { "default_env" =>
                     { "adapter"  => "postgresql",
                       "database" => "foo",
                       "host"     => "localhost",
                       "pool"     => 5
                     }
        }

        assert_equal expected, actual
      end

      def test_tiered_configs_with_database_url
        ENV["DATABASE_URL"] = "postgres://localhost/foo"

        config = {
          "default_env" => {
            "primary" => { "pool" => 5 },
            "animals" => { "pool" => 5 }
          }
        }

        configs = ActiveRecord::DatabaseConfigurations.new(config)
        actual = configs.configs_for(env_name: "default_env", spec_name: "primary").config
        expected = {
          "adapter"  => "postgresql",
          "database" => "foo",
          "host"     => "localhost",
          "pool"     => 5
        }

        assert_equal expected, actual

        configs = ActiveRecord::DatabaseConfigurations.new(config)
        actual = configs.configs_for(env_name: "default_env", spec_name: "animals").config
        expected = { "pool" => 5 }

        assert_equal expected, actual
      end

      def test_separate_database_env_vars
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        ENV["PRIMARY_DATABASE_URL"] = "postgres://localhost/primary"
        ENV["ANIMALS_DATABASE_URL"] = "postgres://localhost/animals"

        config = {
          "default_env" => {
            "primary" => { "pool" => 5 },
            "animals" => { "pool" => 5 }
          }
        }

        configs = ActiveRecord::DatabaseConfigurations.new(config)
        actual = configs.configs_for(env_name: "default_env", spec_name: "primary").config
        assert_equal "primary", actual["database"]

        configs = ActiveRecord::DatabaseConfigurations.new(config)
        actual = configs.configs_for(env_name: "default_env", spec_name: "animals").config
        assert_equal "animals", actual["database"]
      ensure
        ENV.delete("PRIMARY_DATABASE_URL")
        ENV.delete("ANIMALS_DATABASE_URL")
      end

      def test_does_not_change_other_environments
        ENV["DATABASE_URL"] = "postgres://localhost/foo"
        config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" }, "default_env" => {} }

        actual = resolve_spec(:production, config)
        assert_equal config["production"].merge("name" => "production"), actual

        actual = resolve_spec(:default_env, config)
        assert_equal({
          "host" => "localhost",
          "database" => "foo",
          "adapter" => "postgresql",
          "name" => "default_env"
        }, actual)
      end
    end
  end
end