Skip to content

Commit

Permalink
test(db): fix races with logfrom
Browse files Browse the repository at this point in the history
  • Loading branch information
JosephKav committed Apr 6, 2024
1 parent 3c34f19 commit 550d6ce
Show file tree
Hide file tree
Showing 19 changed files with 116 additions and 103 deletions.
3 changes: 2 additions & 1 deletion cmd/argus/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ func main() {
}
}

go db.Run(&config, &jLog)
db.LogInit(&jLog, config.Settings.DataDatabaseFile())
go db.Run(&config)

// Track all targets for changes in version and act on any found changes.
go (&config).Service.Track(&config.Order, &config.OrderMutex)
Expand Down
3 changes: 2 additions & 1 deletion config/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func testLoad(file string, t *testing.T) (config *Config) {
loadMutex.Lock()
defer loadMutex.Unlock()
config.Load(file, &flags, log)
t.Cleanup(func() { os.Remove(*config.Settings.DataDatabaseFile()) })
t.Cleanup(func() { os.Remove(config.Settings.DataDatabaseFile()) })

return
}
Expand Down Expand Up @@ -143,6 +143,7 @@ func testLoadBasic(file string, t *testing.T) (config *Config) {
service.ID = name
}
config.CheckValues()
t.Log("Loaded", file)

