From 923b77a1e6888ad15be2b389a74fbddbe7ca1b53 Mon Sep 17 00:00:00 2001 From: Mohamed Labiadh <47183211+medlabib@users.noreply.github.com> Date: Thu, 5 Nov 2026 01:06:36 +0100 Subject: [PATCH 1/4] test(dbkit/sqlite): build the options tests on 32-bit systems The 'a cache size past 32 bits' row assigned math.MaxInt32 + 1 to an int, which does not compile where int is 32 bits wide. The row is now added only when strconv.IntSize == 64 and builds its value from an int64 variable, so the row still runs on 64-bit targets. Signed-off-by: Mohamed Labiadh <47183211+medlabib@users.noreply.github.com> --- dbkit/sqlite/options_test.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/dbkit/sqlite/options_test.go b/dbkit/sqlite/options_test.go index 47cd6f7..e38a795 100644 --- a/dbkit/sqlite/options_test.go +++ b/dbkit/sqlite/options_test.go @@ -7,6 +7,7 @@ import ( "math" "os" "path/filepath" + "strconv" "testing" "time" @@ -60,14 +61,17 @@ func limitOf(n int64) *int64 { return &n } +// badOptionCase is one Options value sqlite.Open must refuse. +type badOptionCase struct { + name string + change func(*sqlite.Options) + want string +} + func TestOpenRefusesABadOption(t *testing.T) { t.Parallel() - cases := []struct { - name string - change func(*sqlite.Options) - want string - }{ + cases := []badOptionCase{ {"a missing busy timeout", func(o *sqlite.Options) { o.BusyTimeout = 0 }, "dbkit: the option BusyTimeout must be 1ms or more, got 0s"}, {"a negative busy timeout", func(o *sqlite.Options) { o.BusyTimeout = -time.Millisecond }, @@ -98,8 +102,6 @@ func TestOpenRefusesABadOption(t *testing.T) { "dbkit: the option CacheSize must stand above zero, got 0"}, {"a negative cache size", func(o *sqlite.Options) { o.CacheSize = -1 }, "dbkit: the option CacheSize must stand above zero, got -1"}, - {"a cache size past 32 bits", func(o *sqlite.Options) { o.CacheSize = math.MaxInt32 + 1 }, - "dbkit: the option CacheSize must be 2147483647 or less, got 2147483648"}, {"a missing connection cap", func(o *sqlite.Options) { o.MaxConns = 0 }, "dbkit: the option MaxConns must be 2 or more, got 0"}, {"a negative connection cap", func(o *sqlite.Options) { o.MaxConns = -2 }, @@ -119,6 +121,18 @@ func TestOpenRefusesABadOption(t *testing.T) { {"a base folder with a question mark", func(o *sqlite.Options) { o.BaseFolder = "/srv/a?b" }, `dbkit: the option BaseFolder must hold no ?, got "/srv/a?b"`}, } + + // A cache size past 32 bits fits an int only where int is 64 bits wide; + // on 32-bit platforms the constant would not compile, so skip the row there. + if strconv.IntSize == 64 { + past32 := int64(math.MaxInt32) + 1 + cases = append(cases, badOptionCase{ + name: "a cache size past 32 bits", + change: func(o *sqlite.Options) { o.CacheSize = int(past32) }, + want: "dbkit: the option CacheSize must be 2147483647 or less, got 2147483648", + }) + } + for _, c := range cases { t.Run(c.name, func(t *testing.T) { t.Parallel() From 7323e58737c1bad8f31f72dfdff991ed789dfeb7 Mon Sep 17 00:00:00 2001 From: SirLouen Date: Sat, 7 Nov 2026 23:31:38 +0100 Subject: [PATCH 2/4] test(dbkit/sqlite): name and document the options case, drop the guard comment --- dbkit/sqlite/options_test.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/dbkit/sqlite/options_test.go b/dbkit/sqlite/options_test.go index e38a795..c0f5f1e 100644 --- a/dbkit/sqlite/options_test.go +++ b/dbkit/sqlite/options_test.go @@ -61,17 +61,20 @@ func limitOf(n int64) *int64 { return &n } -// badOptionCase is one Options value sqlite.Open must refuse. -type badOptionCase struct { - name string +// optionsCase is one bad change to valid options and the error Open returns. +type optionsCase struct { + // name names the case. + name string + // change makes the one bad change to valid options. change func(*sqlite.Options) - want string + // want is the error Open returns. + want string } func TestOpenRefusesABadOption(t *testing.T) { t.Parallel() - cases := []badOptionCase{ + cases := []optionsCase{ {"a missing busy timeout", func(o *sqlite.Options) { o.BusyTimeout = 0 }, "dbkit: the option BusyTimeout must be 1ms or more, got 0s"}, {"a negative busy timeout", func(o *sqlite.Options) { o.BusyTimeout = -time.Millisecond }, @@ -122,11 +125,9 @@ func TestOpenRefusesABadOption(t *testing.T) { `dbkit: the option BaseFolder must hold no ?, got "/srv/a?b"`}, } - // A cache size past 32 bits fits an int only where int is 64 bits wide; - // on 32-bit platforms the constant would not compile, so skip the row there. if strconv.IntSize == 64 { past32 := int64(math.MaxInt32) + 1 - cases = append(cases, badOptionCase{ + cases = append(cases, optionsCase{ name: "a cache size past 32 bits", change: func(o *sqlite.Options) { o.CacheSize = int(past32) }, want: "dbkit: the option CacheSize must be 2147483647 or less, got 2147483648", From f8b8baea78ec26c7abbee829abf3be598003df13 Mon Sep 17 00:00:00 2001 From: SirLouen Date: Sat, 7 Nov 2026 23:31:38 +0100 Subject: [PATCH 3/4] test(dbkit/postgres): build the open tests on 32-bit systems --- dbkit/postgres/open_test.go | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/dbkit/postgres/open_test.go b/dbkit/postgres/open_test.go index dcd43e4..ef510c7 100644 --- a/dbkit/postgres/open_test.go +++ b/dbkit/postgres/open_test.go @@ -13,6 +13,7 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "testing" "time" @@ -240,20 +241,34 @@ func openFreshHandle(t *testing.T, maxConns int) *postgres.Handle { return mustOpen(t, openFresh(t), maxConns) } +// openCapCase is one connection cap Open refuses and the error it returns. +type openCapCase struct { + // name names the case. + name string + // maxConns is the connection cap Open is given. + maxConns int + // want is the error Open returns. + want string +} + func TestOpenRefusesABadOption(t *testing.T) { t.Parallel() - cases := []struct { - name string - maxConns int - want string - }{ + cases := []openCapCase{ {"a missing connection cap", 0, "dbkit: the option MaxConns must be 2 or more, got 0"}, {"a connection cap of one", 1, "dbkit: the option MaxConns must be 2 or more, got 1"}, {"a negative connection cap", -1, "dbkit: the option MaxConns must be 2 or more, got -1"}, - {"a connection cap past 32 bits", math.MaxInt32 + 1, - "dbkit: the option MaxConns must be 2147483647 or less, got 2147483648"}, } + + if strconv.IntSize == 64 { + past32 := int64(math.MaxInt32) + 1 + cases = append(cases, openCapCase{ + name: "a connection cap past 32 bits", + maxConns: int(past32), + want: "dbkit: the option MaxConns must be 2147483647 or less, got 2147483648", + }) + } + for _, c := range cases { t.Run(c.name, func(t *testing.T) { t.Parallel() From 52473abe44a4b983ac947e4d8fb145357cab1558 Mon Sep 17 00:00:00 2001 From: SirLouen Date: Sat, 7 Nov 2026 23:31:39 +0100 Subject: [PATCH 4/4] feat(ci): vet every module for 32-bit Linux --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 705a1c8..c579fbc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,7 @@ jobs: ${{ matrix.module }}/go.sum - run: go test -race -covermode=atomic -coverprofile=cover.out ./... - run: go vet ./... + - run: GOOS=linux GOARCH=386 go vet ./... && GOOS=linux GOARCH=arm go vet ./... - if: matrix.module == 'dbkit/sqlite' || matrix.module == 'gonsole/auth/sqlite' || matrix.module == 'gonsole' run: GOOS=darwin GOARCH=arm64 go vet ./... && GOOS=windows GOARCH=amd64 go vet ./... @@ -68,6 +69,7 @@ jobs: ${{ matrix.module }}/go.sum - run: go test -race -covermode=atomic -coverprofile=cover.out ./... - run: go vet ./... + - run: GOOS=linux GOARCH=386 go vet ./... && GOOS=linux GOARCH=arm go vet ./... gottext: runs-on: ubuntu-latest