From 432e3bda53ca02b9f3eb58163f8459d051f1df20 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Tue, 6 Feb 2024 20:27:19 -0800 Subject: Initial commit. --- sqlr_test.go | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 sqlr_test.go (limited to 'sqlr_test.go') diff --git a/sqlr_test.go b/sqlr_test.go new file mode 100644 index 0000000..4323f11 --- /dev/null +++ b/sqlr_test.go @@ -0,0 +1,158 @@ +package sqlr + +import ( + "context" + "database/sql" + "github.com/google/go-cmp/cmp" + _ "github.com/mattn/go-sqlite3" + "reflect" + "testing" +) + +func TestScan(t *testing.T) { + ctx := context.Background() + + for _, tc := range []struct { + desc string + db string + query string + want any + }{{ + desc: "match field names", + db: ` + CREATE TABLE Tbl (ColA, ColB); + INSERT INTO Tbl VALUES (100, "test")`, + query: "SELECT ColA, ColB FROM Tbl", + want: &struct { + ColA int + ColB string + }{100, "test"}, + }, { + desc: "select star", + db: ` + CREATE TABLE Tbl (ColA, ColB); + INSERT INTO Tbl VALUES (100, "test")`, + query: "SELECT * FROM Tbl", + want: &struct { + ColA int + ColB string + }{100, "test"}, + }, { + desc: "ignored field", + db: ` + CREATE TABLE Tbl (Col); + INSERT INTO Tbl VALUES (100)`, + query: "SELECT Col FROM Tbl", + want: &struct{ Col, OtherField int }{Col: 100}, + }, { + desc: "tag", + db: ` + CREATE TABLE Tbl (col_a, col_b); + INSERT INTO Tbl VALUES (100, "test")`, + query: "SELECT col_a, col_b FROM Tbl", + want: &struct { + ColA int `sql:"col_a"` + ColB string `sql:"col_b"` + }{100, "test"}, + }} { + t.Run(tc.desc, func(t *testing.T) { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + t.Fatalf("Failed to create in-memory database: %s", err) + } + defer db.Close() + if _, err := db.ExecContext(ctx, tc.db); err != nil { + t.Fatalf("Failed to initialize test database: %s", err) + } + + rows, err := db.QueryContext(ctx, tc.query) + if err != nil { + t.Fatalf("Failed to query test database: %s", err) + } + if !rows.Next() { + t.Fatalf("No data") + } + + got := reflect.New(reflect.TypeOf(tc.want).Elem()).Interface() + if err := Scan(rows, got); err != nil { + t.Fatalf("Scan failed: %s", err) + } + if err := rows.Close(); err != nil { + t.Fatalf("Close rows: %s", err) + } + if err := rows.Err(); err != nil { + t.Fatalf("Database read error: %s", err) + } + + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("Scan returned unexpected diff (-want +got):\n%s", diff) + } + }) + } +} + +func TestScan_Errors(t *testing.T) { + ctx := context.Background() + + for _, tc := range []struct { + desc string + db string + query string + out any + }{{ + desc: "wrong type", + db: ` + CREATE TABLE Tbl (Col); + INSERT INTO Tbl VALUES (100)`, + query: "SELECT Col FROM Tbl", + out: 5, + }, { + desc: "nil pointer", + db: ` + CREATE TABLE Tbl (Col); + INSERT INTO Tbl VALUES (100)`, + query: "SELECT Col FROM Tbl", + out: nil, + }, { + desc: "no field", + db: ` + CREATE TABLE Tbl (ColA, ColB); + INSERT INTO Tbl VALUES (100, "test")`, + query: "SELECT ColA, ColB FROM Tbl", + out: new(struct{ ColA int }), + }, { + desc: "ignored field", + db: ` + CREATE TABLE Tbl (Col); + INSERT INTO Tbl VALUES (100)`, + query: "SELECT Col FROM Tbl", + out: new(struct { + Col int `sql:"-"` + }), + }} { + t.Run(tc.desc, func(t *testing.T) { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + t.Fatalf("Failed to create in-memory database: %s", err) + } + defer db.Close() + if _, err := db.ExecContext(ctx, tc.db); err != nil { + t.Fatalf("Failed to initialize test database: %s", err) + } + + rows, err := db.QueryContext(ctx, tc.query) + if err != nil { + t.Fatalf("Failed to query test database: %s", err) + } + defer rows.Close() + if !rows.Next() { + t.Fatalf("No data") + } + + err = Scan(rows, tc.out) + if err == nil { + t.Errorf("Scan returned nil, want error") + } + }) + } +} -- cgit v1.3.1