return
}
Expand Down
2 changes: 1 addition & 1 deletion config/ordering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestConfig_LoadOrdering(t *testing.T) {
lock.Lock()
config.Load(file, &flags, log)
lock.Unlock()
defer os.Remove(*config.Settings.DataDatabaseFile())
defer os.Remove(config.Settings.DataDatabaseFile())

// THEN it gets the ordering correctly
gotOrder := config.Order
Expand Down
6 changes: 3 additions & 3 deletions config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,11 @@ func (s *Settings) LogLevel() string {
}

// DataDatabaseFile.
func (s *Settings) DataDatabaseFile() *string {
return util.FirstNonNilPtr(
func (s *Settings) DataDatabaseFile() string {
return util.DefaultIfNil(util.FirstNonNilPtr(
s.FromFlags.Data.DatabaseFile,
s.Data.DatabaseFile,
s.HardDefaults.Data.DatabaseFile)
s.HardDefaults.Data.DatabaseFile))
}

// WebListenHost.
Expand Down
12 changes: 6 additions & 6 deletions config/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,17 @@ func TestSettings_GetString(t *testing.T) {
want: "ERROR",
},
"data.database-file hard default": {
getFuncPtr: settings.DataDatabaseFile,
flag: &DataDatabaseFile, want: "data/argus.db",
getFunc: settings.DataDatabaseFile,
flag: &DataDatabaseFile, want: "data/argus.db",
nilConfig: true, configPtr: &settings.Data.DatabaseFile,
},
"data.database-file config": {
getFuncPtr: settings.DataDatabaseFile,
flag: &DataDatabaseFile, want: "somewhere.db",
getFunc: settings.DataDatabaseFile,
flag: &DataDatabaseFile, want: "somewhere.db",
},
"data.database-file flag": {
getFuncPtr: settings.DataDatabaseFile,
flag: &DataDatabaseFile, flagVal: stringPtr("ERROR"),
getFunc: settings.DataDatabaseFile,
flag: &DataDatabaseFile, flagVal: stringPtr("ERROR"),
want: "ERROR",
},
"web.listen-host hard default": {
Expand Down
18 changes: 10 additions & 8 deletions db/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ func (api *api) updateRow(serviceID string, cells []dbtype.Cell) {
if jLog.IsLevel("DEBUG") {
jLog.Debug(
fmt.Sprintf("%s, %v", sqlStmt, params),
*logFrom, true)
logFrom, true)
}
res, err := api.db.Exec(sqlStmt, params...)
// Query failed
if err != nil {
jLog.Error(
fmt.Sprintf("updateRow UPDATE: %q %v, %s", sqlStmt, params, util.ErrorToString(err)),
*logFrom, true)
logFrom, true)

Check warning on line 76 in db/handlers.go

View check run for this annotation

Codecov / codecov/patch

db/handlers.go#L76

Added line #L76 was not covered by tests
return
}

Expand Down Expand Up @@ -105,12 +105,13 @@ func (api *api) updateRow(serviceID string, cells []dbtype.Cell) {
if jLog.IsLevel("DEBUG") {
jLog.Debug(
fmt.Sprintf("%s, %v", sqlStmt, params),
*logFrom, true)
logFrom, true)
}
_, err = api.db.Exec(sqlStmt, params...)
jLog.Error(
fmt.Sprintf("updateRow INSERT: %q %v, %s", sqlStmt, params, util.ErrorToString(err)),
*logFrom,
fmt.Sprintf("updateRow INSERT: %q %v, %s",
sqlStmt, params, util.ErrorToString(err)),
logFrom,
err != nil)
}
}
Expand All @@ -123,11 +124,12 @@ func (api *api) deleteRow(serviceID string) {
if jLog.IsLevel("DEBUG") {
jLog.Debug(
fmt.Sprintf("%s, %v", sqlStmt, serviceID),
*logFrom, true)
logFrom, true)
}
_, err := api.db.Exec(sqlStmt, serviceID)
jLog.Error(
fmt.Sprintf("deleteRow: %q with %q, %s", sqlStmt, serviceID, util.ErrorToString(err)),
*logFrom,
fmt.Sprintf("deleteRow: %q with %q, %s",
sqlStmt, serviceID, util.ErrorToString(err)),
logFrom,
err != nil)
}
9 changes: 6 additions & 3 deletions db/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestAPI_UpdateRow(t *testing.T) {
cfg := testConfig()
testAPI := api{config: cfg}
*testAPI.config.Settings.Data.DatabaseFile = fmt.Sprintf("%s.db", strings.ReplaceAll(name, " ", "_"))
defer os.Remove(*testAPI.config.Settings.Data.DatabaseFile)
defer os.Remove(*cfg.Settings.Data.DatabaseFile)
testAPI.initialise()

// WHEN updateRow is called targeting single/multiple cells
Expand Down Expand Up @@ -134,8 +134,11 @@ func TestAPI_DeleteRow(t *testing.T) {

// Ensure the row exists if tc.exists
if tc.exists {
testAPI.updateRow(tc.serviceID, []dbtype.Cell{
{Column: "latest_version", Value: "9.9.9"}, {Column: "deployed_version", Value: "8.8.8"}})
testAPI.updateRow(
tc.serviceID,
[]dbtype.Cell{
{Column: "latest_version", Value: "9.9.9"}, {Column: "deployed_version", Value: "8.8.8"}},
)
time.Sleep(100 * time.Millisecond)
}
// Check the row existance before the test
Expand Down
8 changes: 5 additions & 3 deletions db/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ var cfg *config.Config

func TestMain(m *testing.M) {
log := util.NewJLog("DEBUG", false)
logFrom = &util.LogFrom{}
log.Testing = true
databaseFile := "TestRun.db"
LogInit(log, databaseFile)

cfg = testConfig()
*cfg.Settings.Data.DatabaseFile = "TestRun.db"
*cfg.Settings.Data.DatabaseFile = databaseFile
defer os.Remove(*cfg.Settings.Data.DatabaseFile)
go Run(cfg, log)
go Run(cfg)
time.Sleep(250 * time.Millisecond) // Time for db to start

os.Exit(m.Run())
}
Expand Down
55 changes: 26 additions & 29 deletions db/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ import (
"github.com/release-argus/Argus/util"
)

var (
jLog *util.JLog
logFrom *util.LogFrom
)
// LogInit for this package.
func LogInit(log *util.JLog, databaseFile string) {
jLog = log
logFrom = util.LogFrom{Primary: "db", Secondary: databaseFile}
}

func checkFile(path string) {
file := filepath.Base(path)
Expand All @@ -40,34 +41,30 @@ func checkFile(path string) {
// create the dir
if os.IsNotExist(err) {
err = os.MkdirAll(dir, 0755)
jLog.Fatal(util.ErrorToString(err), *logFrom, err != nil)
jLog.Fatal(util.ErrorToString(err), logFrom, err != nil)
} else {
// other error
jLog.Fatal(util.ErrorToString(err), *logFrom, true)
jLog.Fatal(util.ErrorToString(err), logFrom, true)

Check warning on line 47 in db/init.go

View check run for this annotation

Codecov / codecov/patch

db/init.go#L47

Added line #L47 was not covered by tests
}

// directory exists but is not a directory
} else if fileInfo == nil || !fileInfo.IsDir() {
jLog.Fatal(fmt.Sprintf("path %q (for %q) is not a directory", dir, file), *logFrom, true)
jLog.Fatal(fmt.Sprintf("path %q (for %q) is not a directory", dir, file), logFrom, true)
}

// Check that the file exists
fileInfo, err = os.Stat(path)
if err != nil {
// file doesn't exist
jLog.Fatal(util.ErrorToString(err), *logFrom, os.IsExist(err))
jLog.Fatal(util.ErrorToString(err), logFrom, os.IsExist(err))

// item exists but is a directory
} else if fileInfo != nil && fileInfo.IsDir() {
jLog.Fatal(fmt.Sprintf("path %q (for %q) is a directory, not a file", path, file), *logFrom, true)
jLog.Fatal(fmt.Sprintf("path %q (for %q) is a directory, not a file", path, file), logFrom, true)
}
}

func Run(cfg *config.Config, log *util.JLog) {
jLog = log
databaseFile := cfg.Settings.DataDatabaseFile()
logFrom = &util.LogFrom{Primary: "db", Secondary: *databaseFile}

func Run(cfg *config.Config) {
api := api{config: cfg}
api.initialise()
defer api.db.Close()
Expand All @@ -81,9 +78,9 @@ func Run(cfg *config.Config, log *util.JLog) {

func (api *api) initialise() {
databaseFile := api.config.Settings.DataDatabaseFile()
checkFile(*databaseFile)
db, err := sql.Open("sqlite", *databaseFile)
jLog.Fatal(err, *logFrom, err != nil)
checkFile(databaseFile)
db, err := sql.Open("sqlite", databaseFile)
jLog.Fatal(err, logFrom, err != nil)

// Create the table
sqlStmt := `
Expand All @@ -96,7 +93,7 @@ func (api *api) initialise() {
approved_version TEXT DEFAULT ''
);`
_, err = db.Exec(sqlStmt)
jLog.Fatal(util.ErrorToString(err), *logFrom, err != nil)
jLog.Fatal(util.ErrorToString(err), logFrom, err != nil)

updateTable(db)

Expand All @@ -123,7 +120,7 @@ func (api *api) removeUnknownServices() {
_, err := api.db.Exec(sqlStmt, params...)
jLog.Fatal(
fmt.Sprintf("removeUnknownServices: %s", util.ErrorToString(err)),
*logFrom,
logFrom,
err != nil)
}

Expand All @@ -139,7 +136,7 @@ func (api *api) extractServiceStatus() {
deployed_version_timestamp,
approved_version
FROM status;`)
jLog.Fatal(err, *logFrom, err != nil)
jLog.Fatal(err, logFrom, err != nil)
defer rows.Close()

api.config.OrderMutex.RLock()
Expand All @@ -156,7 +153,7 @@ func (api *api) extractServiceStatus() {
err = rows.Scan(&id, &lv, &lvt, &dv, &dvt, &av)
jLog.Fatal(
fmt.Sprintf("extractServiceStatus row: %s", util.ErrorToString(err)),
*logFrom,
logFrom,
err != nil)
api.config.Service[id].Status.SetLatestVersion(lv, false)
api.config.Service[id].Status.SetLatestVersionTimestamp(lvt)
Expand All @@ -167,7 +164,7 @@ func (api *api) extractServiceStatus() {
err = rows.Err()
jLog.Fatal(
fmt.Sprintf("extractServiceStatus: %s", util.ErrorToString(err)),
*logFrom,
logFrom,
err != nil)
}

Expand All @@ -176,12 +173,12 @@ func updateTable(db *sql.DB) {
// Get the type of the *_version columns
var columnType string
err := db.QueryRow("SELECT type FROM pragma_table_info('status') WHERE name = 'latest_version'").Scan(&columnType)
jLog.Fatal(fmt.Sprintf("updateTable: %s", util.ErrorToString(err)), *logFrom, err != nil)
jLog.Fatal(fmt.Sprintf("updateTable: %s", util.ErrorToString(err)), logFrom, err != nil)
// Update if the column type is not TEXT
if columnType != "TEXT" {
jLog.Verbose("Updating column types", *logFrom, true)
jLog.Verbose("Updating column types", logFrom, true)
updateColumnTypes(db)
jLog.Verbose("Finished updating column types", *logFrom, true)
jLog.Verbose("Finished updating column types", logFrom, true)
}
}

Expand All @@ -198,17 +195,17 @@ func updateColumnTypes(db *sql.DB) {
approved_version TEXT DEFAULT ''
);`
_, err := db.Exec(sqlStmt)
jLog.Fatal(fmt.Sprintf("updateColumnTypes - create: %s", util.ErrorToString(err)), *logFrom, err != nil)
jLog.Fatal(fmt.Sprintf("updateColumnTypes - create: %s", util.ErrorToString(err)), logFrom, err != nil)

// Copy the data from the old table to the new table
_, err = db.Exec(`INSERT INTO status_backup SELECT * FROM status;`)
jLog.Fatal(fmt.Sprintf("updateColumnTypes - copy: %s", util.ErrorToString(err)), *logFrom, err != nil)
jLog.Fatal(fmt.Sprintf("updateColumnTypes - copy: %s", util.ErrorToString(err)), logFrom, err != nil)

// Drop the table
_, err = db.Exec("DROP TABLE status;")
jLog.Fatal(fmt.Sprintf("updateColumnTypes - drop: %s", util.ErrorToString(err)), *logFrom, err != nil)
jLog.Fatal(fmt.Sprintf("updateColumnTypes - drop: %s", util.ErrorToString(err)), logFrom, err != nil)

// Rename the new table to the old table
_, err = db.Exec("ALTER TABLE status_backup RENAME TO status;")
jLog.Fatal(fmt.Sprintf("updateColumnTypes - rename: %s", util.ErrorToString(err)), *logFrom, err != nil)
jLog.Fatal(fmt.Sprintf("updateColumnTypes - rename: %s", util.ErrorToString(err)), logFrom, err != nil)
}
14 changes: 7 additions & 7 deletions db/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ func TestDBQueryService(t *testing.T) {
{Column: "latest_version_timestamp", Value: (*svc).Status.LatestVersionTimestamp()},
{Column: "deployed_version", Value: (*svc).Status.DeployedVersion()},
{Column: "deployed_version_timestamp", Value: (*svc).Status.DeployedVersionTimestamp()},
{Column: "approved_version", Value: (*svc).Status.ApprovedVersion()}})
{Column: "approved_version", Value: (*svc).Status.ApprovedVersion()}},
)

// THEN that data can be queried
got := queryRow(t, testAPI.db, serviceName)
Expand Down Expand Up @@ -322,10 +323,8 @@ func TestAPI_extractServiceStatus(t *testing.T) {
*cfg.Settings.Data.DatabaseFile = "TestAPI_extractServiceStatus.db"
defer os.Remove(*cfg.Settings.Data.DatabaseFile)
testAPI := api{config: cfg}
go func() {
testAPI.initialise()
testAPI.handler()
}()
testAPI.initialise()
go testAPI.handler()
wantStatus := make([]svcstatus.Status, len(cfg.Service))
// push a random Status for each Service to the DB
index := 0
Expand Down Expand Up @@ -401,8 +400,9 @@ func Test_UpdateColumnTypes(t *testing.T) {
r, w, _ := os.Pipe()
os.Stdout = w

db, err := sql.Open("sqlite", "Test_UpdateColumnTypes.db")
defer os.Remove("Test_UpdateColumnTypes.db")
databaseFile := "Test_UpdateColumnTypes.db"
db, err := sql.Open("sqlite", databaseFile)
defer os.Remove(databaseFile)
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 6 additions & 0 deletions db/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ import (
"database/sql"

"github.com/release-argus/Argus/config"
"github.com/release-argus/Argus/util"
)

type api struct {
config *config.Config
db *sql.DB
}

var (
jLog *util.JLog
logFrom util.LogFrom
)
18 changes: 11 additions & 7 deletions notifiers/shoutrrr/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,15 +509,19 @@ func (s *Shoutrrr) TestSend(serviceURL string) (err error) {

s.SetOption("max_tries", "1")

testServiceInfo := &util.ServiceInfo{
ID: util.DefaultIfNil(s.ServiceStatus.ServiceID),
URL: serviceURL,
WebURL: util.DefaultIfNil(s.ServiceStatus.WebURL),
LatestVersion: s.ServiceStatus.LatestVersion()}
if testServiceInfo.LatestVersion == "" {
testServiceInfo.LatestVersion = "MAJOR.MINOR.PATCH"
latestVersion := s.ServiceStatus.LatestVersion()
if latestVersion == "" {
latestVersion = "MAJOR.MINOR.PATCH"
}

testServiceInfo := &util.ServiceInfo{
ID: util.DefaultIfNil(s.ServiceStatus.ServiceID),
URL: serviceURL,
WebURL: util.TemplateString(
util.DefaultIfNil(s.ServiceStatus.WebURL),
util.ServiceInfo{LatestVersion: latestVersion}),
LatestVersion: latestVersion}

title := "TEST - " + s.Title(testServiceInfo)
message := "TEST - " + s.Message(testServiceInfo)
err = s.Send(
Expand Down
Loading

0 comments on commit 550d6ce

Please sign in to comment.