aboutsummaryrefslogblamecommitdiffstats
path: root/activerecord/test/cases/tasks/mysql_rake_test.rb
blob: 258132835fc3c748fa671bdbf94fa713890ca527 (plain) (tree)
1
2
3
4
5
6
7
8
9

                             

                                            
 
                                   


                                                    
                                                                      



                                   


                                                         
 


                                                             
 
                                                      
                                                            









                                                                    
           
         
 
                                                       
                                                       


                                                                                 
           
         
 
                                                   
                                                       


                                                                                                  
           
         
 
                                                    
                                                       






                                                                                                              
           
         
 
                                                 
                                                            









                                                                    
           
         
 
                                                                        

                                                                  
 

                                                                       
         
 
                                                                 










                                                                                
 
             
                                                        
                                                                




                                                                
       
 
                                                                          
               






                                                                 


                                                         
 


                                                             
 
                           


                                                                                
             
           
         

       

                                                  
                                                                       



                                   


                                                         
 


                                                             
 
                                                       







                                                                  
           
         
 
                             
                                                       


                                                                           
           
         
 
                                                                        

                                                                
 

                                                                       
         

             
                                                        
                                                                




                                                                

       

                                                 
                                                                        



                                 
         
 
                                                                 







                                                                   
           
         
 
                                                         
                                                       


                                                                                 
           
         
 
                                                        
                                                       







                                                                          
           
         

             
                                                        
                                                                




                                                                
       
 

                                                     
                                                           



                                   


                                   
                                                            


                                                                     
           
         

       

                                                       
                                                             



                                   
         
 
                                     
                                                            
                                                   

                                                                       
           
         
       
 









                                                         







                                                                                                            
         
 

                                              
                                                                                                                                      







                                                                                       

                                                








                                                                                                                                                                          
           

         

                                                                        










                                                                                                            
         
 

                                              









                                                                                                                            



                                      









                                                                                                                               
         








                                                                         

       









                                                         
                                                                                                                                                                   















                                                                                       

       
   
