From fbf6e4fd1b24e3bd82ea230d3359b3697df11602 Mon Sep 17 00:00:00 2001 From: nathandennis Date: Thu, 14 Aug 2025 17:07:33 +0100 Subject: [PATCH 1/5] add TestExecute --- gsdb/Execute_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 gsdb/Execute_test.go diff --git a/gsdb/Execute_test.go b/gsdb/Execute_test.go new file mode 100644 index 0000000..fdc1bf6 --- /dev/null +++ b/gsdb/Execute_test.go @@ -0,0 +1,62 @@ +package gsdb + +import ( + "context" + "log/slog" + "os" + "testing" + "time" +) + +func TestExecute(t *testing.T) { + textHandler := slog.NewTextHandler(os.Stdout, nil) + l := slog.New(textHandler) + NewSQLite3("test.db", l, context.Background()) + + type TestPerson struct { + Id int `db:"column=id primarykey=yes table=Test"` + Name string `db:"column=name"` + Dtadded time.Time `db:"column=dtadded"` + Status int `db:"column=status"` + Ignored int `db:"column=ignored omit=yes"` + } + + tableCreate := ` + CREATE TABLE IF NOT EXISTS test ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + dtadded DATETIME DEFAULT CURRENT_TIMESTAMP, + status INTEGER NOT NULL + );` + DB.Execute("DROP TABLE IF EXISTS test;") + DB.Execute(tableCreate) + + tests := []struct { + name string + entry TestPerson + wantErr bool + }{ + { + name: "Execute an Insert success with all fields", + entry: TestPerson{Name: "Ronald McDonald", Dtadded: time.Now().UTC(), Status: 1}, + }, + { + name: "Execute an Insert with fields missing - current setup will populate missing fields with Go zero values", + entry: TestPerson{Dtadded: time.Now().UTC()}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + insertSQL, err := DB.Insert(tc.entry) + if err != nil { + t.Fatalf("Execute() error: %v, wantErr %v", err, tc.wantErr) + } + + _, _, err = DB.Execute(insertSQL) + if err != nil { + t.Fatalf("Execute() error: %v, wantErr %v", err, tc.wantErr) + } + }) + } +} \ No newline at end of file From 0c7dce85c939cf0dd1f80ae42fc2f7f1768d3258 Mon Sep 17 00:00:00 2001 From: nathandennis Date: Tue, 19 Aug 2025 09:07:22 +0100 Subject: [PATCH 2/5] remove wantErr bool for test struct, update error messages --- gsdb/Execute_test.go | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/gsdb/Execute_test.go b/gsdb/Execute_test.go index fdc1bf6..6359474 100644 --- a/gsdb/Execute_test.go +++ b/gsdb/Execute_test.go @@ -28,21 +28,26 @@ func TestExecute(t *testing.T) { dtadded DATETIME DEFAULT CURRENT_TIMESTAMP, status INTEGER NOT NULL );` - DB.Execute("DROP TABLE IF EXISTS test;") - DB.Execute(tableCreate) + _, _, err := DB.Execute("DROP TABLE IF EXISTS test;") + if err != nil { + t.Fatalf("failed to execute drop table prior to tests: %v", err) + } + _, _, err = DB.Execute(tableCreate) + if err != nil { + t.Fatalf("failed to execute tableCreate SQL prior to tests: %v", err) + } tests := []struct { name string entry TestPerson - wantErr bool }{ { - name: "Execute an Insert success with all fields", - entry: TestPerson{Name: "Ronald McDonald", Dtadded: time.Now().UTC(), Status: 1}, + name: "Execute an Insert success with all fields", + entry: TestPerson{Name: "Ronald McDonald", Dtadded: time.Now().UTC(), Status: 1}, }, { - name: "Execute an Insert with fields missing - current setup will populate missing fields with Go zero values", - entry: TestPerson{Dtadded: time.Now().UTC()}, + name: "Execute an Insert with fields missing - current setup will populate missing fields with Go zero values", + entry: TestPerson{Dtadded: time.Now().UTC()}, }, } @@ -50,13 +55,23 @@ func TestExecute(t *testing.T) { t.Run(tc.name, func(t *testing.T) { insertSQL, err := DB.Insert(tc.entry) if err != nil { - t.Fatalf("Execute() error: %v, wantErr %v", err, tc.wantErr) + t.Fatalf("failed to generate Insert SQL: %v", err) } _, _, err = DB.Execute(insertSQL) if err != nil { - t.Fatalf("Execute() error: %v, wantErr %v", err, tc.wantErr) + t.Fatalf("failed to execute insert during test: %s: %v", tc.name, err) + } + + var queriedName string + err = DB.dbConnection.QueryRowContext( + context.Background(), + `SELECT name FROM test ORDER BY id DESC LIMIT 1`, + ).Scan(&queriedName) + if err != nil { + t.Fatalf("QueryRowContext scan failed in TestExecute: %v", err) } + t.Logf("Fetched name: %q", queriedName) }) } -} \ No newline at end of file +} From 6058cf8c1842fc0e7e33786a8e40c6c5bf9029a3 Mon Sep 17 00:00:00 2001 From: nathandennis Date: Tue, 19 Aug 2025 09:21:07 +0100 Subject: [PATCH 3/5] add lastInsertedID and rowsAffected checks --- gsdb/Execute_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gsdb/Execute_test.go b/gsdb/Execute_test.go index 6359474..e798ff6 100644 --- a/gsdb/Execute_test.go +++ b/gsdb/Execute_test.go @@ -40,14 +40,17 @@ func TestExecute(t *testing.T) { tests := []struct { name string entry TestPerson + expectedLastID int64 }{ { name: "Execute an Insert success with all fields", entry: TestPerson{Name: "Ronald McDonald", Dtadded: time.Now().UTC(), Status: 1}, + expectedLastID: 1, }, { name: "Execute an Insert with fields missing - current setup will populate missing fields with Go zero values", entry: TestPerson{Dtadded: time.Now().UTC()}, + expectedLastID: 2, }, } @@ -58,7 +61,7 @@ func TestExecute(t *testing.T) { t.Fatalf("failed to generate Insert SQL: %v", err) } - _, _, err = DB.Execute(insertSQL) + lastInsertedID, rowsAffected, err := DB.Execute(insertSQL) if err != nil { t.Fatalf("failed to execute insert during test: %s: %v", tc.name, err) } @@ -71,7 +74,10 @@ func TestExecute(t *testing.T) { if err != nil { t.Fatalf("QueryRowContext scan failed in TestExecute: %v", err) } - t.Logf("Fetched name: %q", queriedName) + + if tc.expectedLastID != lastInsertedID || queriedName != tc.entry.Name || rowsAffected != 1 { + t.Fatalf("lastInsertedID does not match expected entry ID: got: %d want: %d", lastInsertedID, tc.expectedLastID) + } }) } } From 081d82b85fd64d4696674268f6191a6bc2915160 Mon Sep 17 00:00:00 2001 From: nathandennis Date: Tue, 19 Aug 2025 09:23:27 +0100 Subject: [PATCH 4/5] change tableCreate and table dropping to dbConnection.Exec --- gsdb/Execute_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gsdb/Execute_test.go b/gsdb/Execute_test.go index e798ff6..9692912 100644 --- a/gsdb/Execute_test.go +++ b/gsdb/Execute_test.go @@ -28,11 +28,13 @@ func TestExecute(t *testing.T) { dtadded DATETIME DEFAULT CURRENT_TIMESTAMP, status INTEGER NOT NULL );` - _, _, err := DB.Execute("DROP TABLE IF EXISTS test;") + + _, err := DB.dbConnection.Exec("DROP TABLE IF EXISTS test;") if err != nil { t.Fatalf("failed to execute drop table prior to tests: %v", err) } - _, _, err = DB.Execute(tableCreate) + + _, err = DB.dbConnection.Exec(tableCreate) if err != nil { t.Fatalf("failed to execute tableCreate SQL prior to tests: %v", err) } From 6cfd5f1da8220a8cbba5675ffa68fa0ac6d35d42 Mon Sep 17 00:00:00 2001 From: nathandennis Date: Tue, 19 Aug 2025 10:08:34 +0100 Subject: [PATCH 5/5] update post execute query to use QuerySingleStruct --- gsdb/Execute_test.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/gsdb/Execute_test.go b/gsdb/Execute_test.go index 9692912..a222bf7 100644 --- a/gsdb/Execute_test.go +++ b/gsdb/Execute_test.go @@ -68,17 +68,25 @@ func TestExecute(t *testing.T) { t.Fatalf("failed to execute insert during test: %s: %v", tc.name, err) } - var queriedName string - err = DB.dbConnection.QueryRowContext( - context.Background(), - `SELECT name FROM test ORDER BY id DESC LIMIT 1`, - ).Scan(&queriedName) + result, err := QuerySingleStruct[TestPerson](` + SELECT name, id FROM test ORDER BY id DESC LIMIT 1; + `) if err != nil { - t.Fatalf("QueryRowContext scan failed in TestExecute: %v", err) + t.Fatalf("QuerySingleStruct error during test: %s - %v", tc.name, err) } - - if tc.expectedLastID != lastInsertedID || queriedName != tc.entry.Name || rowsAffected != 1 { - t.Fatalf("lastInsertedID does not match expected entry ID: got: %d want: %d", lastInsertedID, tc.expectedLastID) + + switch { + case result.Name != tc.entry.Name: + t.Fatalf("queried result name does not match. got: %s want: %s", result.Name, tc.entry.Name) + + case lastInsertedID != tc.expectedLastID: + t.Fatalf("expected last inserted IDs to match. got: %d want: %d", lastInsertedID, tc.expectedLastID) + + case int64(result.Id) != tc.expectedLastID: + t.Fatalf("expected result.Id of %d to match expectedLastID: %d but got: %d", int64(result.Id), tc.expectedLastID, lastInsertedID) + + case rowsAffected != 1: + t.Fatalf("expected only 1 rowsAffected but got %d", rowsAffected) } }) }