From 6f8523a0081f02905ed9e6ae97c4db96e67ef49e Mon Sep 17 00:00:00 2001 From: nickolasdaniel Date: Mon, 22 Mar 2021 13:54:57 +0200 Subject: [PATCH] Coverage tests for ees --- ees/sql.go | 66 +++++++++++++++++++++----------------------- ees/sql_it_test.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++ ees/sql_test.go | 62 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 34 deletions(-) diff --git a/ees/sql.go b/ees/sql.go index 233ed4b88..494877fd2 100644 --- a/ees/sql.go +++ b/ees/sql.go @@ -34,6 +34,34 @@ import ( "github.com/cgrates/cgrates/utils" ) +func NewSQLEe(cgrCfg *config.CGRConfig, cfgIdx int, filterS *engine.FilterS, + dc utils.MapStorage) (sqlEe *SQLEe, err error) { + sqlEe = &SQLEe{id: cgrCfg.EEsCfg().Exporters[cfgIdx].ID, + cgrCfg: cgrCfg, cfgIdx: cfgIdx, filterS: filterS, dc: dc} + + dialect, err := sqlEe.NewSQLEeUrl(cgrCfg) + if err != nil { + return + } + sqlEe.db, sqlEe.sqldb, err = openDB(cgrCfg, cfgIdx, dialect) + return +} + +// SQLEe implements EventExporter interface for SQL +type SQLEe struct { + id string + cgrCfg *config.CGRConfig + cfgIdx int // index of config instance within ERsCfg.Readers + filterS *engine.FilterS + db *gorm.DB + sqldb *sql.DB + + tableName string + + sync.RWMutex + dc utils.MapStorage +} + func (sqlEe *SQLEe) NewSQLEeUrl(cgrCfg *config.CGRConfig) (dialect gorm.Dialector, err error) { var u *url.URL // var err error @@ -70,69 +98,40 @@ func (sqlEe *SQLEe) NewSQLEeUrl(cgrCfg *config.CGRConfig) (dialect gorm.Dialecto return } -func NewSQLEe(cgrCfg *config.CGRConfig, cfgIdx int, filterS *engine.FilterS, - dc utils.MapStorage) (sqlEe *SQLEe, err error) { - sqlEe = &SQLEe{id: cgrCfg.EEsCfg().Exporters[cfgIdx].ID, - cgrCfg: cgrCfg, cfgIdx: cfgIdx, filterS: filterS, dc: dc} +func openDB(cgrCfg *config.CGRConfig, cfgIdx int, dialect gorm.Dialector) (db *gorm.DB, sqlDB *sql.DB, err error) { - dialect, err := sqlEe.NewSQLEeUrl(cgrCfg) - if err != nil { - return - } - var db *gorm.DB if db, err = gorm.Open(dialect, &gorm.Config{AllowGlobalUpdate: true}); err != nil { return } - var sqlDB *sql.DB if sqlDB, err = db.DB(); err != nil { return } - if err = sqlDB.Ping(); err != nil { - return - } if iface, has := cgrCfg.EEsCfg().Exporters[cfgIdx].Opts[utils.SQLMaxIdleConns]; has { val, err := utils.IfaceAsTInt64(iface) if err != nil { - return nil, err + return nil, nil, err } sqlDB.SetMaxIdleConns(int(val)) } if iface, has := cgrCfg.EEsCfg().Exporters[cfgIdx].Opts[utils.SQLMaxOpenConns]; has { val, err := utils.IfaceAsTInt64(iface) if err != nil { - return nil, err + return nil, nil, err } sqlDB.SetMaxOpenConns(int(val)) } if iface, has := cgrCfg.EEsCfg().Exporters[cfgIdx].Opts[utils.SQLMaxConnLifetime]; has { val, err := utils.IfaceAsDuration(iface) if err != nil { - return nil, err + return nil, nil, err } sqlDB.SetConnMaxLifetime(val) } - sqlEe.db = db - sqlEe.sqldb = sqlDB return } -// SQLEe implements EventExporter interface for SQL -type SQLEe struct { - id string - cgrCfg *config.CGRConfig - cfgIdx int // index of config instance within ERsCfg.Readers - filterS *engine.FilterS - db *gorm.DB - sqldb *sql.DB - - tableName string - - sync.RWMutex - dc utils.MapStorage -} - // ID returns the identificator of this exporter func (sqlEe *SQLEe) ID() string { return sqlEe.id @@ -141,7 +140,6 @@ func (sqlEe *SQLEe) ID() string { // OnEvicted implements EventExporter, doing the cleanup before exit func (sqlEe *SQLEe) OnEvicted(_ string, _ interface{}) { sqlEe.sqldb.Close() - return } // ExportEvent implements EventExporter diff --git a/ees/sql_it_test.go b/ees/sql_it_test.go index 66c8bdee1..b92c74ca5 100644 --- a/ees/sql_it_test.go +++ b/ees/sql_it_test.go @@ -228,3 +228,72 @@ func testSqlEeVerifyExportedEvent2(t *testing.T) { t.Fatal("Expected table to have only one result ", result) } } + +func TestOpenDB1(t *testing.T) { + cgrCfg := config.NewDefaultCGRConfig() + cgrCfg.EEsCfg().Exporters[0].Opts[utils.SQLMaxIdleConns] = 2 + dialect := mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true&sql_mode='ALLOW_INVALID_DATES'", + "cgrates", "CGRateS.org", "127.0.0.1", "3306", "cgrates")) + _, _, err := openDB(cgrCfg, 0, dialect) + if err != nil { + t.Error(err) + } +} + +func TestOpenDB1Err(t *testing.T) { + cgrCfg := config.NewDefaultCGRConfig() + cgrCfg.EEsCfg().Exporters[0].Opts[utils.SQLMaxIdleConns] = "test" + dialect := mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true&sql_mode='ALLOW_INVALID_DATES'", + "cgrates", "CGRateS.org", "127.0.0.1", "3306", "cgrates")) + _, _, err := openDB(cgrCfg, 0, dialect) + errExpect := "strconv.ParseInt: parsing \"test\": invalid syntax" + if err == nil || err.Error() != errExpect { + t.Errorf("Expected %v but received %v", errExpect, err) + } +} + +func TestOpenDB2(t *testing.T) { + cgrCfg := config.NewDefaultCGRConfig() + cgrCfg.EEsCfg().Exporters[0].Opts[utils.SQLMaxOpenConns] = 2 + dialect := mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true&sql_mode='ALLOW_INVALID_DATES'", + "cgrates", "CGRateS.org", "127.0.0.1", "3306", "cgrates")) + _, _, err := openDB(cgrCfg, 0, dialect) + if err != nil { + t.Error(err) + } +} + +func TestOpenDB2Err(t *testing.T) { + cgrCfg := config.NewDefaultCGRConfig() + cgrCfg.EEsCfg().Exporters[0].Opts[utils.SQLMaxOpenConns] = "test" + dialect := mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true&sql_mode='ALLOW_INVALID_DATES'", + "cgrates", "CGRateS.org", "127.0.0.1", "3306", "cgrates")) + _, _, err := openDB(cgrCfg, 0, dialect) + errExpect := "strconv.ParseInt: parsing \"test\": invalid syntax" + if err == nil || err.Error() != errExpect { + t.Errorf("Expected %v but received %v", errExpect, err) + } +} + +func TestOpenDB3(t *testing.T) { + cgrCfg := config.NewDefaultCGRConfig() + cgrCfg.EEsCfg().Exporters[0].Opts[utils.SQLMaxConnLifetime] = 2 + dialect := mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true&sql_mode='ALLOW_INVALID_DATES'", + "cgrates", "CGRateS.org", "127.0.0.1", "3306", "cgrates")) + _, _, err := openDB(cgrCfg, 0, dialect) + if err != nil { + t.Error(err) + } +} + +func TestOpenDB3Err(t *testing.T) { + cgrCfg := config.NewDefaultCGRConfig() + cgrCfg.EEsCfg().Exporters[0].Opts[utils.SQLMaxConnLifetime] = "test" + dialect := mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true&sql_mode='ALLOW_INVALID_DATES'", + "cgrates", "CGRateS.org", "127.0.0.1", "3306", "cgrates")) + _, _, err := openDB(cgrCfg, 0, dialect) + errExpect := "time: invalid duration \"test\"" + if err == nil || err.Error() != errExpect { + t.Errorf("Expected %v but received %v", errExpect, err) + } +} diff --git a/ees/sql_test.go b/ees/sql_test.go index 9193d8d10..ce2ccfce9 100644 --- a/ees/sql_test.go +++ b/ees/sql_test.go @@ -28,6 +28,8 @@ import ( "github.com/cgrates/cgrates/utils" "gorm.io/driver/mysql" "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm.io/gorm/logger" ) func TestSqlID(t *testing.T) { @@ -154,3 +156,63 @@ func TestNewSQLeExportPathError(t *testing.T) { t.Errorf("Expected %v but received %v", errExpect, err) } } + +// type mockConnPool struct { +// sqldb *sql.DB +// } + +// func (mcp mockConnPool) Ping() error { +// return nil +// } +// func (mockConnPool) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) { +// return nil, nil +// } +// func (mockConnPool) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { +// return nil, nil +// } +// func (mockConnPool) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) { +// return nil, nil +// } +// func (mockConnPool) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { +// return nil +// } + +type mockDialect2 struct { + gorm.Dialector +} + +func (mockDialect2) Initialize(db *gorm.DB) error { return nil } + +func TestOpenDBError2(t *testing.T) { + tmp := logger.Default + logger.Default = logger.Default.LogMode(logger.Silent) + cgrCfg := config.NewDefaultCGRConfig() + mckDialect := new(mockDialect2) + _, _, err := openDB(cgrCfg, 0, mckDialect) + errExpect := "invalid db" + if err == nil || err.Error() != errExpect { + t.Errorf("Expected %v but received %v", errExpect, err) + } + logger.Default = tmp +} + +type mockDialectErr struct { + gorm.Dialector +} + +func (mockDialectErr) Initialize(db *gorm.DB) error { + return utils.ErrNotFound +} + +func TestOpenDBError3(t *testing.T) { + tmp := logger.Default + logger.Default = logger.Default.LogMode(logger.Silent) + cgrCfg := config.NewDefaultCGRConfig() + mckDialect := new(mockDialectErr) + _, _, err := openDB(cgrCfg, 0, mckDialect) + errExpect := "NOT_FOUND" + if err == nil || err.Error() != errExpect { + t.Errorf("Expected %v but received %v", errExpect, err) + } + logger.Default = tmp +}