Files
goclaw/cmd/migrate_test.go
viettranx 935b58b7a3 fix(migrate): RFC 8089-compliant file:// URL for Windows paths
golang-migrate's file source driver parsed "file://F:\\project\\..."
with "F" as host and ":\\..." as port → "invalid port" error, so
upgrade/migrate commands crashed on Windows before applying any SQL.

Format the source URL per RFC 8089: forward-slash separators and a
leading "/" before the drive letter → "file:///F:/project/...".
POSIX paths pass through unchanged (leading "/" already present).

Shape-driven, not OS-driven: no runtime.GOOS branch needed, which
also lets the unit test cover both shapes on a single runner.

Closes #872
2026-04-18 16:55:08 +07:00

43 lines
1.3 KiB
Go

package cmd
import (
"path/filepath"
"strings"
"testing"
)
func TestAbsoluteToFileURI(t *testing.T) {
cases := []struct {
name string
in string
want string
}{
{"posix absolute", "/app/migrations", "file:///app/migrations"},
// Windows drive-letter path with backslashes: the exact shape
// golang-migrate needs. Before the fix, "file://F:\\..." was parsed
// with "F" as host and ":\\..." as port → "invalid port" error.
{"windows backslash", `F:\project\goclaw\migrations`, "file:///F:/project/goclaw/migrations"},
{"windows mixed separators", `C:/already/forward`, "file:///C:/already/forward"},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
if got := absoluteToFileURI(c.in); got != c.want {
t.Errorf("got %q, want %q", got, c.want)
}
})
}
}
// TestMigrationsSourceURLRelative verifies the helper resolves a relative
// input via filepath.Abs before formatting — exact output depends on CWD,
// so we only assert invariants that must hold on every runner.
func TestMigrationsSourceURLRelative(t *testing.T) {
got := migrationsSourceURL("migrations")
if !strings.HasPrefix(got, "file://") {
t.Fatalf("missing file:// prefix: %q", got)
}
if !strings.Contains(filepath.ToSlash(got), "/migrations") {
t.Errorf("missing /migrations segment: %q", got)
}
}