From fa05d57bc0fd8bdc2f1f0d85db299cd43abb1724 Mon Sep 17 00:00:00 2001 From: Kyle Simukka Date: Thu, 6 Nov 2025 18:44:00 +0100 Subject: [PATCH 1/2] Updated testing environment. --- Makefile | 2 ++ docker-compose.test.yml | 27 ++++++++++++++++++--------- dockerfile.test | 6 ++++++ 3 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 Makefile create mode 100644 dockerfile.test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1bfea7f --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + docker compose --progress plain -f docker-compose.test.yml run test \ No newline at end of file diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 94da3ec..56f4fc3 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -1,15 +1,24 @@ services: - # - # mssql - # mssql: image: mcr.microsoft.com/mssql/server:latest - - hostname: mssql - container_name: mssql - network_mode: bridge - ports: - - "1433:1433" + networks: + - mssql environment: ACCEPT_EULA: "Y" SA_PASSWORD: VippsPw1 + healthcheck: + test: ["CMD", "/opt/mssql-tools18/bin/sqlcmd", "-C", "-Usa", "-PVippsPw1", "-Q", "select 1"] + interval: 1s + retries: 20 + test: + build: + dockerfile: dockerfile.test + networks: + - mssql + environment: + SQLSERVER_DSN: sqlserver://mssql:1433?database=master&user id=sa&password=VippsPw1 + depends_on: + mssql: + condition: service_healthy +networks: + mssql: diff --git a/dockerfile.test b/dockerfile.test new file mode 100644 index 0000000..9313912 --- /dev/null +++ b/dockerfile.test @@ -0,0 +1,6 @@ +FROM golang:1.23 AS builder +WORKDIR /sqlcode +ENV GODEBUG="x509negativeserial=1" +COPY . . +RUN go mod tidy +CMD ["go", "test", "-v", "$(go list ./... | grep -v './example')"] \ No newline at end of file From 351a6dcb5fe01e5717768fd02c284fda3845b33d Mon Sep 17 00:00:00 2001 From: Kyle Simukka Date: Thu, 6 Nov 2025 19:46:56 +0100 Subject: [PATCH 2/2] Working connection. --- Makefile | 5 +- ...mpose.test.yml => docker-compose.mssql.yml | 1 + docker-compose.pgsql.yml | 27 ++++++ dockerfile.test | 2 +- go.mod | 1 + go.sum | 2 + sqlcode.yaml | 6 +- sqltest/fixture.go | 93 ++++++++++++++----- 8 files changed, 108 insertions(+), 29 deletions(-) rename docker-compose.test.yml => docker-compose.mssql.yml (94%) create mode 100644 docker-compose.pgsql.yml diff --git a/Makefile b/Makefile index 1bfea7f..f6980da 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ test: - docker compose --progress plain -f docker-compose.test.yml run test \ No newline at end of file + docker compose --progress plain -f docker-compose.mssql.yml run test + +test_pgsql: + docker compose --progress plain -f docker-compose.pgsql.yml run test \ No newline at end of file diff --git a/docker-compose.test.yml b/docker-compose.mssql.yml similarity index 94% rename from docker-compose.test.yml rename to docker-compose.mssql.yml index 56f4fc3..84618fc 100644 --- a/docker-compose.test.yml +++ b/docker-compose.mssql.yml @@ -17,6 +17,7 @@ services: - mssql environment: SQLSERVER_DSN: sqlserver://mssql:1433?database=master&user id=sa&password=VippsPw1 + SQLSERVER_DRIVER: sqlserver depends_on: mssql: condition: service_healthy diff --git a/docker-compose.pgsql.yml b/docker-compose.pgsql.yml new file mode 100644 index 0000000..6391e0c --- /dev/null +++ b/docker-compose.pgsql.yml @@ -0,0 +1,27 @@ +services: + postgres: + image: postgres + networks: + - postgres + environment: + POSTGRES_PASSWORD: VippsPw1 + POSTGRES_USER: sa + POSTGRES_DB: master + healthcheck: + test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"] + interval: 1s + retries: 20 + test: + build: + dockerfile: dockerfile.test + networks: + - postgres + environment: + SQLSERVER_DSN: postgresql://sa:VippsPw1@postgres:5432/master?sslmode=disable + SQLSERVER_DRIVER: postgres + GODEBUG: "x509negativeserial=1" + depends_on: + postgres: + condition: service_healthy +networks: + postgres: diff --git a/dockerfile.test b/dockerfile.test index 9313912..f4a199f 100644 --- a/dockerfile.test +++ b/dockerfile.test @@ -1,4 +1,4 @@ -FROM golang:1.23 AS builder +FROM golang:1.25.1 AS builder WORKDIR /sqlcode ENV GODEBUG="x509negativeserial=1" COPY . . diff --git a/go.mod b/go.mod index fa5e2c6..65a2812 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.9 // indirect diff --git a/go.sum b/go.sum index d0ecd83..6433e10 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= diff --git a/sqlcode.yaml b/sqlcode.yaml index 549c23f..8adefb7 100644 --- a/sqlcode.yaml +++ b/sqlcode.yaml @@ -1,6 +1,8 @@ databases: - localtest: - connection: sqlserver://localhost:1433?database=foo&user id=foouser&password=FooPasswd1 + mssql: + connection: sqlserver://mssql:1433?database=foo&user id=foouser&password=FooPasswd1 + pgsql: + connection: postgresql://sa:VippsPw1@postgres:5432/master?sslmode=disable # One option is to list other paths to include ('dependencies') here. diff --git a/sqltest/fixture.go b/sqltest/fixture.go index 0059908..8c86651 100644 --- a/sqltest/fixture.go +++ b/sqltest/fixture.go @@ -3,14 +3,17 @@ package sqltest import ( "context" "database/sql" + "database/sql/driver" "fmt" - mssql "github.com/denisenkom/go-mssqldb" - "github.com/denisenkom/go-mssqldb/msdsn" - "github.com/gofrs/uuid" "io/ioutil" "os" "strings" "time" + + mssql "github.com/denisenkom/go-mssqldb" + "github.com/denisenkom/go-mssqldb/msdsn" + "github.com/gofrs/uuid" + pgsql "github.com/lib/pq" ) type StdoutLogger struct { @@ -30,6 +33,20 @@ type Fixture struct { DB *sql.DB DBName string adminDB *sql.DB + Driver driver.Driver +} + +func (f *Fixture) Quote(value string) string { + var ms mssql.Driver + var pg pgsql.Driver + + if f.Driver == &ms { + return fmt.Sprintf("[%s]", value) + } + if f.Driver == &pg { + return fmt.Sprintf(`"%s"`, value) + } + return value } func NewFixture() *Fixture { @@ -39,44 +56,70 @@ func NewFixture() *Fixture { defer cancel() dsn := os.Getenv("SQLSERVER_DSN") - if dsn == "" { + if len(dsn) == 0 { panic("Must set SQLSERVER_DSN to run tests") } - dsn = dsn + "&log=3" - mssql.SetLogger(StdoutLogger{}) + driver := os.Getenv("SQLSERVER_DRIVER") + if len(driver) == 0 { + panic("Must set SQLSERVER_DRIVER to run tests") + } + + switch driver { + case "sqlserver": + // set the logging level + dsn = dsn + "&log=3" + mssql.SetLogger(StdoutLogger{}) + case "postgres": + break + } var err error - fixture.adminDB, err = sql.Open("sqlserver", dsn) + fixture.adminDB, err = sql.Open(driver, dsn) if err != nil { panic(err) } - fixture.DBName = strings.ReplaceAll(uuid.Must(uuid.NewV4()).String(), "-", "") + // store a reference to the type of sql driver + fixture.Driver = fixture.adminDB.Driver() - _, err = fixture.adminDB.ExecContext(ctx, fmt.Sprintf(`create database [%s]`, fixture.DBName)) - if err != nil { - panic(err) - } - // These settings are just to get "worst-case" for our tests, since snapshot could interfer - _, err = fixture.adminDB.ExecContext(ctx, fmt.Sprintf(`alter database [%s] set allow_snapshot_isolation on`, fixture.DBName)) - if err != nil { - panic(err) - } - _, err = fixture.adminDB.ExecContext(ctx, fmt.Sprintf(`alter database [%s] set read_committed_snapshot on`, fixture.DBName)) + fixture.DBName = strings.ReplaceAll(uuid.Must(uuid.NewV4()).String(), "-", "") + dbname := fixture.Quote(fixture.DBName) + _, err = fixture.adminDB.ExecContext(ctx, fmt.Sprintf(`create database %s`, dbname)) if err != nil { + fmt.Printf("Failed to create the database: %s for the %s driver\n", dbname, driver) panic(err) } - pdsn, _, err := msdsn.Parse(dsn) - if err != nil { - panic(err) + if driver == "sqlserver" { + // These settings are just to get "worst-case" for our tests, since snapshot could interfer + _, err = fixture.adminDB.ExecContext(ctx, fmt.Sprintf(`alter database %s set allow_snapshot_isolation on`, dbname)) + if err != nil { + panic(err) + } + _, err = fixture.adminDB.ExecContext(ctx, fmt.Sprintf(`alter database %s set read_committed_snapshot on`, dbname)) + if err != nil { + panic(err) + } + + pdsn, _, err := msdsn.Parse(dsn) + if err != nil { + panic(err) + } + pdsn.Database = fixture.DBName + + fixture.DB, err = sql.Open(driver, pdsn.URL().String()) + if err != nil { + panic(err) + } } - pdsn.Database = fixture.DBName - fixture.DB, err = sql.Open("sqlserver", pdsn.URL().String()) - if err != nil { - panic(err) + if driver == "postgres" { + // TODO + fixture.DB, err = sql.Open(driver, strings.ReplaceAll(dsn, "/master", "/"+fixture.DBName)) + if err != nil { + panic(err) + } } return &fixture