# 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    = Class.new { def create_database(*); end }.new
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "my-app-db"
        }
        $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.stub(:connection, @connection) do
          assert_called_with(
            ActiveRecord::Base,
            :establish_connection,
            [
              [ "adapter" => "mysql2", "database" => nil ],
              [ "adapter" => "mysql2", "database" => "my-app-db" ],
            ]
          ) do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration
          end
        end
      end

      def test_creates_database_with_no_default_options
        with_stubbed_connection_establish_connection do
          assert_called_with(@connection, :create_database, ["my-app-db", {}]) do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration
          end
        end
      end

      def test_creates_database_with_given_encoding
        with_stubbed_connection_establish_connection do
          assert_called_with(@connection, :create_database, ["my-app-db", charset: "latin1"]) do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge("encoding" => "latin1")
          end
        end
      end

      def test_creates_database_with_given_collation
        with_stubbed_connection_establish_connection do
          assert_called_with(
            @connection,
            :create_database,
            ["my-app-db", collation: "latin1_swedish_ci"]
          ) do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge("collation" => "latin1_swedish_ci")
          end
        end
      end

      def test_establishes_connection_to_database
        ActiveRecord::Base.stub(:connection, @connection) do
          assert_called_with(
            ActiveRecord::Base,
            :establish_connection,
            [
              ["adapter" => "mysql2", "database" => nil],
              [@configuration]
            ]
          ) do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration
          end
        end
      end

      def test_when_database_created_successfully_outputs_info_to_stdout
        with_stubbed_connection_establish_connection do
          ActiveRecord::Tasks::DatabaseTasks.create @configuration

          assert_equal "Created database 'my-app-db'\n", $stdout.string
        end
      end

      def test_create_when_database_exists_outputs_info_to_stderr
        with_stubbed_connection_establish_connection do
          ActiveRecord::Base.connection.stub(
            :create_database,
            proc { raise ActiveRecord::Tasks::DatabaseAlreadyExists }
          ) do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration

            assert_equal "Database 'my-app-db' already exists\n", $stderr.string
          end
        end
      end

      private
        def with_stubbed_connection_establish_connection
          ActiveRecord::Base.stub(:establish_connection, nil) do
            ActiveRecord::Base.stub(:connection, @connection) do
              yield
            end
          end
        end
    end

    class MysqlDBCreateWithInvalidPermissionsTest < ActiveRecord::TestCase
      def setup
        @error         = Mysql2::Error.new("Invalid permissions")
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "my-app-db",
          "username" => "pat",
          "password" => "wossname"
        }
        $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
        ActiveRecord::Base.stub(:establish_connection, -> * { raise @error }) do
          assert_raises(Mysql2::Error, "Invalid permissions") do
            ActiveRecord::Tasks::DatabaseTasks.create @configuration
          end
        end
      end
    end

    class MySQLDBDropTest < ActiveRecord::TestCase
      def setup
        @connection    = Class.new { def drop_database(name); end }.new
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "my-app-db"
        }
        $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.stub(:connection, @connection) do
          assert_called_with(
            ActiveRecord::Base,
            :establish_connection,
            [@configuration]
          ) do
            ActiveRecord::Tasks::DatabaseTasks.drop @configuration
          end
        end
      end

      def test_drops_database
        with_stubbed_connection_establish_connection do
          assert_called_with(@connection, :drop_database, ["my-app-db"]) do
            ActiveRecord::Tasks::DatabaseTasks.drop @configuration
          end
        end
      end

      def test_when_database_dropped_successfully_outputs_info_to_stdout
        with_stubbed_connection_establish_connection do
          ActiveRecord::Tasks::DatabaseTasks.drop @configuration

          assert_equal "Dropped database 'my-app-db'\n", $stdout.string
        end
      end

      private
        def with_stubbed_connection_establish_connection
          ActiveRecord::Base.stub(:establish_connection, nil) do
            ActiveRecord::Base.stub(:connection, @connection) do
              yield
            end
          end
        end
    end

    class MySQLPurgeTest < ActiveRecord::TestCase
      def setup
        @connection    = Class.new { def recreate_database(*); end }.new
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "test-db"
        }
      end

      def test_establishes_connection_to_the_appropriate_database
        ActiveRecord::Base.stub(:connection, @connection) do
          assert_called_with(
            ActiveRecord::Base,
            :establish_connection,
            [@configuration]
          ) do
            ActiveRecord::Tasks::DatabaseTasks.purge @configuration
          end
        end
      end

      def test_recreates_database_with_no_default_options
        with_stubbed_connection_establish_connection do
          assert_called_with(@connection, :recreate_database, ["test-db", {}]) do
            ActiveRecord::Tasks::DatabaseTasks.purge @configuration
          end
        end
      end

      def test_recreates_database_with_the_given_options
        with_stubbed_connection_establish_connection do
          assert_called_with(
            @connection,
            :recreate_database,
            ["test-db", charset: "latin", collation: "latin1_swedish_ci"]
          ) do
            ActiveRecord::Tasks::DatabaseTasks.purge @configuration.merge(
              "encoding" => "latin", "collation" => "latin1_swedish_ci")
          end
        end
      end

      private
        def with_stubbed_connection_establish_connection
          ActiveRecord::Base.stub(:establish_connection, nil) do
            ActiveRecord::Base.stub(:connection, @connection) do
              yield
            end
          end
        end
    end

    class MysqlDBCharsetTest < ActiveRecord::TestCase
      def setup
        @connection    = Class.new { def charset; end }.new
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "my-app-db"
        }
      end

      def test_db_retrieves_charset
        ActiveRecord::Base.stub(:connection, @connection) do
          assert_called(@connection, :charset) do
            ActiveRecord::Tasks::DatabaseTasks.charset @configuration
          end
        end
      end
    end

    class MysqlDBCollationTest < ActiveRecord::TestCase
      def setup
        @connection    = Class.new { def collation; end }.new
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "my-app-db"
        }
      end

      def test_db_retrieves_collation
        ActiveRecord::Base.stub(:connection, @connection) do
          assert_called(@connection, :collation) do
            ActiveRecord::Tasks::DatabaseTasks.collation @configuration
          end
        end
      end
    end

    class MySQLStructureDumpTest < ActiveRecord::TestCase
      def setup
        @configuration = {
          "adapter"  => "mysql2",
          "database" => "test-db"
        }
      end

      def test_structure_dump
        filename = "awesome-file.sql"
        assert_called_with(
          Kernel,
          :system,
          ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
          returns: true
        ) do
          ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
        end
      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.stub(:ignore_tables, ["foo", "bar"]) do
          assert_called_with(
            Kernel,
            :system,
            ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "--ignore-table=test-db.foo", "--ignore-table=test-db.bar", "test-db"],
            returns: true
          ) do
            ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
          end
        end
      end

      def test_warn_when_external_structure_dump_command_execution_fails
        filename = "awesome-file.sql"
        assert_called_with(
          Kernel,
          :system,
          ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
          returns: false
        ) do
          e = assert_raise(RuntimeError) {
            ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
          }
          assert_match(/^failed to execute: `mysqldump`$/, e.message)
        end
      end

      def test_structure_dump_with_port_number
        filename = "awesome-file.sql"
        assert_called_with(
          Kernel,
          :system,
          ["mysqldump", "--port=10000", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
          returns: true
        ) do
          ActiveRecord::Tasks::DatabaseTasks.structure_dump(
            @configuration.merge("port" => 10000),
            filename)
        end
      end

      def test_structure_dump_with_ssl
        filename = "awesome-file.sql"
        assert_called_with(
          Kernel,
          :system,
          ["mysqldump", "--ssl-ca=ca.crt", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"],
          returns: true
        ) do
            ActiveRecord::Tasks::DatabaseTasks.structure_dump(
              @configuration.merge("sslca" => "ca.crt"),
              filename)
          end
      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