goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/database/database_test.go (about)

     1  package database
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  	"gorm.io/driver/sqlite"
    11  	"gorm.io/gorm"
    12  	"gorm.io/gorm/utils/tests"
    13  	"goyave.dev/goyave/v5/config"
    14  	"goyave.dev/goyave/v5/slog"
    15  )
    16  
    17  type DummyDialector struct {
    18  	tests.DummyDialector
    19  	DSN string
    20  }
    21  
    22  func openDummy(dsn string) gorm.Dialector {
    23  	return &DummyDialector{
    24  		DSN: dsn,
    25  	}
    26  }
    27  
    28  func TestNewDatabase(t *testing.T) {
    29  	RegisterDialect("dummy", "host={host} port={port} user={username} dbname={name} password={password} {options}", openDummy)
    30  	RegisterDialect("sqlite3_test", "file:{name}?{options}", sqlite.Open)
    31  	t.Cleanup(func() {
    32  		mu.Lock()
    33  		delete(dialects, "dummy")
    34  		delete(dialects, "sqlite3_test")
    35  		mu.Unlock()
    36  	})
    37  
    38  	t.Run("RegisterDialect_already_exists", func(t *testing.T) {
    39  		assert.Panics(t, func() {
    40  			RegisterDialect("dummy", "", openDummy)
    41  		})
    42  	})
    43  
    44  	t.Run("New", func(t *testing.T) {
    45  		cfg := config.LoadDefault()
    46  		cfg.Set("app.debug", true)
    47  		cfg.Set("database.connection", "dummy")
    48  		cfg.Set("database.host", "localhost")
    49  		cfg.Set("database.port", 5432)
    50  		cfg.Set("database.name", "dbname")
    51  		cfg.Set("database.username", "user")
    52  		cfg.Set("database.password", "secret")
    53  		cfg.Set("database.options", "option=value")
    54  		cfg.Set("database.maxOpenConnections", 123)
    55  		cfg.Set("database.maxIdleConnections", 123)
    56  		cfg.Set("database.maxLifetime", 123)
    57  		cfg.Set("database.defaultReadQueryTimeout", 123)
    58  		cfg.Set("database.defaultWriteQueryTimeout", 123)
    59  		cfg.Set("database.config.skipDefaultTransaction", true)
    60  		cfg.Set("database.config.dryRun", true)
    61  		cfg.Set("database.config.prepareStmt", false)
    62  		cfg.Set("database.config.disableNestedTransaction", true)
    63  		cfg.Set("database.config.allowGlobalUpdate", true)
    64  		cfg.Set("database.config.disableAutomaticPing", true)
    65  		cfg.Set("database.config.disableForeignKeyConstraintWhenMigrating", true)
    66  
    67  		slogger := slog.New(slog.NewHandler(true, &bytes.Buffer{}))
    68  		db, err := New(cfg, func() *slog.Logger { return slogger })
    69  		require.NoError(t, err)
    70  		require.NotNil(t, db)
    71  
    72  		if assert.NotNil(t, db.Config.Logger) {
    73  			// Logging is enabled when app.debug is true
    74  			l, ok := db.Config.Logger.(*Logger)
    75  			if assert.True(t, ok) {
    76  				assert.NotNil(t, l.slogger)
    77  			}
    78  		}
    79  
    80  		dbConfig := db.Config
    81  		// Can't check log level (gorm logger unexported)
    82  		assert.True(t, dbConfig.SkipDefaultTransaction)
    83  		assert.True(t, dbConfig.DryRun)
    84  		assert.False(t, dbConfig.PrepareStmt)
    85  		assert.True(t, dbConfig.DisableNestedTransaction)
    86  		assert.True(t, dbConfig.AllowGlobalUpdate)
    87  		assert.True(t, dbConfig.DisableAutomaticPing)
    88  		assert.True(t, dbConfig.DisableAutomaticPing)
    89  
    90  		// Cannot check the max open conns, idle conns and lifetime
    91  
    92  		plugin, ok := db.Plugins[(&TimeoutPlugin{}).Name()]
    93  		if assert.True(t, ok) {
    94  			timeoutPlugin, ok := plugin.(*TimeoutPlugin)
    95  			if assert.True(t, ok) {
    96  				assert.Equal(t, 123*time.Millisecond, timeoutPlugin.ReadTimeout)
    97  				assert.Equal(t, 123*time.Millisecond, timeoutPlugin.WriteTimeout)
    98  			}
    99  		}
   100  
   101  	})
   102  
   103  	t.Run("silent", func(t *testing.T) {
   104  		cfg := config.LoadDefault()
   105  		cfg.Set("app.debug", false)
   106  		cfg.Set("database.connection", "dummy")
   107  		cfg.Set("database.host", "localhost")
   108  		cfg.Set("database.port", 5432)
   109  		cfg.Set("database.name", "dbname")
   110  		cfg.Set("database.username", "user")
   111  		cfg.Set("database.password", "secret")
   112  		cfg.Set("database.options", "option=value")
   113  		cfg.Set("database.maxOpenConnections", 123)
   114  		cfg.Set("database.maxIdleConnections", 123)
   115  		cfg.Set("database.maxLifetime", 123)
   116  		cfg.Set("database.defaultReadQueryTimeout", 123)
   117  		cfg.Set("database.defaultWriteQueryTimeout", 123)
   118  		cfg.Set("database.config.skipDefaultTransaction", true)
   119  		cfg.Set("database.config.dryRun", true)
   120  		cfg.Set("database.config.prepareStmt", false)
   121  		cfg.Set("database.config.disableNestedTransaction", true)
   122  		cfg.Set("database.config.allowGlobalUpdate", true)
   123  		cfg.Set("database.config.disableAutomaticPing", true)
   124  		cfg.Set("database.config.disableForeignKeyConstraintWhenMigrating", true)
   125  
   126  		logger := slog.New(slog.NewHandler(false, &bytes.Buffer{}))
   127  		db, err := New(cfg, func() *slog.Logger { return logger })
   128  		require.NoError(t, err)
   129  		require.NotNil(t, db)
   130  
   131  		if assert.NotNil(t, db.Config.Logger) {
   132  			// Logging is disable when app.debug is false
   133  			l, ok := db.Config.Logger.(*Logger)
   134  			if assert.True(t, ok) {
   135  				assert.Nil(t, l.slogger)
   136  			}
   137  		}
   138  	})
   139  
   140  	t.Run("NewFromDialector", func(t *testing.T) {
   141  		cfg := config.LoadDefault()
   142  		cfg.Set("app.debug", true)
   143  		cfg.Set("database.connection", "dummy")
   144  		cfg.Set("database.host", "localhost")
   145  		cfg.Set("database.port", 5432)
   146  		cfg.Set("database.name", "dbname")
   147  		cfg.Set("database.username", "user")
   148  		cfg.Set("database.password", "secret")
   149  		cfg.Set("database.options", "option=value")
   150  		cfg.Set("database.maxOpenConnections", 123)
   151  		cfg.Set("database.maxIdleConnections", 123)
   152  		cfg.Set("database.maxLifetime", 123)
   153  		cfg.Set("database.defaultReadQueryTimeout", 123)
   154  		cfg.Set("database.defaultWriteQueryTimeout", 123)
   155  		cfg.Set("database.config.skipDefaultTransaction", true)
   156  		cfg.Set("database.config.dryRun", true)
   157  		cfg.Set("database.config.prepareStmt", false)
   158  		cfg.Set("database.config.disableNestedTransaction", true)
   159  		cfg.Set("database.config.allowGlobalUpdate", true)
   160  		cfg.Set("database.config.disableAutomaticPing", true)
   161  		cfg.Set("database.config.disableForeignKeyConstraintWhenMigrating", true)
   162  
   163  		dialector := &DummyDialector{}
   164  		db, err := NewFromDialector(cfg, nil, dialector)
   165  		require.NoError(t, err)
   166  		require.NotNil(t, db)
   167  
   168  		dbConfig := db.Config
   169  		// Can't check log level (gorm logger unexported)
   170  		assert.True(t, dbConfig.SkipDefaultTransaction)
   171  		assert.True(t, dbConfig.DryRun)
   172  		assert.False(t, dbConfig.PrepareStmt)
   173  		assert.True(t, dbConfig.DisableNestedTransaction)
   174  		assert.True(t, dbConfig.AllowGlobalUpdate)
   175  		assert.True(t, dbConfig.DisableAutomaticPing)
   176  		assert.True(t, dbConfig.DisableAutomaticPing)
   177  
   178  		// Cannot check the max open conns, idle conns and lifetime
   179  
   180  		plugin, ok := db.Plugins[(&TimeoutPlugin{}).Name()]
   181  		if assert.True(t, ok) {
   182  			timeoutPlugin, ok := plugin.(*TimeoutPlugin)
   183  			if assert.True(t, ok) {
   184  				assert.Equal(t, 123*time.Millisecond, timeoutPlugin.ReadTimeout)
   185  				assert.Equal(t, 123*time.Millisecond, timeoutPlugin.WriteTimeout)
   186  			}
   187  		}
   188  
   189  	})
   190  
   191  	t.Run("New_connection_none", func(t *testing.T) {
   192  		cfg := config.LoadDefault()
   193  		cfg.Set("database.connection", "none")
   194  		db, err := New(cfg, nil)
   195  		assert.Nil(t, db)
   196  		require.Error(t, err)
   197  		assert.Equal(t, "Cannot create DB connection. Database is set to \"none\" in the config", err.Error())
   198  	})
   199  
   200  	t.Run("New_unknown_driver", func(t *testing.T) {
   201  		cfg := config.LoadDefault()
   202  		cfg.Set("database.connection", "notadriver")
   203  		db, err := New(cfg, nil)
   204  		assert.Nil(t, db)
   205  		require.Error(t, err)
   206  		assert.Equal(t, "DB Connection \"notadriver\" not supported, forgotten import?", err.Error())
   207  	})
   208  
   209  	t.Run("SQLite_query", func(t *testing.T) {
   210  		cfg := config.LoadDefault()
   211  		cfg.Set("app.debug", false)
   212  		cfg.Set("database.connection", "sqlite3_test")
   213  		cfg.Set("database.name", "database_test.db")
   214  		cfg.Set("database.options", "mode=memory")
   215  
   216  		db, err := New(cfg, nil)
   217  		require.NoError(t, err)
   218  		require.NotNil(t, db)
   219  
   220  		dbNames := []string{}
   221  		res := db.Table("pragma_database_list").Select("name").Find(&dbNames)
   222  		require.NoError(t, res.Error)
   223  		assert.Equal(t, []string{"main"}, dbNames)
   224  	})
   225  }